一、X-Frame-Options

  这个header主要用来配置哪些网站可以通过frame来加载资源。它主要是用来防止UI redressing 补偿样式攻击。IE8和firefox 18以后的版本都开始支持ALLOW-FROM。chrome和safari都不支持ALLOW-FROM,但是WebKit已经在研究这个了。

  X-Frame-Options 响应头有三个可选的值:

DENY:页面不能被嵌入到任何iframe或frame中;

SAMEORIGIN:页面只能被本站页面嵌入到iframe或者frame中;

ALLOW-FROM:页面允许frame或frame加载。



// 正确的设置

DENY – 禁止所有的资源(本地或远程)试图通过frame来加载其他也支持X-Frame-Options 的资源。
SAMEORIGIN – 只允许遵守同源策略的资源(和站点同源)通过frame加载那些受保护的资源。
ALLOW-FROM http://www.example.com – 允许指定的资源(必须带上协议http或者https)通过frame来加载受保护的资源。
这个配置只在IE和firefox下面有效。其他浏览器则默认允许任何源的资源(在X-Frame-Options没设置的情况下)。 

// 通常不正确的设置
ALLOW FROM http://example.com – ALLOW和FROM 之间只能通过连字符来连接,空格是错误的。
ALLOW-FROM example.com – ALLOW-FROM选项后面必须跟上一个URI而且要有明确的协议(http或者https)


二、X-XSS-Protection

  顾名思义,这个响应头是用来防范XSS的。最早我是在介绍IE8的文章里看到这个,现在主流浏览器都支持,并且默认都开启了XSS保护,用这个header可以关闭它。它有几种配置:

  0:禁用XSS保护;

  1:启用XSS保护;

  1; mode=block:启用XSS保护,并在检查到XSS攻击时,停止渲染页面(例如IE8中,检查到攻击时,整个页面会被一个#替换);



// nginx配置设置
... ...
server {
... ...
add_header X-XSS-Protection 1;
... ...


  HTML前端解决方法:



<meta http-equiv="X-XSS-Protection" content="1; mode=block" />


  这个header主要是用来防止浏览器中的反射性xss。现在,只有IE,chrome和safari(webkit)支持这个header。



// 正确的设置
0 – 关闭对浏览器的xss防护
1 – 开启xss防护
1; mode=block – 开启xss防护并通知浏览器阻止而不是过滤用户注入的脚本。
1; report=http://site.com/report – 这个只有chrome和webkit内核的浏览器支持,这种模式告诉浏览器当发现疑似xss攻击的时候就将这部分数据post到指定地址。

// 通常不正确的设置
0; mode=block; – 记住当配置为0的时候,即使加了mode=block选项也是没有效果的。需要指出的是,chrome在发现这种错误的配置后还是会开启xss防护。
1 mode=block; – 数字和选项之间必须是用分号分割,逗号和空格都是错误的。但是这种错误配置情况下,IE和chrome还是默认会清洗xss攻击,但是不会阻拦。


  如何检测?

  如果过滤器检测或阻拦了一个反射性xss以后,IE会弹出一个对话框。当设置为1时,chrome会隐藏对反射性xss的输出。如果是设置为 1; mode=block ,那么chrome会直接将user-agent置为一个空值:, URL  这种形式。

三、X-Content-Type-Options

  互联网上的资源有各种类型,通常浏览器会根据响应头的Content-Type字段来分辨它们的类型。例如:"text/html"代表html文档,"image/png"是PNG图片,"text/css"是CSS样式文档。然而,有些资源的Content-Type是错的或者未定义。这时,某些浏览器会启用MIME-sniffing来猜测该资源的类型,解析内容并执行。

  例如,我们即使给一个html文档指定Content-Type为"text/plain",在IE8-中这个文档依然会被当做html来解析。利用浏览器的这个特性,攻击者甚至可以让原本应该解析为图片的请求被解析为JavaScript。

  这个header主要用来防止在IE9、chrome和safari中的MIME类型混淆攻击。firefox目前对此还存在争议。通常浏览器可以通过嗅探内容本身的方法来决定它是什么类型,而不是看响应中的content-type值。通过设置 X-Content-Type-Options:如果content-type和期望的类型匹配,则不需要嗅探,只能从外部加载确定类型的资源。举个例子,如果加载了一个样式表,那么资源的MIME类型只能是text/css。



// 正确的设置
nosniff – 这个是唯一正确的设置,必须这样。

// 通常不正确的设置
‘nosniff’ – 引号是不允许的
: nosniff – 冒号也是错误的


  如何检测?

  在IE和chrome中打开开发者工具,在控制台中观察配置了nosniff和没有配置nosniff的输出有啥区别。

四、如何避免

  通过下面这个响应头可以禁用浏览器的类型猜测行为

  打开nginx.conf,文件位置一般在安装目录 /usr/local/nginx/conf 里。

  然后在http配置代码块里某一行添加如下语句即可



add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";


浅析Web安全漏洞里的X-Frame-Options、X-XSS-Protection、X-Content-Type-Options响应头配置以及如何通过nginx配置避免_加载

五、Strict-Transport-Security

  Strict Transport Security (STS) 是用来配置浏览器和服务器之间安全的通信。它主要是用来防止中间人攻击,因为它强制所有的通信都走TLS。目前IE还不支持 STS头。需要注意的是,在普通的http请求中配置STS是没有作用的,因为攻击者很容易就能更改这些值。为了防止这样的现象发生,很多浏览器内置了一 个配置了STS的站点list。



// 正确的设置  
// 注意下面的值必须在https中才有效,如果是在http中配置会没有效果。

max-age=31536000 – 告诉浏览器将域名缓存到STS list里面,时间是一年。
max-age=31536000; includeSubDomains – 告诉浏览器将域名缓存到STS list里面并且包含所有的子域名,时间是一年。
max-age=0 – 告诉浏览器移除在STS缓存里的域名,或者不保存此域名。

// 通常不正确的设置
// 直接将includeSubDomains设置为 https://www.example.com ,但是用户依然可以通过 http://example.com 来访问此站点。如果example.com 并没有跳转到 https://example.com 并设置 STS header,那么访问 http://www.example.com 就会直接被浏览器重定向到 https://www.example.com 。
max-age=60 – 这个只设置域名保存时间为60秒。这个时间太短了,可能并不能很好的保护用户,可以尝试先通过http来访问站点,这样可以缩短传输时间。
max-age=31536000 includeSubDomains – max-age 和 includeSubDomains 直接必须用分号分割。这种情况下,即使max-age的值设置的没有问题,chrome也不会将此站点保存到STS缓存中。
max-age=31536000, includeSubDomains – 同上面情况一样。
max-age=0 – 尽管这样在技术上是没有问题的,但是很多站点可能在处理起来会出差错,因为0可能意味着永远不过期。


  如何检测

  判断一个主机是否在你的STS缓存中,chrome可以通过访问chrome://net-internals/#hsts,首先,通过域名请求选 项来确认此域名是否在你的STS缓存中。然后,通过https访问这个网站,尝试再次请求返回的STS头,来决定是否添加正确。

六、Access-Control-Allow-Origin

  Access-Control-Allow-Origin是从Cross Origin Resource Sharing (CORS)中分离出来的。这个header是决定哪些网站可以访问资源,通过定义一个通配符来决定是单一的网站还是所有网站可以访问我们的资源。需要注意的是,如果定义了通配符,那么 Access-Control-Allow-Credentials选项就无效了,而且user-agent的cookies不会在请求里发送。



// 正确的设置
* – 通配符允许任何远程资源来访问含有Access-Control-Allow-Origin 的内容。
http://www.example.com – 只允许特定站点才能访问(http://[host], 或者 https://[host])

// 通常不正确的设置
http://example.com, http://web2.example.com – 多个站点是不支持的,只能配置一个站点。
*.example.com – 只允许单一的站点
http://*.example.com – 同上面一样


  如何检测?很容易就能确定这个header是否被设置的正确,因为如果设置错误的话,CORS请求就会接收不到数据。