DVWA CSRF 跨站请求伪造通关教程
漏洞简介
CSRF,全称 Cross-Site Request Forgery,跨站请求伪造。简单说就是攻击者伪造一个请求,诱导已经登录的用户去点,然后用户不知不觉就帮攻击者干了一些事,比如改密码、转账之类的。
原理就是浏览器会自动带上 Cookie,所以只要用户登录了,请求发出去就带着身份信息,服务器分辨不出这是不是用户真的想做的操作。
这关的目标是通过 CSRF 修改用户密码。
Low 级别
看代码:
1 | $pass_new = $_GET[ 'password_new' ]; |
GET 请求直接改密码,啥防护都没有。
攻击方法
正常改密码的请求长这样:
1 | http://localhost:3892/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change# |
那我伪造一个:
1 | http://localhost:3892/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change# |
做个钓鱼页面:
1 |
|
用户访问这个页面的瞬间,img 标签就会发送请求,密码就被改成 hacked 了。用户完全不知道发生了什么。
试一下用新密码登录,成功!
Medium 级别
Medium 加了 Referer 检验:
1 | if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) { |
它检查请求头里的 Referer 是否包含服务器域名,比如 localhost。
绕过方法
问题在于它只是检查包含,那我把我钓鱼页面的路径里加上 localhost 不就行了?
比如文件名叫 localhost.html,或者放在 localhost 目录下。这样 Referer 里就会有 localhost 这个字符串,校验就过了。
1 |
|
这验证写得也太随意了。
High 级别
High 加了 CSRF Token:
1 | checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); |
每次请求都要带个有效 Token,攻击者不知道 Token 就没法伪造请求了。
攻击方法
单纯的 CSRF 搞不定了,得配合 XSS 才行。如果有 XSS 漏洞,就能用 JavaScript 去获取页面里的 Token:
1 | var token = document.getElementsByName('user_token')[0].value; |
然后构造攻击页面:
1 |
|
不过这个受同源策略限制,实际场景得看具体情况,这里主要是演示思路。
Impossible 级别
Impossible 级别是真安全:
1 | checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); |
改用 POST 了,还强制验证 Token,密码强度也有要求。这才是正确的防护姿势。
小结
CSRF 防护要点:
- 敏感操作一定要用 CSRF Token
- 尽量用 POST,别用 GET
- Cookie 设置 SameSite 属性
- 重要操作要求二次确认
- Referer 校验可以加,但别只指望它