本文直接从防御方式开始讨论, 防御 CSRF 有 4 种方法:
使用 POST 替代 GET
检验 HTTP Referer
验证码
Token
使用 POST 替代 GET
一些程序员在开发的时候都是用 GET,POST 通用的函数来接收客户端的数据, 这样也是某些接口有 CSRF 的原因之一, 但是将全部接口都改成只允许 POST 方式访问, 就能防范 CSRF 了吗? 答案是: 不能. 只能说提高了一些成本.
原本是 GET 方式访问的接口, 攻击者只需要构造接口的 URL 参数让受害者点击即可. 现在改成使用 POST 方式访问, 攻击者只需要利用其他站点, 在站点上布置一个 POST 请求, 让用户点击.
检验 HTTP Referer
HTTP Referer 真是一个用于安全的字段, 除了能防范 CSRF, 还能防 JSONP 劫持, 盗链, 站外提交等安全问题. 但是 HTTP Referer 就一点问题都没有了吗? 答案是: 否定的, HTTP Referer 只能检查点击的链接来源是来自站内还是站外, 如果是 GET 方式的 CSRF, 那链接本身就是站内的, 也就意味着检验 HTTP Referer 是无效的.
验证码
上面说的两种防御 CSRF 的方式, 都有一定缺陷. 但是使用验证码是完全可以做到防止 CSRF 的, 因为验证码是用户在提交表单的时候, 必须输入图片验证码, 保证了服务器收到的是来自预期的请求. 这里我补充一下, 验证码功能必须没有缺陷才行, 我之前测试过很多 web 站点, 验证码或多或少有问题, 这样不但不能防止 CSRF, 甚至会引发出其他漏洞被利用.
下面我用前端抓包的方式来观察百度的发送图片验证码的流程:
(假设我这里操作一个修改密码操作) 我请求了一次修改密码接口后, 该接口就会返回图片验证码资源回到浏览器并展示出来, 发送修改密码表单时需要用户填写图片验证码, 然后将修改的一起发送到服务器去校验.
这样就保证了攻击者无法预知与伪造请求中的 veritycode 参数.
那么验证码有什么缺点吗? 在用户体验上, 如果一个网站很多功能都需要输入验证码才能发送, 那么无疑非常影响用户体验.
Token
Token 和验证码的原理非常相似, 只不过在使用上, 验证码是非常需要用户交互的, 但是 Token 基本是无感知的.
根据 Token 加入请求的方式, 又可以分为三种类型:
Cookie Token
HTTP 头自定义属性 Token
表单 Token
Cookie Token
类似图片验证码一样, 每次请求的功能接口时, 都通过响应头的 Set-Cookie, 将 token 存储到本地 cookie 中.
Set-Cookie: RePassToken=0123456789 expires=Thu, 04-Apr-2019 15:11:32 GMT; path=/; domain=passport.baidu.com; httponly
HTTP 头自定义属性 Token
先申明前端要在请求头里面添加自定义参数, 必须后台允许, 否则请求会报错.
这里以 vue-resource 请求为例, 前端的方法, 全局配置请求头, 在 main.JS 里面设置:
- Vue.http.interceptors.push((request, next) => {
- request.headers.set('HTTP_Token', '1234567890'); // 在请求里面添加了 token
- next((response) => { return response })
- })
这里以 PHP 举例, 服务器端将 http 头数据都放在全局数据_SERVER 里, 参数都以 HTTP 开头, 例如:
- # 客户端在 http 头里添加了 HTTP_Token 参数, 服务器端可这样读取
- if(array_key_exists('HTTP_Token', $_SERVER)) {
- $token = $_SERVER['HTTP_Token'];
- }
我直接讲这个方式的缺点, 使用 HTTP 头定义属性的方式来修复 CSRF 还是比较少的, 因为现在的前端和后端的开发基本都是两个独立的团队, 安全部门为了修复一个低位漏洞 CSRF 就要沟通两个部门, 还是修改前端和后端两处地方, 显然不是一个最优解. 毕竟还是有很多其他低成本的方式可以使用.
表单 Token
这个表单可以是 GET,POST, 每个表单, 请求都得包含一个 token, 才能使用功能. 下面观察一下百度的个人中心的 token 使用流程.
如果修改了 token 发 请求, 那么将不能得到正常的响应文了.
总结
以上说的几种防护方式各有利弊, 需要注意的是, 如果网站还存在着其他安全漏洞, 比如 XSS, 那么攻击者还是能够通过 JS 取到 Token 进行攻击的.
来源: https://www.cnblogs.com/mysticbinary/p/12630011.html