跨站请求伪造

案例

开始讨论之前,先看一个案例。下图为新浪某子站玩玩,该网站有抽奖机会,每个人限抽奖一次,如果磅数推广分享到微博则可以多获得一次摇奖机会。

玩玩

2016-03-07曾报出玩玩网站存在CSRF漏洞:用户甚至不知道玩玩网站的存在,只是在浏览新浪微博(已登录)的时候好奇的点开某博主发出的微博或打开好友发来的新闻链接,就发现用户已经自动转发某条微博,如下图所示,而微博这条信息中则显示“来自新浪玩玩”。

转发玩玩

概念

CSRF漏洞全称为Cross Site Request Forgery,跨站点请求伪造。

顾名思义,跨站即请求的来源是非目标网站,请求伪造即请求的发出不是用户的意愿。
利用受害者尚未失效的身份认证信息(cookie、session等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。

上面的例子上只是冒用用户名义转发了一条微博,危害性还没那么大,但是一旦有漏洞的网站是银行,冒用用户名义做一些转账,改密码等操作的危害就非常大了。

Cookie传输过程

更好的了解这个漏洞前,需要先了解一些Cookie传输过程知识,如下图所示。

Cookie传输过程

我们知道HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。通过使用Cookie,服务器从通行证上确认客户身份. Cookie实际上是一小段的文本信息,客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。

Cookie可以根据失效时间分类:

  • session cookie:临时cookie 浏览器关闭后失效
  • Third-party cookie:本地cookie 服务器在set-cookie指定Expire时间,过时失效。若是跨域可能会禁止

P3P Header的副作用:The Platform for Privacy Preferences在线隐私偏好平台

  • P3P头,某种程度上允许浏览器发送第三方cookie:用于类似广告等需要跨域访问的页面

浏览器Cookie存储机制

待补充

Session 传输过程

待补充

CSRF攻击过程

接下来了解一下CSRF的攻击过程,下图为CSRF攻击过程,普通用户访问mybank后,浏览器留下认证cookie,此时用户访问了攻击者构建的网站,网站中含有CSRF攻击代码,一个form表单,提交后的行为为转账操作。表单需要的参数分别为收账人和转账金额,如图分别为attacker和1000,表单为自动提交。也就是当用户打开该网页时表单自动触发,带着用户已经通过的身份验证信息向银行发出了转账操作。

CSRF攻击过程

CSRF攻击主要是因为Web的隐式身份验证机制,Web的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。

案例剖析

玩玩代码

这次我们回来看一下文章开篇的玩玩转发微博的漏洞发生原理和过程。与上述银行攻击过程类似,普通用户登录新浪后,浏览到某篇大号文章后点开,此站点恰好存在CSRF的攻击代码,点开后浏览器自动运行。浏览器“拿着”用户登录微博的身份认证信息触发了转发微博这个事件,整个过程用户毫不知情。恶意代码假冒用户之手做了转发微博这个行为。

整个过程黑客没有插入任何恶意代码到原网站,只是调用了网站本身的js代码接口,完成了未经授权的转发而已。

演练

下面使用 DVWA 这个工具练习CSRF整个攻击过程。

  1. 运行起DVWA
1
./run-dvwa-docker-container.sh
  1. 访问 http://127.0.0.1:9099/dvwa,默认登录名密码为:admin/password
  2. 设置安全等级为Low,点击CSRF板块
  3. 尝试改密码
  4. 观察Url,构造攻击链接,此时我们已经拿到让用户更改密码的攻击链接了,但是这个链接太长,而且暴露的信息很明显。
  5. 将明显的链接进行短链接隐藏url,常用的短链接隐藏的网站很多,如百度短链接、980短链接等。网址缩短的原理是使用HTTP 301 Moved状态码重定向,浏览器就会自动的转向到目标网址。
  6. 就算如此,仅仅凭借链接上的参数传递终究是有限的,而且post请求也无法通过直接构造链接的方式,可以考虑构造攻击页面的方式。 将所需要的参数放进构造出的HTML中,可以考虑使用form或img等标签。

构造攻击页面

图像URL是否是真的图片并不重要,img标签存在就会触发 src 中的特定请求。这意味着浏览器不会阻止图片下载。

跨站点请求伪造漏洞的本质

由上述练习逐渐感觉到,CSRF 发生的本质原因是重要操作的所有参数都是可以被攻击者猜测到的

跨站点请求伪造的测试方法

黑盒测试

扮演双重角色-攻击者和受害者

  1. 获得认证后的相关URL地址(http://127.0.0.1:9099/dvwa/index.php)
  2. 建立一个包含请求URL 的html页面
  3. 确保合法用户已经登录应用
  4. 引诱合法用户访问测试URL
  5. 观察结果,如检查web服务器是否执行了相关请求

灰盒测试

审计检查应用程序以确定其会话管理是否存在漏洞

  1. 如果会话管理只依赖客户端的数据(浏览器可获得的信息),那么应用程序就是存在漏洞的
  2. 如果应用程序不存在漏洞,该应用必须在URL中包含会话相关的信息,无法被用户辨别或预测出

测试工具

  1. Burp Suite
  2. CSRF Tester
  3. WebScarab Spider

出现条件

  1. Web浏览器处理会话相关的功能使用如cookies和http认证信息
  2. 攻击者识别合法的web应用url、参数和其合法值等
  3. 应用会话管理仅依赖于浏览器所了解的信息

“一些HTML的tag会导致对http(s)资源的直接访问” 帮助攻击者利用该漏洞的

攻击面小
1) 浏览器自动发送鉴别用户会话的信息。 假设 site 是一个web应用程序的站点,用户 victim 刚刚向 site 认证了自己。在响应中,site 给 victim 分配了标示认证会话的cookie。通常,一旦浏览器接受了 site 设置的cookie,就会自动在之后的所有指向 site 请求中发送该cookie。
2) 通过代码分析,或者通过访问,记录HTML/javascript中的表单和URL连接请求获得。
3) http的认证信息已经存储在浏览器中,并在随后的请求中会进行再次发送的情况。

防御方法

跨站请求伪造可以从两方面来分析:跨站; 请求伪造

则需要至少满足以下几个条件之一: 1. 来源验证 2. 请求不可伪造,不可预测 3. 请求用户确认

  • 服务器对请求来源(HTTP中的Referer头)进行验证,如果该请求不是来自本站的则拒绝处理该请求。

Referer:根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。

在通常情况下,访问一个安全受限页面的请求来自于同一个网站,Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。

Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。

所以该方式一般用于监控CSRF攻击的发生,而不用来抵御攻击。

然而这种方式代价很小,开发人员只是需要增加一个拦截器来检查 Referer 的值。

  • 加入用户互动,使用验证码来保证每次操作都需要用户进行互动,该方式可以保证请求是经过用户确认之后的,可以避免冒用用户之手发送未授权请求。
  • 将参数加密或混淆,直接将某参数如“password_new”,通过加密混淆后为用户无法辨别的一段乱码。不过该方式依然有很明显的缺点,难读不说,一旦用户使用收藏夹收藏该网页后,因为参数乱码可能导致下次无法进入到指定页面。
  • 在请求时加入随机参数token:该方式与上一解决方案同样是在请求不可预测角度防御,不同在于,增加一个随机参数,而不改变原有的参数值。服务器将用户session和token进行绑定,在返回用户请求的页面时将token set到页面的form表单里。这样用户在submit表单时,服务器对POST请求中的token进行验证,验证不成功则拒绝该请求。

对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。在每个 form 中提供隐藏 field 在服务器端建立一个拦截器来验证这个 token。

使用该方式时要注意Token的使用原则:

  • 保证Token足够随机,只有这样才算不可预测
  • 一次性的,即每次请求成功后要更新Token,这样可以增加攻击难度,增加预测难度
  • Token要注意保密性,敏感操作使用post,防止Token出现在URL中

一些常用框架如Spring, Struts等框架内置了CSRF攻击防御的支持,我们在开发时候可以直接选择使用。

案例:CSRF + XSS漏洞

新浪案例

看到这样一份充满“诱惑”的文章,很多八卦的用户便会毫不犹豫的点击查看,很多用户却因此遭遇CSRF漏洞因此转发莫名其妙的文章,这样例子确实存在的。在新浪2011年,hacker先注册了个叫hellosammy的sina微博帐号,接着在名人堂里找到了一些加v用户(或者是普通用户),并关注他们,并给他们发送带有恶意链接的私信。收到私信的一时没经得住标题党的诱惑,点开了链接,于是后续一发不可收拾,他们除了在自己的微博上自动发送恶意链接,更可恶的是给自己关注的人通过私信方式也发送了恶意链接,如此以N次方的速度传播开来。

新浪案例解释

顺便再回顾下XSS(跨站脚本攻击)的基本知识:恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,控制用户浏览器。有XSS的网站可以直接伪造请求。

而CSRF(跨站请求伪造):点击攻击者提供的链接的时候,强制在web应用认证的情况下执行恶意攻击者期望操作的攻击,发送攻击者期望的请求。CSRF与XSS最大的区别就在于,CSRF并没有盗取cookie而是直接利用

Flash CSRF

待补充

CSRF Worm

待补充