http安全相关响应头(response header)备忘整理


网站上线了好几天,一直在完善nginx相关的配置,有种换个角度看http的感觉。通过各种header与浏览器进行交互的时候,浏览器是如何处理它们的,web一般有哪些安全相关的header是需要留意的,为此查询了很多博客和文档。也借此机会,作为首篇文章,汇总整理一下常用的安全相关response header。


Content-Security-Policy 内容安全策略(CSP)

Content-Security-Policy: item; item;

可以严格限制网站中一切资源的来源和形式还有要不要被执行和加载等一系列行为。比如图片只可以从某个地址加载,js和css只能通过外部文件的形式加载,ajax只能访问配置的站点。最主要是可以防止跨站脚本攻击(XSS)。对于论坛类允许用户输入且会被他人浏览的网站来说,用户输入的内容应当是被过滤和转义的,因为里面可能包含可以被浏览器运行的代码。下面以本站的配置为起点,介绍一下CSP的语法和作用

Content-Security-Policy: default-src https:; style-src-elem https://cdn.jsdelivr.net; img-src https://www.kotomiko.com https://kotomiko.com; font-src data:;

这是本站目前的配置方式。

default-src https:

所有的请求必须是HTTPS的包括静态资源。

default-src是大部份选项的缺省设置,如果具体的设置没有被找到,缺省就会被使用。所以很典型的用法就是缺省设置最严格,再针对网站的需要放开更细一步的限制。如:

如果设置成*.kotomiko.com会限制页面所有的请求只能发送到kotomiko及子域,但下面的style-src-elem https://cdn.jsdelivr.net不受这条规则限制,因为在样式表方面它会覆盖default-src的设置

‘self'指定所有请求必须只能发送到本页面的源,https与http的scheme不一样或是端口不一样,都不被认为符合这条规则。单引号是必要的

style-src-elem https://cdn.jsdelivr.net

样式表<style><link rel="stylesheet">的加载只允许从https://cdn.jsdelivr.net加载

img-src https://www.kotomiko.com https://kotomiko.com

图片只允许从主站加载

font-src data:

允许使用base64编码的字体。由于bootstrap的css中使用了这个方式


关于值的设置都是大致相同的,设置的时候主要是注意优先级以免被覆盖设置,一般每个值之间都有空格,多个设置之间用分号隔开。需要特别注意的是https:data:的设置是一定要有冒号'self''none'以及'unsafe-inline'等一定需要单引号

关于<script><style>的补充

script-src 'unsafe-inline' 'unsafe-eval'

style-src 'unsafe-inline'

'unsafe-inline'表明了写在<html>里的脚本或样式允许被运行。

'unsafe-eval' 则是允许浏览器运行eval()函数。对于论坛等网站来说,是不建议开启的


这里说明一些常见的设置

Content-Security-Policy: default-src 'self'; form-action https://api.kotomiko.com https:; frame-src 'none';

所有内容都只能来自当前域,不包含子域,form表单只能提交给api.kotomiko.com且只允许https,不允许加载frame

Content-Security-Policy: default-src https:; img-src *; script-src 'none'; style-src *.kotomiko.com 'unsafe-inline';

所有内容只允许加载https协议,允许从任何域加载图片,不允许加载javaScript, 只允许从kotomiko及子域加载样式表,以及允许写在<html>文档里的style被执行


CSP也可以使用<meta>的方式放在html页面里

<meta http-equiv="Content-Security-Policy" content="default-src https:">

如果想测试网站某些配置是不是会影响到正常运行。可以使用Content-Security-Policy-Report-Only头部,设置方式是一样的,如果有违反了配置的错误的话,会把错误输出到控制台,并且不会影响网站的正常使用。它还支持report-uri项的设置,如果网站有违反规则的错误发生,浏览器会把错误相关信息发送到这个地址


X-XSS-Protection 跨站脚本保护(X-XSS)

X-XSS-Protection: 1; mode=block

这个头部和禁用了unsafe-inlineSCP其实是一样的。只是它出现在SCP之前,所以对于不支持SCP的浏览器来说,它能起到类似的作用。目前支持4种值

  1. X-XSS-Protection: 0 禁用过滤,相当于不进行任何保护
  2. X-XSS-Protection: 1 启用过滤,在检测到XSS的时候,会移除不安全的代码(浏览器的默认行为)
  3. X-XSS-Protection: 1; mode=block 启用过滤,不过如果检测到XSS的话,会不渲染页面
  4. X-XSS-Protection: 1; report = <uri> 跟2的作用一样,移除不安全的代码,并且会向指定的uri报告相关信息

X-Content-Type-Options

X-Content-Type-Options: nosniff

这个头部主要是用于禁用MIME类型嗅控(MIME type sniffin)。它只有这一种写法。

假设用户编写了一段恶意的javaScript然后更改后辍名为.jpg并且上传到了自己的文章或者博客里。服务端当然可以对图片进行识别和压缩来破坏里面的恶意代码,但也可能没有这么做。浏览器在请求图片的时候,发现它是javaScript,会把这个图片当作javaScript运行(也是出于对网站技术员的特殊关心),一个XSS攻击就这样形成了,不过不同浏览器对这个头部的支持不太一样,所以不能过于依赖这个头部,即使是目前的主流浏览器版本,在<a><image>的情况下也仍然有不支持这个头部的。


X-Frame-Options

X-Frame-Options: deny

X-Frame-Options: sameorigin

X-Frame-Options: allow-from https://<domain>.com/

关于frame的头部,不经过一些关于frame的保护的话,网站被别人嵌在frame里或是被嵌也不是不可能发生的事情。像常见的运营商劫持就是通过frame的手段。一来影响体验,再则frame的js互访问性也伴随着安全的不确定性。点击劫持也可以被这个头部限制,浏览网站有时候点击某个按钮会有种被挡住了的感觉。会弹出些广告或其他的网页,在连续点击几次后才能触发到正确的点击事件。这种情况大概率是按钮被一个透明的frame挡住了,点击实际上响应的是frame的点击事件。

  1. X-Frame-Options: deny 完全禁用frame,自己的页面无法使用frame,也不能被其他网站嵌套
  2. X-Frame-Options: sameorigin 同域名下允许嵌套
  3. X-Frame-Options: allow-from https://<domain>.com/ 允许该页面在指定的域名下嵌套

X-Download-Options

X-Download-Options: noopen

针对旧版本IE浏览器的头部。旧版本的IE下载文件允许直接在浏览器打开,如果下载的文件是html文件则会直接执行在当前页面的上下文中,共享当前页面的js和document实例。这种方式的安全性是没有办法保证的,目标html可以修改html元素,也可以提取cookie等可能包含身份密钥的信息。通过添加这个头部并且设置noopen可以禁用旧版IE允许打开下载文件的选项。

X-Permitted-Cross-Domain-Policies

X-Permitted-Cross-Domain-Policies: none

X-Permitted-Cross-Domain-Policies: master-only

X-Permitted-Cross-Domain-Policies: by-content-type

X-Permitted-Cross-Domain-Policies: by-ftp-filename

X-Permitted-Cross-Domain-Policies: all

这个头部也是针对跨域的,不过它是用于Adobe系列产品的,用于限制Adobe相关脚本的跨域权限,跨域的情况一般会先访问目标域名根目录的crossdomain.xml文件,该文件需要定义允许访问与不允许访问的URI的相关设置,同时考虑到根目录的权限不一定被开发者拥有,所有可以使用X-Permitted-Cross-Domain-Policies头部替代设置。虽然html5标准抛弃了Adobe Flash等一系列嵌入式的网站脚本,不过完全过渡过来也是需要时间的。如果网站有应用Adobe系列产品的话,建议了解一下相关的设置。

  1. X-Permitted-Cross-Domain-Policies: none 完全禁用跨域
  2. X-Permitted-Cross-Domain-Policies: master-only 仅允许使用域名根目录的crossdomain.xml文件
  3. X-Permitted-Cross-Domain-Policies: by-content-type 仅允许http和https协议的访问,并且响应正文类型需要是Content-Type: text/x-cross-domain-policycrossdomain.xml文件
  4. X-Permitted-Cross-Domain-Policies: by-ftp-filename 仅允许ftp协议,并且以/crossdomain.xml结尾的URI指向的文件
  5. X-Permitted-Cross-Domain-Policies: all 允许所有的crossdomain.xml文件

关于安全相关的reponse header目前只了解到了这些,这篇文章也只整理了关于http相关的头部,感觉篇幅不宜太长,https相关的安全加强设置之类的,后面重开一篇比较合适的感觉。网上关于这些的文章也不少,虽然自己是左搜右搜配置本站的代理服务器,但感觉内容其实是大同小异的,选用了本站觉得需要的整理了一下。