原理 #
CSRF(Cross-site request forgery),也被称为:one click attack/session riding,中文名称:跨站请求伪造,缩写为:CSRF/XSRF)跨站请求伪造。
一般来说,攻击者通过伪造用户浏览器的请求,向访问一个用户自己曾经认证访问过的网站发送出去,使目标网站接收并误以为是用户的真实操作而去执行命令。常用于盗取账号、转账、发送虚假消息等。攻击者利用网站对请求的验证漏洞而实现这样的攻击行为,网站能够确认请求来源于用户的浏览器,却不能验证请求是否源于用户的真实意愿下的操作行为。
直白点说就是攻击者盗用了用户的身份,以用户的名义发送恶意的请求。CSRF是一种依赖于Web浏览器的、被混淆过的代理人攻击,往往涉及到个人隐私泄漏以及财产安全。

要完成一次CSRF攻击,受害者必须依次完成两个步骤:
- 登录受信任网站A,并在本地生成Cookie。
- 在不退出A的情况下,访问危险网站B。
但如果不满足以上两个条件中的任何一个,就不会受到CSRF的攻击吗?是的,确实如此,但不能保证以下情况不会发生:
- 不能保证登录了一个网站后,不再打开一个页面并访问另外的网站。
- 不能保证关闭浏览器了后,本地的Cookie立刻过期、上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了……)。
- 上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
分类 #
- 从数据包的角度可以分为GET型和POST型;
- 从利用角度可以分为:
a .对后台管理员进行攻击,比如,诱骗管理员点击修改管理员密码、添加管理员等;
b. 修改普通用户账户和数据,比如,修改个人资料、手机绑定、收货地址等;
c. 账户劫持,比如,修改密码等;
d. 结合其他类型漏洞进行利用,比如,selfxss+CSRF可以打组合拳进行攻击;
e. CSRF蠕虫,比如,很多“点我链接发微博”、“点我链接改信息”等。
限制绕过 #
某些站点在测试时,发现其存在Referer验证。这时就需要通过绕过“判断Referer是否有某域名”才可以触发。以下是总结CSRF中的Referer验证的绕过方法:
referer绕过 #
1. 判断Referer为空的情况
跨协议间提交请求。可以利用常见的协议:ftp://、http://、https://、file://、javascript:、data:等。
最简单的情况就是在本地打开一个HTML页面,这时浏览器地址栏是file://开头的,若这个HTMl页面向任何HTTP站点提交请求的话,这些请求的Referer都是空的。所以可以利用data:协议来构造一个自动提交的CSRF攻击,若使用的是IE浏览器,可以使用javascript:。
加入http://a.b.com/d这个接口存在空Referer绕过的CSRF,可以构造如下POC:
<html> <body> <iframe src="data:text/html;base64,PGZvcm0gbWV0aG9kPXBvc3QgYWN0aW9uPWh0dHA6Ly9hLmIuY29tL2Q+PGlucHV0IHR5cGU9dGV4dCBuYW1lPSdpZCcgdmFsdWU9JzEyMycvPjwvZm9ybT48c2NyaXB0PmRvY3VtZW50LmZvcm1zWzBdLnN1Ym1pdCgpOzwvc2NyaXB0Pg=="> </doby> </html>
上面iframe的src的代码其实是(利用base解码即可):
<form method=post action=http://a.b.com/d><input type=text name='id' value='123'/></form><script>document.forms[0].submit();</script>
自动提交表单到有缺陷的CGI。
1.判断Referer是某域的情况
如果要找的CSRF是 xxx.com,验证的Referer是*.xx.com,可以找个二级域名,<img "csrf地址"="">,之后再把文章地址发出去,就可以进行伪造。如下:
Referfer:https://www.evil.com 修改为: Referfer:https://img.evil.com
2.判断Referer是否有某域名
比如,判断了Referer开头是否以google.com以及google子域名,不验证根域名为google.com,就可以构造子域名x.google.com.xxx.com作为蠕虫传播的载体服务器,即可绕过。如下:
Referer: http://member.xxx.com 修改为: Referer: http://member.xxx.com.evil.com
3.判断Referer是否存在某关键词
比如判断Referer是否存在google.com这个关键词。
可在网站新建一个google.com目录,把CSRF存放在google.com目录即可。如下:
Referer:https://www.google.com/xxx.jsp 修改为: Referer:https://www.evil.com/www.google.com/xxx.jsp Referer:https://www.evil.com/www.google.com/xxx.jsp.php
token绕过 #
** token无效验证**
服务端没有校验token,直接将URL中的token去掉。另外,部分模块有token校验,有些模块却没有token,去寻找没有校验的;
** 利用XSS漏洞绕过CSRF防御**
存在XSS的情况下,使用ajax来跨域获取DOM节点中的Token字段,进行构造;
token固定不变
token规则过于简单,比如根据某个用户ID做了单向hash获得的,可以直接去构造;
** token泄漏**
token的表数据泄漏,或者算法泄漏,程序逻辑不严谨导致的安全隐患。
测试过程 #
- 对目标系统敏感部位进行抓包分析。
比如修改信息、转账、添加信息等。通常一个数据包HTTP请求头中会有一个Referer,这个需要特别去验证。比如,放入BurpSuite Repeater中去测试,先去掉Referer,看看响应包是否有变化。如果没有变化就意味着服务器端未对Referer进行验证。
- 查看数据包是否存在类似CSRF token的字段。
常见的参数有:CSRF、token、sid等等,而且一般来说这些字段的值都是随机字符串。如果没有的话就排除CSRF Token的验证,进行下一步。
- 很多时候通过以上两步就可以断定系统是存在CSRF漏洞的,不过还有一个很隐蔽的地方。
某些操作对数据包的提交采用Ajax的情况下,存在一种情况:数据包HTTP请求头会自定义一个字段,这时就像存在Referer的情况一样,没办法CSRF了。
测试案例1 #
- 登录网站,访问修改账户资料界面。

- 使用BurpSuite构建POC

- 根据表单值构建POC,生成HTML文件(使用Unicode编码,不要用记事本编写)

- 在受害者没有退出页面的情况下,诱骗受害者打开链接并点击按钮

- 成功修改。

测试案例2 #
截取数据包,将请求报文中Referer的值改为百度的地址,再重放数据包,可看见右侧正常返回响应报文,证明系统未对请求包中的Referer值做校验,如下图所示:

测试案例3 #
- 访问存在CSRF漏洞的网站。

- 抓包可以看到Referer字段
- 新打开一个页面,点击访问此链接http://127.0.0.1/vulnerabilities/csrf/?password_new=abc&password_conf=abc&Change=Change#,进行抓包。
查看请求包数据发现通过直接点击此链接的方式打开网页,请求包中并没有Referer字段,所以修改密码不成功。

- 自己增加Referer字段,字段值包含主机头127.0.0.1即可。

- 放包,密码修改成功
