与安全相关的 HTTP 头
2015 12 6 08:26 PM 2162次查看
分类:Web 标签:无
首先说下跨域请求。
为了描述的简单,先假设某用户为 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 这三种值。
虽然这些限制使得安全性得到了保障,但也极大地限制了其使用场景。而本文要说的第一批 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 属性:
如果是用 jQuery 的话,需要这样设置:var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.withCredentials = true; xhr.onreadystatechange = handler; xhr.send();
接着,D 在输出响应时,将这个 header 值设为 true,就能使用 Set-Cookie 来设置 cookie 了(由于 cookie 可以设置在根域上,因此可以跨子域设置 cookie)。$.ajax({ 'url': url, 'type': 'GET', 'xhrFields': {'withCredentials': true}, 'success': handler })
另外还有一个概念叫 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 汇报日志。
- (空):允许任何内容。
- '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 等方法从字符串生成可执行代码。
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 请求。
- 前者需要对 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 页面才启用。
- max-age:声明多长时间内有效。
- X-Frame-Options:设置该页面是否能通过 frame、iframe 和 object 标签,包含其他页面里。
它可选的值有:- DENY:不允许
- SAMEORIGIN:仅限同域
- ALLOW-FROM:仅限某个域。
- DENY:不允许
- X-XSS-Protection:启用 XSS 保护。
它可选的值有:- 0:禁用。
- 1:启用。
- 1; mode=block:启用,且在检查到 XSS 攻击时,停止页面渲染。
- 0:禁用。
- X-Content-Type-Options:值可为 nosniff,用于禁用浏览器的类型猜测,避免把图片当成 JavaScript 代码来加载等情况。
0条评论 你不来一发么↓