CSRF,Cross-site request forgery
https://en.wikipedia.org/wiki/Cross-site_request_forgery
跨站请求伪造攻击过程如下:
- 用户打开浏览器,访问受信任网站A,输入用户名和密码,请求登陆网站A
- A网站验证用户A身份成功,并返回Cookie信息给浏览器,浏览器存储该Cookie信息
- 在保持A网站登陆的情况下,由于各种原因,用户访问网站B某包含恶意代码页面
- 恶意代码页面使用浏览器中存储的用户A网站Cookie构造恶意请求,并向A网站发起以达到对用户的非法目的
简而言之,网站B恶意页面获取浏览器中用户在网站A的Cookie信息,伪造用户请求操作A网站,在用户无感知的情况下达成恶意目的
实际场景
某购物网站 www.buy-something.com,
想象一下,有一个名为 e-bank.com 的网站向用户提供电子银行服务,其中包含一个名为 /transfer 的页面用于提交转账请求。
当用户访问 e-bank.com/transfer 页面时,会展示由用户填写的表单,当用户填写完成表单提交时,则向页面地址本身发送 HTTP POST 请求,发送用户填写的收款人和金额等参数。
或者邮件中嵌入的链接
<a href="http://test.com/csrf/transfer.php?amount=1000&for=hacker" taget="_blank">重磅消息!!</a>
此时攻击者可以构建一个恶意页面,其中包含一个不可见表单并将提交地址指向 e-bank.com/transfer,攻击者预先在表单参数中设置好特殊的收款账户和金额,当用户受到欺骗点击进入这个恶意页面时,浏览器加载执行 JavaScript 代码,将表单提交。
如果用户没有在 e-bank.com 上注册或登录,转账请求当然不可能被执行。但一旦用户刚刚使用过这个服务,登录状态尚未过期,则转账请求就可能被执行成功。
这就是 CSRF 攻击,原理简单,潜在危害巨大,索性现在已经有很多成熟的手法用于阻止攻击。下面我来介绍一下。
攻击特点
- 攻击 一般发起在第三方网站,而不是被攻击的网站,被攻击的网站无法防止攻击发生
- 攻击 利用受害者被攻击网站的登录凭证,冒充受害者提交操作,而不是直接窃取数据
- 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是 冒用
- 跨站请求可以用各种方式:图片 URL、超链接、CORS、Form 表单提交等等,部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪
对于服务器返回的结果,由于浏览器 同源策略 的限制,黑客也无法进行解析。因此,黑客无法从返回的结果中得到任何东西,他所能做的就是给服务器发送请求,以执行请求中所描述的命令,在服务器端直接改变数据的值,而非窃取服务器中的数据。所以,我们要保护的对象是那些可以直接产生数据改变的服务,而对于读取数据的服务,则不需要进行 CSRF 的保护。比如银行系统中转账的请求会直接改变账户的金额,会遭到 CSRF 攻击,需要保护。而查询金额是对金额的读取操作,不会改变数据,CSRF 攻击无法解析服务器返回的结果,无需保护。
上文中讲了 CSRF 的两个特点:
- CSRF(通常)发生在第三方域名
- CSRF 攻击者不能获取到 Cookie 等信息,只能冒用
防御思路
防御思路:
- 我们能不能 区分 一个请求是来自于自己的前端页面,还是第三方的网站?
- 怎么让自己的前端页面和伪造的请求变得 不一样 呢?
针对 CSRF 的特点制定防护策略:
- 阻止不明外域访问
- 同源检测机制:服务器通过请求头附带的
Origin和Referer字段确定请求的来源域 - Samesite Cookie
- 同源检测机制:服务器通过请求头附带的
- 提交时要求附加本域才能获取的信息
- CSRF Token
- 双重 Cookie 验证
- 保证网络请求由真实用户发出
- 用户操作限制(验证码)
跨站请求伪造的防御策略
跨站请求伪造通常从第三方网站发起,被攻击网站无法防止攻击发生,只能通过增强网站针对跨站请求伪造的防护能力来提升安全性。
验证HTTP Referer字段
HTTP头中的Referer字段用来标明请求来源于哪个地址。在处理敏感数据请求时,通常来说,Referer字段应该和请求地址位于同一域名下。
这种方法简单易行,仅需要在关键访问处增加一步校验。但该方法也有局限性,因其完全依赖浏览器发送正确的Referer字段。虽然HTTP协议对此字段的内容有明确的规定,但无法保证来访浏览器的具体实现,也无法保证浏览器没有安全漏洞影响到此字段。并且,也存在攻击者攻击浏览器篡改其Referer字段的可能性。客户端可以篡改referer字段。
在请求地址中添加Token并验证
CSRF的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果在访问敏感数据请求时要求用户浏览器提供不保存在Cookie中并且攻击者无法伪造的数据作为校验,那么攻击者就无法再运行CSRF攻击。这种数据通常是窗体中的一个数据项。服务器将其生成并附加在窗体中,其内容是一个伪随机数。当客户端通过窗体提交请求时,这个伪随机数也一并提交上去以供校验。正常访问时客户端浏览器能够正确得到并传回这个伪随机数,而通过CSRF传来的欺骗性攻击中,攻击者事先无从得知这个伪随机数的值,服务端就会因为校验Token的值为空或者错误而拒绝这个可疑请求。
使用验证码
CSRF是在用户不知情的情况下构造了网络请求,因此添加验证码能强制用户必须与应用进行交互,服务器通过验证码来识别是不是用户主动发送的请求。
跨域
我们有时还会听到一种名为 CORS 的技术,它是一套用于指示浏览器是否允许跨域请求的规范。
现代浏览器均支持这一规范,一个现有页面上发起 Fetch/XHR 请求时,浏览器会首先发送一个 HTTP OPTIONS 请求用于预先检查目标服务是否允许当前来源的地址发起请求,服务器将以响应头的方式返回一个列表以指示浏览器,什么来源、哪种 HTTP method、包含什么样的请求头的请求是允许发送的,浏览器会遵守这些指示,在客户端阻止被禁止的请求。
这也是主动的保护手段,通过在服务器侧的配置,可以直接阻止浏览器发起请求。但需要注意的是,尽管正常用户不了解也不太可能这样做,但这个功能可以被客户端侧关闭。
https://tsejx.github.io/javascript-guidebook/computer-networks/web-security/csrf/
https://tech.meituan.com/2018/10/11/fe-security-csrf.html
https://www.explainthis.io/zh-hans/swe/what-is-csrf
跨域
https://www.cnblogs.com/dtux/p/18410759