攻击原理

Web程序进行重要更新操作的URL保护不当,只要用户已经认证,就可以简单地发送请求进行该操作。攻击流程示例:

  1. 某个允许“一个月内免登录”的A博客系统赠送积分,在用户已经登录的前提下,使用以下URL的GET请求进行积分赠送:

     http://blog.a.com/curUser/score?transto=zhang3&amount=100
    
  2. 恶意用户B发现了这个漏洞,并对某个知名的博文发表以下评论(注意:该博文可能是在A博客系统上,也可能位于其他任何Web系统上):

     <img style="display:none;" src="http://blog.a.com/curUser/score?transto=b&amount=100" />
     楼主的帖子实在是写得太好了。文笔流畅,修辞得体,深得魏晋诸朝遗风,....
    
  3. 结果:如果受害者C访问了该帖子,并且C是A博客系统的使用者,且已经登录,则会触发该积分赠送操作。当然,如果不跨站攻击的成功率更高一些。

无效的预防措施

Secret Cookie是指只能在HTTPS协议下的保护下才能使用的Cookie。不能使用的原因是:在发送HTTP请求时都会携带上请求域下所有的Cookie(比如jsessionid)。 下面的HTTP响应片段是设置了一个既是Secure又是HTTPOnly的Cookie。

Set-Cookie: SSID=Ap4P….GTEq; Domain=.foo.com; Path=/; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure;  HttpOnly

只允许POST请求

因为攻击者可以填写隐藏的表单,并诱导受害者点击以出发submit请求。

多步骤事务

将一个事务分成多个步骤(HTTP请求),并不能完全胜任预防工作。只要攻击者能够预测、或模拟完整事务的每一个步骤,就仍能够进行攻击。

重写URL

是指不使用Cookie,而将sessionId作为URL参数。而攻击者是无法猜测sessionId的。这可能会被认为是一个有效方案,因为攻击者无法猜测到受害者的sessionID,但是会暴露用户凭证。

预防措施

使用Synchronizer Token模式(常用方式)

该模式主要原理是:针对敏感操作(比如更新、转账等业务操作),显示最初的编辑画面前,要先在服务器端生成一个随机的challenge Token,并使之与当前用户的session关联。challenge token 被插入到表单的隐藏项,或URL中。在用户提交请求时,服务器端对该token进行存在性检查和正确性检查。通常检查逻辑是:

  1. 检查请求中的token是否存在
  2. 如果存在,该值是否与session中的值一致
  3. 如果前两步的结果均是否,则拒绝该请求,并重设token。

加强该模式的方法可以有:

  • token的名称也能够随机
  • 一个session一个token变为一个request一个token
<form action="/transfer.do" method="post">  <!--  表单隐藏项 -->
    <input type="hidden" name="CSRFToken" value="OWY4NmQwOOA">
</form>
<a href="/xxxx.do?CSRFToken=OWY4NmQwOOA"> XXX </a>  <!-- 链接URL参数 -->

注意:该模式会影响使用性,比如,无法使用浏览器的后退按钮,因为前一个页面中包含的token可能已经失效了。 应当鼓励像保护用户认证过的SessionId那样保护CSRF token,比如使用SSLv3/TLS。使用一个Session一个token的模式,就无法让用户同时进行多个更新操作,因为第二个更新操作的画面会清除第一个画面产生的token。

该模式的一个变种就是 “Double Submit Cookies”, 是指,token同时保存cookie中和form的隐藏项中,提交时再对比两者是否一致。

Challenge-Response

  • 使用CAPTCHA。CAPTCHA通常是指刻意模糊、扭曲的文字图片,用以区分机器人还是用户。
  • 重新认证。是指通过RemeberMe可以进行保护级别较低的业务(大多是非敏感数据的查看),但是涉及到重要操作时,必须让用户重新输入密码。(PS:这个在Spring Security框架中就有所体现)
  • One-time Token。 举例:在淘宝购物时,会向绑定的手机发送一次性的验证码。

其他

  • 针对Flash:合理配置crossdomain.xml
  • 检查Referer
  • 检查Origin

参考