最近换了个负责网络安全的leader,整个部门开始网络安全整顿,我们负责WEB的接到通知要求防御CSRF攻击,设置referer白名单。之前看过一点referer相关的,但是了解不够深入,趁这次机会好好了解了一下。

1. 什么是 Referer

Referer 是 HTTP 请求头的一个字段,当浏览器(或者模拟浏览器行为)向服务器发送请求时,浏览器会自动在请求头中加上 Referer 字段,表示的意思是链接的来源地址,比如在页面引入图片、JS 等资源,或者跳转链接,一般不修改策略,都会带上Referer。

比如在www.google.com 里有一个www.baidu.com 链接,那么点击这个www.baidu.com ,它的header 信息里就有:Referer=http://www.google.com

在这里插入图片描述
这里有个问题要说明下,Referer 实际上是单词 referrer 的错误拼写,Referrer-Policy 这个首部并没有延续这个错误拼写。

2. Referer 安全性

Referer 参数其实就告诉了链接的请求来源于哪个网站,所以可以根据这个特性,限制一些接口只能本网站的才能调,外部网站不能调。

这个参数常常是跟同源策略跨域请求关联在一起,因为现在普遍都是前后端分离项目, 前端页面的地址和后端 api 接口地址是跨域的,为了让后台接口判断是不是合法请求,除了前端在请求头中加上 Authorization 字段,后台也可以通过 Referer 字段判断请求来源。

另外,在 CSRF 攻击的防范中,除了 SameSite Cookie ,CSRF token 等方法,Referer 字段判断请求来源也是一种防范手段。

3. 什么是 Referrer-policy

Referrer Policy是W3C官方提出的一个候选策略,主要用来规范Referrer,简单来说就是规定什么时候发送 Referer 字段,以及发送哪些信息。

最初是只有5种策略的,现在规范增加到9种:

no-referrer
整个 Referer 首部会被移除,Referer 不随着请求一起发送。

no-referrer-when-downgrade (默认值)
在没有指定任何策略的情况下用户代理的默认行为。在同等安全级别(HTTPS -> HTTPS)的情况下,Referer 会被发送,在协议降级(HTTPS -> HTTP)的情况下 Referer 不会被发送。

origin
Referrer 发送的信息只包括协议+域名+端口,不包括其它信息。例如 https://example.com/page.html 会将 https://example.com/ 作为引用地址。

origin-when-cross-origin
对于同源的请求,会发送完整的URL作为引用地址,但是跨域时候只发送协议+域名+端口。

same-origin
同源请求发送,否则不发送。

strict-origin
在同等安全级别(HTTPS -> HTTPS)的情况下,发送Referrer(协议+域名+端口),但是在协议降级(HTTPS -> HTTP)的情况下不会发送。

strict-origin-when-cross-origin
对于同源的请求,会发送完整的URL作为引用地址;对于跨域请求,在同等安全级别(HTTPS -> HTTPS)的情况下,发送Referrer(协议+域名+端口);在协议降级(HTTPS -> HTTP)的情况下不发送此首部。

unsafe-url
无论协议是否降级,也不管是同源请求还是跨域请求,都发送完整的 URL(移除参数信息之后)作为引用地址,所以这种是一种不安全的协议。

这项设置会将受 TLS 安全协议保护的资源的源和路径信息泄露给非安全的源服务器。进行此项设置的时候要慎重考虑。—— Referrer-Policy,MDN文档

空字符串
相当于没有设置,在没有此类更高级别策略的情况下,默认使用 no-referrer-when-downgrade

4. Referrer-policy 使用方法

加在 Header 中

代码如下:

<script>
fetch(url, {referrerPolicy: "strict-origin-when-cross-origin"});
</script>

有一个疑问,在浏览器调试工具中,Referrer Policy 出现在 General 里面,并没有出现在请求或者响应的报文中,所以无法判断是在请求头还是响应头中。
在这里插入图片描述
MDN文档上说 Referrer Policy 是响应头中的字段,但我个人觉得如果是在响应头里面,请求都发出了,再响应这个字段也没啥用了。而如果是放在请求头里面,这个字段的作用是修改浏览器处理 Referer 的行为,提交给服务器也没啥用啊。
在这里插入图片描述
于是用Wireshark抓包工具看了一下报文信息,发现请求的时候只有 Referer ,没有 Referrer Policy ,说明这个字段并没有在实际请求的时候发送,也没有通过服务器响应接收:
在这里插入图片描述
所以 Referrer Policy 应该可以理解为浏览器自己的一个配置项,在构造 ajax 请求的时候可以添加到 header 中,这个配置项用于修改浏览器处理 Referer 的行为,但不会放到实际的 header 中发送给服务端。

页面设置
现在很多前端项目都是单页应用,可以在入口文件 index.html 中的 <head> 标签中添加 meta 信息:

<meta name="referrer" content="strict-origin-when-cross-origin">

元素设置
在html元素中设置 referrerpolicy

<a href="http://example.html" referrerpolicy="origin" target="_blank">链接</a>
<img src="/example.jpg" referrerpolicy="strict-origin-when-cross-origin" />

Referrer-Policy是有一个优先级顺序的:

  • Element-level policy

  • Page-level policy

  • Browser default

元素级别的策略优先级最高,页面级别的次之,浏览器默认值最低。所以,可以先设置一个较严格的页面级策略,再对某些资源做渐进增强。

5. Referer 应用场景

  1. 防盗链
  2. 防止恶意请求

参考:
Referrer-Policy MDN 官方文档
HTTP系列之Referer和Referrer policy简介
http请求头中Referer的含义和作用
HTTP的Referrer和Referrer Policy设置

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐