文章首发于 Web 安全防护战 - 浅谈CSRF。php
在进入 web 安全知识以前,建议对 HTTP 有所了解,能够看HTTP 入门体检,会对如下的内容有所帮助。html
CSRF,跨站请求伪造。也被称为one-click attack或者session riding,一般缩写为CSRF或者XSRF。是一种挟制用户在当前已登陆的Web应用程序上执行非本意的操做的攻击方法。前端
XSS 的 Cross Site主要是指在本网站运行了来自其余网站的脚本,而 CSRF 的Cross Site则相反,指在其余网站对本网站形成了影响。跟 XSS 相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。git
咱们在本地搭建两个破烂的网站,一个模拟 CSRF 攻击网站,另外一个模拟博客网站。咱们的博客网站是采起 GET
方法来发送评论(偷懒,不要模仿)。github
匿名信息的状况下:web
// 攻击网站攻击代码
<img src="http://localhost:3000/?message=CSRF 攻击" />
复制代码
诱引用户点击进行CSRF攻击的状况以下:算法
// 攻击网站攻击代码
<img src="http://localhost:3000/?message=<a href=http://www.csrf.com/>点了会有好事发生!</a>" />
复制代码
大概的流程以下:后端
GET
请求);禁止第三方网站带 Cookies,即在响应头 Set-Cookie
设置 SameSite 属性,表示该 Cookie 问同源网站而非来源第三方网站。如 Koa2 设置以下:api
ctx.cookies.set([cookie_key], [cookie_value], {sameSite: 'strict' | 'lax'};
复制代码
其中 strict
与 lax
区别以下:跨域
// B网站 API 响应头设置以下:
Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3
复制代码
foo=1
这个 Cookie 是不会从 A网站 带到 B网站的;Lax
,只会在使用危险 HTTP 方法时发送跨域 Cookie 被阻止,如 POST 请求。假如 A 网站 有一个超连接 GET 请求 B网站的 API,那么这时候 Cookie 是能够从 A网站 带到 B网站的;baz=3
是能够从 A网站 带到 B网站;注意:
Lax 的防范有限,而 Strict 则一棒子打死,因此先对大多数 Cookie 设置为 Lax 做为 CSRF 攻击缓解措施,而针对某部分认为存在危险可能的 Cookie才设置 Strict。另外,SameSite Cookie 在子域不支持共享,也就是说父域登陆后在子域还须要从新登陆,这显然不够友好,并且还存在兼容性问题。
不管是验证码仍是 CSRF Token,道理都是同样的,就是为了保证只有在本网站才能得到到的随机验证码。
验证码的原理:
验证码实现虽然简单,可是咱们不能让用户请求的时候都提交验证码,这样会影响用户体验。
CSRF Token的原理:
GET
请求 /api/message?token=xxx
或 POST
请求在form表单追加 <input type="hidden" name="token" value="xxx"/>
或 Ajax
请求在页面添加<meta name="csrf" content="token" />
,经过 JS 去获取该 meta 值;注:
Token 虽然颇有效的防护 CSRF,可是实现复杂,不只须要前端这边的请求都带上 Token,并且后端也须要对每一个接口都进行校验,所以工做量比较大。
Origin
、Referer
,都是用来表示请求源地址。在大多数场景中,会跟随着请求头发送到服务器,而后服务器经过解析头部值,获取请求来源地址。通常来讲,咱们在服务器设置好容许请求地址经过的白名单,而后当服务器拿到请求的来源地址,就能够进行过滤了。
Origin 说到 Origin
,就不得不提 CORS 了。CORS 须要浏览器和服务器同时支持。目前,全部浏览器都支持该功能,~IE 浏览器不能低于IE10~。一旦请求发生 CORS,那么请求头部信息就会携带 Origin
,可是假如发生302重定向,那么Origin也不会跟随着请求头部信息一块儿发送给服务器。
Referer Referer
的值是由浏览器提供的,每一次的 HTTP 请求首部中都会有该字段,不论是Ajax请求,仍是图片。既然由浏览器提供,那么就存在被攻击者刻意隐藏,甚至伪造Referer
的值。
控制Referer
的策略以下:
旧策略属性值 | 新策略属性值 |
---|---|
never | no-referrer |
default | no-referrer-when-downgrade |
always | unsafe-url |
origin-when-crossorigin | origin-when-cross-origin |
经过设置 HTTP 响应头 Content-Security-Policy
来指定 Referrer
策略:Content-Security-Policy: referrer no-referrer|no-referrer-when-downgrade|unsafe-url|origin-when-cross-origin;
策略属性值说明:
no-referrer
:任何状况都不发送 Referer
;no-referrer-when-downgrade
:当协议发生降级(如 HTTPS 页面跳转/引入 HTTP 页面)时不发送Referer
;unsafe-url
:不安全策略,不管什么状况都发送Referer
;origin-when-crossorigin
:尽在发生跨域以及包含host的前提下发送Referer
。隐藏Referer
有如下几种状况:
<meta name=“referrer” content=“never” />
或 <meta name=“referrer” content=“no-referrer” />
;a
、area
、link
、iframe
和 img
能够经过 referrerPolicy
进行设置隐藏 referrerPolicy="never"
或 referrerPolicy="no-referrer"
。其中 a
和 link
还能够经过设置rel="noreferrer"
;window.location.href=url
或 window.open
时会丢失Referer
。总的来讲,CSRF 危害很大,并且还跟 XSS 同样很难防范。虽说咱们在上面罗列的接种防护策略能够很大程度上防护 CSRF 攻击,可是并不是十全十美。因此咱们只有根据本身的实际状况来选择最合适的策略,这样才能下降受到 CSRF 攻击的几率。哦,对了,在防护 CSRF 以前,须要先防护 XSS。