• home > webfront > SGML > web >

    referrer-policy:狙击盗链与跨站攻击之Referrer策略

    Author:zhoulujun Date:

    http 协议中 referer的metadata参数可让html 文档可以控制 http 请求中的 referer ,比如是否发送 referer、只发送 hostname 还是发送完整的 referer 等。

    什么是Referrer

    根据Referer的定义,它的作用是指示一个请求是从哪里链接过来

    HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理

    那么当一个请求并不是由链接触发产生的,那么自然也就不需要指定这个请求的链接来源。这个是时候就是空refferrer——比如,直接在浏览器的地址栏中输入一个资源的URL地址,那么这种请求是不会包含Referer字段的,因为这是一个“凭空产生”的HTTP请求,并不是从一个地方链接过去的。

    也可以看一下阮一峰老师的解释:HTTP Referer 教程——http://www.ruanyifeng.com/blog/2019/06/http-referer.html

    Referrer策略与盗链

    我们自己网站上面的内容(图片盗链、文件盗链、音频盗链、视频盗链等),比如图片音乐被别人盗链(白嫖)了,会消耗不少的带宽。像我这种小破站,基本就完全卡死了(现在有了CDN好好,比如白嫖google 的 cloudflare——诅咒GFW一万遍!)

    什么是盗链?

    内容不在自己服务器上,而通过技术手段,绕过别人放广告等有利益的最终页,直接在(如插广告等手段获利益的)页面上向最终用户提供内容。

    常常是一些名不经传的小网站来盗取一些有实力的大网站的地址(比如一些音乐、图片、软件的下载地址)然后放置在自己的网站中,通过这种方法盗取大网站的空间和流量。

    为什么会产生盗链?

    一般浏览一个页面并不是一次全部传送到客户端的,而是最先的一个http请求被传送回来的是这个页面的文本,然后通过客户端的浏览器对这段文本的解释执行,发现还有图片,那么客户端的浏览器会再发送一条http请求,当这个请求被处理后那么这个图片文件会被传送至客户端,然后浏览器会将图片安放到页面的正确位置,这样一个完整的页面经过发送多条http请求才被完整的显示。基于这样的机制,就产生了盗链问题。不仅损害了原网站的合法利益,还加重了服务器的负担。

    如何防盗链?

    要实现防盗链,就必须先理解盗链的实现原理。

    在http协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或文件。

    换句话说,通过referer,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以跟踪到显示它的网页地址。

    有了referer跟踪来源就好办了,这时就可以通过技术手段来进行处理,一旦检测到来源不是本站即进行阻止或返回指定的页面。

    其实就是通过Referer手段,来识别用户的来源,从而防止盗链的目的。但是,盗链的问题解决了,缺会引发一些列的安全问题。

    Referrer策略与web安全

    页面引入图片、JS 等资源,或者从一个页面跳到另一个页面,都会产生新的 HTTP 请求,浏览器一般都会给这些请求头加上表示来源的 Referrer 字段。Referrer 在分析用户来源时很有用,有着广泛的使用。

    但 URL 可能包含用户敏感信息,如果被第三方网站拿到很不安全(例如之前不少 Wap 站把用户 SESSION ID 放在 URL 中传递,第三方拿到 URL 就可以看到别人登录后的页面)。之前浏览器会按自己的默认规则来决定是否加上 Referrer。

    3.png

    2014 年,W3C 的 Web 应用安全工作组(Web Application Security Working Group)发布了 Referrer Policy 草案,对浏览器该如何发送 Referrer 做了详细的规定。新版 Chrome 已经支持了这份草案,我们终于可以灵活地控制自己网站的 Referrer 策略了。

    通过新的 Referrer Policy,我们可以针对第三方网站隐藏 Referrer,也可以只发送来源 URL 的 host 部分。但有一点要记住,新策略允许沉默,但不允许说谎。换句话说,你有权不告诉对方请求从哪儿来,但是不允许用假来源去骗人。不过即便是这样,这也对现有一些 Web 应用程序的安全性造成威胁。不少 Web 应用在限制 Referrer 时允许为空,之前想要发送无 Referrer 请求还要一点点技巧,现在就轻而易举了。

    Referrer Policy States

    新的 Referrer Policy 规定了五种 Referrer 策略:No Referrer、No Referrer When Downgrade、Origin Only、Origin When Cross-origin、和 Unsafe URL。之前就存在的三种策略:never、default 和 always,在新标准里换了个名称。他们的对应关系如下:

    策略名称属性值(新)属性值(旧)解释
    No Referrerno-referrernever绝不允许referrer data通过
    No Referrer When Downgradeno-referrer-when-downgradedefault发送referrer信息去安全的HTTPS站点,而非不稳定的HTTP站点。
    Origin Onlyorigin-

    发送协议、主机和端口(即子域)没有一个完整的URL作为来源,

    即https://moz.com/example.html只会发送https://moz.com

    Origin When Cross-originorigin-when-crossorigin-

    当传origin-only来路信息发送给外部站点时,如果目标有相同的协议、主机和端口(即子域),无论它是HTTP或HTTPS,都将全部的URL作为Referrer发送出去。(注解:官方说明书上有一处排印错误,将来的版本应该是"origin-when-cross-origin")

    标签写法:

    Unsafe URLunsafe-urlalways

    总是将URL字串作为一个referrer通过。

    注意:如果你的URL中存在任何敏感信息,这不是最安全的选择。其中URL的片段、用户名、密码被自动剥去。


    No Referrer:任何情况下都不发送 Referrer 信息;可以看到,新标准给之前的三种策略赋予了更具意义的新名称,同时还增加了两种新策略。另外现阶段支持 Referrer Policy 的浏览器保留了对旧标准的支持,但还是推荐大家尽快更新。简单介绍下这五种类型的具体含义:

    • No Referrer When Downgrade:仅当发生协议降级(如 HTTPS 页面引入 HTTP 资源,从 HTTPS 页面跳到 HTTP 等)时不发送 Referrer 信息。这个规则是现在大部分浏览器默认所采用的;

    • Origin Only:发送只包含 host 部分的 Referrer。启用这个规则,无论是否发生协议降级,无论是本站链接还是站外链接,都会发送 Referrer 信息,但是只包含协议 + host 部分(不包含具体的路径及参数等信息);

    • Origin When Cross-origin:仅在发生跨域访问时发送只包含 host 的 Referrer,同域下还是完整的。它与 Origin Only 的区别是多判断了是否 Cross-origin。需要注意的是协议、域名和端口都一致,才会被浏览器认为是同域;

    • Unsafe URL:无论是否发生协议降级,无论是本站链接还是站外链接,统统都发送 Referrer 信息。正如其名,这是最宽松而最不安全的策略;

    Referrer Policy Delivery

    知道了有哪些策略可以用,还需要了解怎么用。这里介绍指定 Referrer Policy 的三种方式:

    CSP 响应头

    CSP(Content Security Policy),是一个跟页面内容安全有关的规范。在 HTTP 中通过响应头中的 Content-Security-Policy 字段来告诉浏览器当前页面要使用何种 CSP 策略。我之前写过一篇 Content Security Policy 介绍,可以先看看。现在 CSP 还可以通过 referrer 指令和五种可选的指令值,来指定 Referrer 策略,格式非常简单:

    Content-Security-Policy: referrer no-referrer|no-referrer-when-downgrade|origin|origin-when-cross-origin|unsafe-url;

    注:根据文档,通过 CSP 头部设置 Origin When Cross-origin 策略时,指令值应该用 origin-when-cross-origin,这跟前面的表格里的 origin-when-crossorigin 有差异。实际上经过我的测试,Chrome 42 只支持 origin-when-crossorigin,后续会不会变还不知道,建议大家使用时,自己先测一下。

    CSP 的指令和指令值之间以空格分割,多个指令之间用英文分号分割。

    <meta> 标签

    通过 <meta> 标签也可以指定 Referrer 策略,同样很简单:

    1. None:绝不允许referrer data通过,标签写法:<meta name="referrer" content="none">

    2. None When Downgrade:发送referrer信息去安全的HTTPS站点,而非不稳定的HTTP站点。

      标签写法:<meta name="referrer" content="none-when-downgrade">

    3. Origin Only: 发送协议、主机和端口(即子域)没有一个完整的URL作为来源,即https://moz.com/example.html只会发送https://moz.com

      标签写法:<meta name="referrer" content="origin">

    4. Origin When Cross-Origin: 当传origin-only来路信息发送给外部站点时,如果目标有相同的协议、主机和端口(即子域),无论它是HTTP或HTTPS,都将全部的URL作为Referrer发送出去。(注解:官方说明书上有一处排印错误,将来的版本应该是"origin-when-cross-origin")

      标签写法:<meta name="referrer" content="origin-when-crossorigin">

    5. Unsafe URL: 总是将URL字串作为一个referrer通过。注意:如果你的URL中存在任何敏感信息,这不是最安全的选择。其中URL的片段、用户名、密码被自动剥去。

      标签写法:<meta name="referrer" content="unsafe-url">

    不过一般我们在服务端设置好。给定在http协议头里面就好。

    需要注意的是,<meta> 只能放在 <head>...</head> 之间,如果出现的位置不对会被忽略。同样,如果没有给它定义 content 属性,或者 content 属性为空,也会被忽略。如果 content 属性不是合法的取值,浏览器会自动选择 no-referrer 这种最严格的策略。

    <a> 标签的 referrer 属性

    通过给 <a> 标签增加 referrer 属性也可以指定 Referrer 策略,格式如下:

    <a href="http://example.com" referrer="no-referrer|origin|unsafe-url">xxx</a>

    这种方式作用的只是这一个链接。并且,<a> 标签可用的 Referrer 策略只有三种:不传、只传 host 和都传。另外,这样针对单个链接设置的策略优先级比 CSP 和 <meta> 要高。

    需要注意的是:经过我的测试,目前并没有哪个浏览器实现了对 referrer 属性的支持。现阶段,如果要针对单个链接去掉 Referrer,还是推荐使用下面这种支持度更好的写法(详情):

    <a href="http://example.com" rel="noreferrer">xxx</a>

    另外再重复一遍,现阶段的浏览器还保留了对 never、default 和 always 的支持,但是已经不推荐使用了。

    可以看到,通过新的 Referrer 策略,网站所有者可以选择更高的安全级别来保证用户隐私不被泄露;也可以选择更低的安全级别来获得一些便利,相比之前只能由浏览器默认策略一刀切,确实灵活了不少。

    其他问题

    这与 rel=noreferer 有什么关系呢?可能 rel=noreferer 会覆盖掉本文中的 meta 标签所设置的值。也就是功能覆盖。

    origin 信息不是一个完整的 url,所以浏览器客户端估计会在 origin 后面加一个 / 来作为 path 部分。

    如果 origin 是唯一的,会发生什么情况呢?估计 referer 会被忽略。


    浏览器兼容情况:

    Screen Shot 2017-05-05 at 16.24.09.png

    服务端referer策略控制

    如果Web服务器用的是Apache,可以使用Apache自带的Url Rewrite功能可以很轻松地防止各种盗链,其原理是检查refer,如果refer的信息来自其他网站则重定向到指定图片或网页上。

    如果服务器使用的是IIS的话,则需要通过第三方插件来实现防盗链功能了,现在比较常用的一款产品叫做ISAPI_Rewrite,可以实现类似于apache的防盗链功能。另外对于论坛来说还可以使用"登录验证"的方法进行防盗链。

    备注:referer一来可以追溯上一个入站地址是什么;二来对于资源文件,可以跟踪包含显示他的网页地址是什么。

    URLRewrite的设置

    安装目录下的httpd.ini

    RewriteCond Host(.+)
    RewriteCond Referer(?!http://\1.*).*
    RewriteRule .*\.(?:gif|jpg|png|exe|rar|zip) /block.gif [I,O]

    现在apache作为一线服务器的其实不多了,基本都是nginx打头阵了。

    nginx 防盗链

    location ~* \.(gif|jpg|png|swf|flv)$ {
        valid_referers none blocked www.test.com  *.jfedu.net;
        root /usr/share/nginx/html;
        if ($invalid_referer) {
        return 403;
    }}
    • location ~* \.(gif|jpg|png|swf|flv)${}为设置防盗链的文件类型,使用竖线|分隔。~*表示忽略大小写,只要是访问以.gif jpg png swf flv结尾的请求就匹配花括号里面的规则

    • valid_referers  www.test.com   *.jfedu.net;为白名单,使用空格分隔,可以使用*进行泛域名设置。

    • if ($invalid_referer) {}为判断是否符合白名单,不符合白名单将执行{}内的内容。

    对于CDN防盗链设置,对于资源,设置*.zhoulujun.cn 只允许你给定的域名访问,

    但是,对于全栈CDN来说,还要增加 refer为空,对于SEO,还要增加各个搜索引擎的域名 ip

    所以,全栈CDN,还是要CDN拆解,资源CDN与网页CDN,比如

    https://www.zhoulujun.cn/html/theory/network/2016_0316_7709.html

    如果不设置,百度收录的页面会直接打不开,蜘蛛也搜索不到



    参考文章:

    https://imququ.com/post/referrer-policy.html——本文来源,推荐博客https://imququ.com/post/about.md

    Nginx http_referer_module 防盗链原理和使用 https://blog.csdn.net/qq_34556414/article/details/104807737

    http://www.tuicool.com/articles/YJjeq2U

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy

    HTTP Referer二三事 http://www.fwolf.com/blog/post/320




    转载本站文章《referrer-policy:狙击盗链与跨站攻击之Referrer策略》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/SGML/web/2017_0505_8006.html