若得山花插满头,莫问奴归处。
CSRF 攻击
- CSRF 是跨站请求伪造的缩写,也被称为 XSRF, 是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。黑客引诱用户打开黑客的网站,在黑客的网站中,利用用户的登录状态发起跨站请求。
- 跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
- 因为 CSRF 攻击利用的是冲着浏览器分不清发起请求是不是真正的用户本人,也就是说,简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
CSRF 攻击流程
- 用户 C 打开浏览器,访问安全网站 A,输入用户名和密码请求登录网站 A.
- 在用户信息通过验证后,网站 A 产生 Cookie 信息并返回给浏览器,此时用户登录 A 成功,可以正常发送请求到网站 A。
- 用户没有退出 A 之前,在同一个浏览器中,打开一个 Tab 页面来访问网站 B.
- 网站 B 接收到用户的请求后,返回一些攻击代码,并且发出一个请求要求访问第三方站点 A.
- 浏览器在接收到这些攻击性代码后,根据网站 B 的请求,在用户不知情的情况下携带 Cookie 信息,向网站 A 发出请求。网站 A 并不知道该请求其实是由 B 发出的,所以会根据用户 C 的 cookie 信息以 C 的权限处理该请求,导致来自网站 B 的恶意代码被执行。
CSRF 攻击基本条件
- 登录受信任网站 A,并且在本地生成 Cookie。
- 在不退出登录网站 A 的前提下,访问危险网站 B.
常见的 CSRF 攻击
- GET 类型的 CSRF
- 银行站点 A: 它以 GET 请求的方式来完毕银行转账的工作:如http://www.mybank.com.Transfer.php?toBankId=11&money=1000
- 危险站点 B:其中存在一段 html 代码为
<img src=http://www.mybank.com/Transfer.php?toBankId=11&1000>
- 首先你登录了银行站点 A,然后访问危险站点 B,这时你就会发现自己的银行账号少了 1000 元。为什么会这样呢?原因是银行站点 A 违反了 HTTP 规范,使用 GET 请求更新资源。在訪问危急站点 B 的之前,你已经登录了银行站点 A,而 B 中的 一个合法的请求,但这里被不法分子利用了)。所以你的浏览器会带上你的银行站点 A 的 Cookie 发出 Get 请求,去获取资源以 GET 的方式请求第三方资源(这里的第三方就是指银行站点了,原本这是http://www.mybank.com/Transfer.php?toBankId=11&money=1000 ,结果银行站点服务器收到请求后,觉得这是一个更新资源操作(转账操作),所以就立马进行转账操作。
- POST 类型的 CSRF
- 这种类型的 CSRF 危害没有 GET 类型的大,利用起来通常使用的是一个自动提交的表单
1 | <form action=http://wooyun.org/csrf.php method=POST> |
- 访问该页面后,表单会自动提交,相当于模拟用户完成一次 POST 操作。
CSRF 攻击预防
- 验证 HTTP Referer 字段
- 发出一个请求时,此时 HTTP 协议头部会携带 Referer 字段,其中包含着请求该站点的域名,此时如果我们在访问银行站点时并且向银行发出请求,此时携带的 Referer 就是 mybank.com,如果此时我们从存在危险的网站 B 向银行站点发起请求,此时的 Referer 就是危险网站 B 的域名。
- 优点:使用方便,开发简单,一定程度上能预防 CSRF 攻击
- 缺点:这种机制完全依托于浏览器,Referer 字段容易被故意篡改,或者被禁用。
- 添加 token 验证
在安全站点 A 中生成一个 SessionId,保存在服务器端,该值可以作为 token 传递给客户端。客户端可以设置一个隐藏的 input 框,其中的值为该 token,当我们进行请求时,就会将该值传入到站点 A 的服务器,此时在服务器端就可以进行比较生成的 token 和保存的 token 是否一样,如果一样的话,就表示是从安全站点上发出的请求,就做出具体的相应。在危险网站 B 就无法拿到 token,所以也就无法进行正确的请求了。
优点
安全程度比 Referer 更高
实现方式上稍微复杂
需要保证 token 存储的安全性
在 HTTP 头中自定义属性并验证
这种方法也是保存 token,但是其实和上述不同的是,其在 HTTP 头部保存 token,我们可以一次性给访问该网站的请求都加上该自定义字段,但是如何将数据存放在 HTTP 中呢?此时我们就需要另一个模块,XHRHTTPRequest,当我们使用该模块时,存在另一个弊端,就是只能是异步请求。其他请求都是无法访问的。另外,对于没有进行 CSRF 防护的遗留系统来说,要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,这样几乎是要重写整个网站,这代价无疑是不能接受的。
优点
- 使用方式简单,不容易泄漏
- 使用地方局限。