跨站点攻击-跨站点请求伪造(CSRF)

作者:vkvi 来源:ITPOW(原创) 日期:2009-9-28

跨站点请求伪造(CSRF 或 XSRF:Cross Site Request Forgery。forgery n. 伪造,伪造罪,伪造物),听起来很高深,实际上就是外部站点提交数据,比如您有一个留言板,留言板有一个撰写页、一个处理页,我自己仿照您的撰写页做一个表单,只是把 form 的 action 指向您的处理页,如果我的这个表单提交后,您的处理页接受了,好,您的留言板有“跨站点请求伪造”。

把问题再深入一步。

您的留言板后台有个删除留言页面 delete_process.asp,这个页面代码大致如下:

dim id
id = CLng(Request.Form("id"))
sql = "delete from msgs where id=" & id

我在我的服务器上做一个页面,就是自动 POST 提交 id 值到 delete_process.asp,然后我诱使您的留言板管理员登录,再诱使(方法可能很隐秘)他访问我服务器上的页面,然后指定 id 的留言就被删除了。

如果上面的代码是 id = CLng(Request.QueryString("id"),那攻击者就更方便了,不需要做什么页面了,直接写一个 URL 就可以了,因为 GET 的数据是放在 URL 中的。

这也太没意思了吧!

是啊,这种支持外部站点提交数据的网站多得是,连 Google 搜索都支持,那岂不是网上大乱了。

的确,如果您用一些扫描工具来扫描您的站点,看到报告后,您会气得吐血,因为您的网站遍地都是问题,目录 A 的投票表单提交到投票系统目录 B 后,这些扫描工具都会报告这是个 CSRF。

所以对待这个问题要理性地对待,如果您的表单处理本来就需要对外公开的,就像 Google 搜索页一样,又像公众投票一样,就不需要去保护起来。但像您的网站后台管理系统这些需要保护,您的后台系统如果不是网上通用的,中招的机率会很小,因为攻击者不知道您的系统结构,相对来说要安全得多,所以也可以不需要保护。

如果对安全要求很高,就需要保护了,就不能仅靠 Cookie 或 Session 来判断权限,还需要进行二次判断,假设您有一个撰写页面、一个处理页面,都是需要登录才能使用的,您可以这样做(当然还有其他方法):

  • 在撰写页面,向表单中输出一个 hidden 元素,hidden 元素存储一个随机数,并将随机数存储在 Session 中。
  • 在处理页面,判断撰写页面提交过来的 hidden 元素值和 Session 中的是否一致。一致就放行,不一致就拒绝。

由于攻击者没有登录,它无法从撰写页面获得随机数,就无法实行攻击了。

可不可以仅仅通过 HTTP_REFERER 来预防攻击呢?

HTTP_REFERER 是可以伪造的,但是,如果用户用的浏览器是正规浏览器,正规浏览器自身不会去伪造,攻击者也没有办法让用户使用的浏览器去伪造,所以判断 HTTP_REFERER 也不失为一种简单实用的办法。

但复杂的、要求高的系统中,该法并不一定保险,具体参见本节下方相关文章的“CSRF 跨站域请求伪造白话详解”。

相关阅读


相关文章