Web十大漏洞原理与解决方案
— 只有想不到的事,没有做不到的事—
理论
什么是CSRF?
CSRF(Cross-Site Request Forgery),也被称为 one-click attack 或者 session riding,即跨站请求伪造攻击
。
那么 CSRF 到底能够干嘛呢?CSRF是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。可以简单的理解为:攻击者可以盗用你的登陆信息,以你的身份模拟发送各种请求
对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。攻击者只要借助少许的社会工程学的诡计,例如通过 QQ 等聊天软件发送的链接(有些还伪装成短域名,用户无法分辨),攻击者就能迫使 Web 应用的用户去执行攻击者预设的操作。
案例《小明的悲惨遭遇》
这一天,小明同学百无聊赖地刷着Gmail邮件。大部分都是没营养的通知、验证码、聊天记录之类。但有一封邮件引起了小明的注意:
甩卖比特币,一个只要998!!
聪明的小明当然知道这种肯定是骗子,但还是抱着好奇的态度点了进去(请勿模仿)。果然,这只是一个什么都没有的空白页面,小明失望的关闭了页面。一切似乎什么都没有发生……
在这平静的外表之下,黑客的攻击已然得手。小明的Gmail中,被偷偷设置了一个过滤规则,这个规则使得所有的邮件都会被自动转发到hacker@hackermail.com。小明还在继续刷着邮件,殊不知他的邮件正在一封封地,如脱缰的野马一般地,持续不断地向着黑客的邮箱转发而去。
不久之后的一天,小明发现自己的域名已经被转让了。懵懂的小明以为是域名到期自己忘了续费,直到有一天,对方开出了 $650≈4700人民币的赎回价码,小明才开始觉得不太对劲。小明仔细查了下域名的转让,对方是拥有自己的验证码的,而域名的验证码只存在于自己的邮箱里面。小明回想起那天奇怪的链接,打开后重新查看了“空白页”的源码:
<form method="POST" action="https://mail.google.com/mail/h/ewt1jmuj4ddv/?v=prf" enctype="multipart/form-data">
<input type="hidden" name="cf2_emc" value="true"/>
<input type="hidden" name="cf2_email" value="hacker@hakermail.com"/>
.....
<input type="hidden" name="irf" value="on"/>
<input type="hidden" name="nvp_bu_cftb" value="Create Filter"/>
</form>
<script>
document.forms[0].submit();
</script>
这个页面只要打开,就会向Gmail发送一个post请求。请求中,执行了“Create Filter”命令,将所有的邮件,转发到“hacker@hackermail.com”。
小明由于刚刚就登陆了Gmail,所以这个请求发送时,携带着小明的登录凭证(Cookie),Gmail的后台接收到请求,验证了确实有小明的登录凭证,于是成功给小明配置了过滤器。
黑客可以查看小明的所有邮件,包括邮件里的域名验证码等隐私信息。拿到验证码之后,黑客就可以要求域名服务商把域名重置给自己。
小明很快打开Gmail,找到了那条过滤器,将其删除。然而,已经泄露的邮件,已经被转让的域名,再也无法挽回了……
以上就是小明的悲惨遭遇。而“点开一个黑客的链接,所有邮件都被窃取”这种事情并不是杜撰的,此事件原型是《2007年Gmail的CSRF漏洞》
CSRF原理
- • 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
- • 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
- • 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
- • 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
- • 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
CSRF的攻击条件有哪些?
- 1. 用户已经登录了站点A,本地存储了cookie信息,且cookie信息没有过期。
- 2. 用户再没有退出站点A登录的情况(cookie生效的时候),访问了恶意攻击者提供的引诱危险站点B,而B站点通过这些cookle信息去访问站点A。
- 3. 目标网站没有做任何的CSRF防御措施。
CSRF的防御方法
一、如何判定是否存在CSRF漏洞?
1.Referer
:去掉Referer
后重新提交,如果该提交有效,则判定该该网站存在CSRF漏洞
。
2.工具:CSRFTester
,CSRF Request Builder
,BurpSuite
等
二、防御CSRF攻击
1.验证 HTTP Referer / Origin
字段。
2.CSRF Token。
3.判定是否是当前用户进行操作:比如修改密码时,获取当前用户密码,验证码等。
4.正确使用 GET,POST 请求和 cookie;
5. 双重Cookie验证
6.Samesite Cookie属性
防止CSRF攻击的办法已经有上面的预防措施。为了从源头上解决这个问题,Google起草了一份草案来改进HTTP协议,那就是为Set-Cookie响应头新增Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”,同站Cookie只能作为第一方Cookie,不能作为第三方Cookie,Samesite 有两个属性值,分别是 Strict 和 Lax,下面分别讲解:
Samesite=Strict
这种称为严格模式,表明这个 Cookie 在任何情况下都不可能作为第三方 Cookie,绝无例外。比如说 http://b.com 设置了如下 Cookie:
Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3
我们在 http://a.com 下发起对 http://b.com 的任意请求,foo 这个 Cookie 都不会被包含在 Cookie 请求头中,但 bar 会。举个实际的例子就是,假如淘宝网站用来识别用户登录与否的 Cookie 被设置成了
Samesite=Strict
,那么用户从百度搜索页面甚至天猫页面的链接点击进入淘宝后,淘宝都不会是登录状态
,因为淘宝的服务器不会接受到那个 Cookie,其它网站发起的对淘宝的任意请求都不会带上那个 Cookie。
Samesite=Lax
这种称为宽松模式,
比 Strict 放宽了点限制
:假如这个请求是这种请求(改变了当前页面或者打开了新页面)且同时是个GET请求,则这个Cookie可以作为第三方Cookie。比如说 b.com设置了如下Cookie:
Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3
当用户从 http://a.com 点击链接进入 http://b.com 时,foo 这个 Cookie 不会被包含在 Cookie 请求头中,但 bar 和 baz 会,也就是说用户在不同网站之间通过链接跳转是不受影响了。但假如这个请求是从 http://a.com 发起的对 http://b.com 的异步请求,或者页面跳转是通过表单的 post 提交触发的,则bar也不会发送。
我们该如何使用Samesite Cookie?
如果SamesiteCookie被设置为Strict
,浏览器在任何跨域请求中都不会携带Cookie,新标签重新打开也不携带,所以说CSRF攻击基本没有机会。
但是跳转子域名或者是新标签重新打开刚登陆的网站,之前的Cookie都不会存在。尤其是有登录的网站,那么我们新打开一个标签进入,或者跳转到子域名的网站,都需要重新登录。对于用户来讲,可能体验不会很好。
如果SamesiteCookie被设置为Lax
,那么其他网站通过页面跳转过来的时候可以使用Cookie,可以保障外域链接打开页面时用户的登录状态。但相应的,其安全性也比较低。
另外一个问题是Samesite的兼容性不是很好,现阶段除了从新版Chrome和Firefox支持以外,Safari以及iOS Safari都还不支持,现阶段看来暂时还不能普及。
7.防止网站被利用。
前面所说的,都是被攻击的网站如何做好防护。而非防止攻击的发生,CSRF的攻击可以来自:
- • 攻击者自己的网站。
- • 有文件上传漏洞的网站。
- • 第三方论坛等用户内容。
- • 被攻击网站自己的评论功能等。
对于来自黑客自己的网站,我们无法防护。但对其他情况,那么如何防止自己的网站被利用成为攻击的源头呢?
严格管理所有的上传接口,防止任何预期之外的上传内容(例如HTML)。
添加Header X-Content-Type-Options: nosniff
防止黑客上传HTML内容的资源(例如图片)被解析为网页。
对于用户上传的图片,进行转存或者校验。不要直接使用用户填写的图片链接。
当前用户打开其他用户填写的链接时,需告知风险(这也是很多论坛不允许直接在内容中发布外域链接的原因之一,不仅仅是为了用户留存,也有安全考虑)。
实操案例
DVWA(High)
源码分析:可以看出high等级的主要区别是增加了一个token值的校验,每次登录都会校验token是否正确,若想要执行更改密码操作必须知道正常用户的token,获得用户token的方式有两种:
- 1. 构造一个页面让用户点击,点击之后偷偷的读取用户登录网站的token,把token加到自己构造的更改密码的表单上做让用户点击完成攻击,但由于同源策略,一半无法获得token,也有解决方法,但那个更繁琐,这里不赘述了
- 2. 如果用户网站上刚好有存储型漏洞,可以利用存储型漏洞与csrf漏洞配合,即通过存储型漏洞获得token再利用csrf漏洞结合拿到的token完成攻击
这里为了方便,可以在源码中的input找到user_token,而将token拼接到medium等级的表单中完成攻击
获得的token:20f07053354bf93a94e3bb45e2923312
在原来的表单中将token进行拼接
攻击完成
同理也可以使用a标签或者form get请求的方式进行csrf攻击
PikaChu(post)
通过抓包可以得出修改数据的api为:http://192.168.209.128/pikachu/vul/csrf/csrfpost/csrf_post_edit.php,以及需要的表单参数。
在自己的网页上,或者不同端口(跨域)构建出一个html表单,并输入相应的信息。
submit!攻击成功,token难度也是如此操作,需要从当前网页中获取到token信息。
其他平台
2012年3月份的
WordPress的CSRF漏洞。。。。。。
总结
文章参考:
- • 前端安全系列(二):如何防止CSRF攻击?
- • 什么是CSRF?如何防御CSRF攻击?知了堂告诉你
- • 使用BurpSuite进行CSRF漏洞测试
感谢! -
完,谢谢观看,摘自我的公众号【小羽网安】