IT技术互动交流平台

与安全相关的 HTTP 头

作者:佚名  发布日期:2016-02-17 00:05:21

 由于 Web 安全问题越来越严重,各种浏览器都加强了安全策略,也引入了很多新的 HTTP 头。最近在做读读日报的扫码登录时,就被这些玩意折腾了一天,于是记录在此。

首先说下跨域请求。
为了描述的简单,先假设某用户为 A,他用的浏览器是 B,他访问的网站是 C,C 需要访问另一个网站 D 的资源 E,攻击者有个攻击网站 F。
当 C 和 D 的域名、端口或协议不同时,对 E 的访问就称为跨域请求。
以下都属于跨域:

http://example.com、http://www.example.com 和 http://abc.example.com http://www.example.com:80 和 http://www.example.com:8080 http://www.example.com 和 https://www.example.com


当不跨域时,浏览器并不对其做太多安全限制;但因为跨域请求会存在安全隐患,所以默认会有如下的限制:

仅允许 GET、HEAD 和 POST 请求。 仅允许手动设置 Accept、Accept-Language、Content-Language 和 Content-Type 头。 Content-Type 头仅允许使用 application/x-www-form-urlencoded、multipart/form-data 和 text/plain 这三种值。

满足这些限制的请求,这里称为 simple request。

虽然这些限制使得安全性得到了保障,但也极大地限制了其使用场景。而本文要说的第一批 headers 就是用来解决这些跨域请求的限制的,它们以「Access-Control-」开头,最重要的两个 headers 有:

Access-Control-Allow-Origin:限制这个请求能从哪些 URI 访问。
这应该是其中最重要的一个 header,使用跨域 AJAX 时,被调用方 E 需要输出这个头,指明能从哪个网站访问。如果未输出这个头的话,只允许同域名的访问。
如果是一个公共服务,允许任意调用的话,将其设为「*」即可;如果要严格设置能使用的网站,将其设为「http://www.example.com」即可(http 和 https 不能混用)。
假如这个头没有正确设置的话,用户 A 在访问攻击网站 F 时,F 可以在 A 不知情的情况下发起一个跨域请求,访问资源 E。 Access-Control-Allow-Credentials:允许这个请求使用 Cookie。
这是另一个极为重要的 header。一般情况下,跨域 AJAX 不会附带用户的 Cookie,也不允许设置用户的 Cookie,因此不能很方便地进行登录等需要用到 Cookie 的操作。
要使用它的话,首先 C 在构造这个 XMLHttpRequest 对象时,需要设置 withCredentials 属性:
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.withCredentials = true;
xhr.onreadystatechange = handler;
xhr.send();
如果是用 jQuery 的话,需要这样设置:
$.ajax({
    'url': url,
    'type': 'GET',
    'xhrFields': {'withCredentials': true},
    'success': handler
})
接着,D 在输出响应时,将这个 header 值设为 true,就能使用 Set-Cookie 来设置 cookie 了(由于 cookie 可以设置在根域上,因此可以跨子域设置 cookie)。


另外还有一个概念叫 preflighted request。在不满足 simple request 的限制时,浏览器会先往这个地址发起一个 OPTION 请求,询问是否可用,然后再发起实际的请求。
它会用到这些 headers:

Access-Control-Request-Method 和 Access-Control-Allow-Methods:声明所用及允许的 HTTP methods。
普通的跨域请求只支持 GET、HEAD 和 POST 方法,想用其他方法的话,访问时需要将 Access-Control-Request-Method 设为 DELETE 等其他方法,E 则在 Access-Control-Allow-Methods 中返回所有支持的方法(用逗号隔开)即可。 Access-Control-Request-Headers 和 Access-Control-Allow-Headers:声明所用及允许的 HTTP headers。
类似上一组,用于支持其他的请求头。 Access-Control-Max-Age:告诉浏览器多长时间内,不需要发相同的 preflighted request,直接使用缓存的结果。


除此之外,还有个很重要的 header 叫作 Content-Security-Policy,用来定义页面可以加载哪些资源,目前有 2 个 levels。
其中,level 1 可以用这些指令(多个指令之间用分号分隔):

default-src:默认的加载策略。 script-src:允许加载这个域的 JavaScript。 style-src:允许加载这个域的 CSS。 img-src:允许加载这个域的图片。 connect-src:允许这个域的 AJAX 和 WebSocket 请求。 font-src:允许加载这个域的字体。 object-src:允许加载这个域的 object、embed 或 applet 对象。 media-src:允许加载这个域的 audio 或 video 对象。 frame-src:允许加载这个域的 frame 或 iframe。 sandbox:对这个资源启用沙箱。 report-uri:值为 URI,如果请求的资源不被策略允许,往这个 URI POST 汇报日志。

其中,*-src 的可用指令值有(多个指令值之间用空格分隔):

(空):允许任何内容。 'none':不允许允许任何内容。 'self':允许同源的内容。 data:允许 data 协议。 www.example.com:允许 www.example.com 的内容。 https://www.example.com:允许 https://www.example.com 的内容。 *.example.com:允许 example.com 及其子域的内容。 127.0.0.1:*:允许 127.0.0.1 所有端口的内容。 https::允许 HTTPS 内容。 'unsafe-inline':允许内联内容 'unsafe-eval':允许 eval 等方法从字符串生成可执行代码。

举例来说,如果怕被插入其他域名的 JavaScript 脚本,而又要允许 Google 统计的话,可以设置:

Content-Security-Policy: script-src 'self' *.google-analytics.com

而如果怕启用后有问题,可以用 Content-Security-Policy-Report-Only 这个 header。它并不进行实际的拦截,但遇到问题仍然会往 report-uri 发送报告。


而 level 2 主要增加了这些:

 

child-src:取代 frame-src(适用于多级嵌套的情况)。 frame-ancestors:取代 X-Frame-Options(见下文),用于限制页面能被哪些页面嵌套(适用于多级嵌套的情况)。 form-action:可以往这些 URIs 提交表单。 referrer:可用值有 no-referrer、no-referrer-when-downgrade、origin、origin-when-cross-origin 和 unsafe-url。 upgrade-insecure-requests:把页面中所有的 HTTP 请求都替换成 HTTPS 请求。

此外,script-src 指令也增加了 nonce 和 hash 的取值,可以防止意外地插入 inline JavaScript。

前者需要对 inline script 标签输出一个随机的 nonce 属性(假设是 nonce="abcd"),并在 header 里指定 Content-Security-Policy: script-src 'nonce-abcd'。 后者需要对 inline script 标签里的内容(含空白部分)计算 hash 值,支持 sha256、sha384 和 sha512(假设是 abcd...),并在 header 里指定 Content-Security-Policy: script-src 'sha256-abcd...'。


还有一些比较杂乱的 headers:

Strict-Transport-Security:强制使用 HTTPS 访问。
当用户访问过一次这个网站的 HTTPS 页面后,设置了这个 header,以后在访问这个网站的 HTTP 页面时,会自动转换成 HTTPS 请求。
它可以设置三个值:
max-age:声明多长时间内有效。 includeSubDomains:可省,子域也启用这个规则。 preload:可省,有一批列表限制了部分网站仅允许 HTTPS 访问,不需要访问过一次 HTTPS 页面才启用。 它比服务器强制跳转 HTTPS 更安全和高效,但假如遇到 HTTPS 证书出问题等情况,就没法临时降级到 HTTP 页面了。 X-Frame-Options:设置该页面是否能通过 frame、iframe 和 object 标签,包含其他页面里。
它可选的值有:
DENY:不允许 SAMEORIGIN:仅限同域 ALLOW-FROM:仅限某个域。 X-XSS-Protection:启用 XSS 保护。
它可选的值有:
0:禁用。 1:启用。 1; mode=block:启用,且在检查到 XSS 攻击时,停止页面渲染。 X-Content-Type-Options:值可为 nosniff,用于禁用浏览器的类型猜测,避免把图片当成 JavaScript 代码来加载等情况。

 

Tag标签: 与安全相关的   HTTP     
  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规