1,点击劫持
# 点击劫持(ClickJacking)是一种视觉上的欺骗手段。大概有两种方式,
# 一是攻击者使用一个透明的iframe,覆盖在一个网页上,然后诱使用户在该页面上进行操作,此时用户将在不知情的情况下点击透明的iframe页面;
# 二是攻击者使用一张图片覆盖在网页,遮挡网页原有位置的含义;
# 点击劫持(ClickJacking)是一种视觉上的欺骗手段。大概有两种方式,
# 一是攻击者使用一个透明的iframe,覆盖在一个网页上,然后诱使用户在该页面上进行操作,此时用户将在不知情的情况下点击透明的iframe页面;
# 二是攻击者使用一张图片覆盖在网页,遮挡网页原有位置的含义;
- 解释:
2,X-Frame-Options
X-Frame-Options HTTP
响应头是微软提出来的一个HTTP响应头,主要用来给浏览器指示允许一个页面可否在 <frame>
, <iframe>
或者 <object>
中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (ClickJacking{注1}) 的攻击
使用X-Frame-Options有三个值
# DENY # 表示该页面不允许在frame中展示,即使在相同域名的页面中嵌套也不允许
# SAMEORIGIN # 表示该页面可以在相同域名页面的frame中展示
# ALLOW-FROM url # 表示该页面可以在指定来源的frame中展示
如果设置为 DENY,不光在别人的网站 frame 嵌入时会无法加载,在同域名页面中同样会无法加载。另一方面,如果设置为SAMEORIGIN,那么页面就可以在同域名页面的 frame 中嵌套。
PS:目前发现这个HTTP响应头会带来的问题就是百度统计中的“热点追踪(页面点击图)”功能会失效,这也说明百度统计的“热点追踪(页面点击图)”使用的是 frame 嵌入引用网页的形式,这时候大家可以使用 X-Frame-Options 的ALLOW-FROM uri来指定百度统计域名为可 frame 嵌入域名即可。具体在Nginx里可以采用如下的方式添加响应头
比如:
add_header X-Frame-Options:ALLOW-FROM https://tongji.baidu.com;
add_header X-Frame-Options:SAMEORIGIN;
add_header X-Frame-Options ALLOWALL; #允许所有域名iframe
add_header Set-Cookie "Path=/; HttpOnly; Secure";
# DENY # 表示该页面不允许在frame中展示,即使在相同域名的页面中嵌套也不允许
# SAMEORIGIN # 表示该页面可以在相同域名页面的frame中展示
# ALLOW-FROM url # 表示该页面可以在指定来源的frame中展示
如果设置为 DENY,不光在别人的网站 frame 嵌入时会无法加载,在同域名页面中同样会无法加载。另一方面,如果设置为SAMEORIGIN,那么页面就可以在同域名页面的 frame 中嵌套。
PS:目前发现这个HTTP响应头会带来的问题就是百度统计中的“热点追踪(页面点击图)”功能会失效,这也说明百度统计的“热点追踪(页面点击图)”使用的是 frame 嵌入引用网页的形式,这时候大家可以使用 X-Frame-Options 的ALLOW-FROM uri来指定百度统计域名为可 frame 嵌入域名即可。具体在Nginx里可以采用如下的方式添加响应头
比如:
add_header X-Frame-Options:ALLOW-FROM https://tongji.baidu.com;
add_header X-Frame-Options:SAMEORIGIN;
add_header X-Frame-Options ALLOWALL; #允许所有域名iframe
add_header Set-Cookie "Path=/; HttpOnly; Secure";
X-Frame-Options
X-Frame-Options 响应头用于防范点击劫持(Click Jacking)。
响应头格式为:
x-frame-options: ${value}
可填入的 value 有三种:
allow-from ${domain} 不允许被指定域名以外的页面嵌入
sameorigin 不允许被站点自身域名以外的页面嵌入
deny 不允许被任何页面嵌入
由于嵌入的页面不会加载,这就减少了点击劫持的发生。
在 Nginx 中的配置:
add_header X-Frame-Options deny;
X-Content-Type-Options
互联网上的资源多种多样,在 web 浏览方面,一般浏览器会根据响应头的 Content-Type 字段分辨资源的类型。例如,”text/html” 表示 html 文件,”text/css” 表示 CSS 样式文件,”application/javascript” 表示 js 代码。但有时,会出现 Content-Type 未定义或无效值的资源,这时浏览器会调用 MIME-sniffing 来猜测该资源的类型。攻击者利用浏览器的这种猜测,例如可以让原本应解析为图片的请求被解析为恶意 JavaScript 脚本,被攻击者成功入侵。
为了防范这类攻击,需要禁用浏览器的资源类型猜测。
通过返回下面这个响应头:
X-Content-Type-Options: nosniff
其中,这个响应头的值只能是 nosniff。
在 Nginx 中的配置:
add_header X-Content-Type-Options nosniff;
X-XSS-Protection
顾名思义,这个响应头用于防范 XSS 攻击。
该响应头已具有广泛浏览器支持,并且主流浏览器基本默认开启 XSS 保护。倒是用这个头可以关闭它。虽然一般不建议这样做。
响应头格式为:
X-Xss-Protection: ${value}
可填入的值有三种:
0 禁用 XSS 保护
1 启用 XSS 保护
1; mode=block 启用 XSS 保护,并规定在检查到 XSS 攻击时停止页面渲染
在 Nginx 中的配置:
add_header X-Xss-Protection "1; mode=block" ;
X-Frame-Options
X-Frame-Options 响应头用于防范点击劫持(Click Jacking)。
响应头格式为:
x-frame-options: ${value}
可填入的 value 有三种:
allow-from ${domain} 不允许被指定域名以外的页面嵌入
sameorigin 不允许被站点自身域名以外的页面嵌入
deny 不允许被任何页面嵌入
由于嵌入的页面不会加载,这就减少了点击劫持的发生。
在 Nginx 中的配置:
add_header X-Frame-Options deny;
X-Content-Type-Options
互联网上的资源多种多样,在 web 浏览方面,一般浏览器会根据响应头的 Content-Type 字段分辨资源的类型。例如,”text/html” 表示 html 文件,”text/css” 表示 CSS 样式文件,”application/javascript” 表示 js 代码。但有时,会出现 Content-Type 未定义或无效值的资源,这时浏览器会调用 MIME-sniffing 来猜测该资源的类型。攻击者利用浏览器的这种猜测,例如可以让原本应解析为图片的请求被解析为恶意 JavaScript 脚本,被攻击者成功入侵。
为了防范这类攻击,需要禁用浏览器的资源类型猜测。
通过返回下面这个响应头:
X-Content-Type-Options: nosniff
其中,这个响应头的值只能是 nosniff。
在 Nginx 中的配置:
add_header X-Content-Type-Options nosniff;
X-XSS-Protection
顾名思义,这个响应头用于防范 XSS 攻击。
该响应头已具有广泛浏览器支持,并且主流浏览器基本默认开启 XSS 保护。倒是用这个头可以关闭它。虽然一般不建议这样做。
响应头格式为:
X-Xss-Protection: ${value}
可填入的值有三种:
0 禁用 XSS 保护
1 启用 XSS 保护
1; mode=block 启用 XSS 保护,并规定在检查到 XSS 攻击时停止页面渲染
在 Nginx 中的配置:
add_header X-Xss-Protection "1; mode=block" ;
- nginx配置
允许单个域名iframe嵌套
add_header X-Frame-Options ALLOW-FROM http://xxx.com/;
允许多个域名iframe嵌套,注意这里是用逗号分隔
add_header X-Frame-Options "ALLOW-FROM http://xxx.com/,https://xxx.cn/";
3,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。在Nginx里通过下面这个响应头可以禁用浏览器的类型猜测行为:
# X-Content-Type-Options HTTP 消息头相当于一个提示标志,被服务器用来提示客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定,
# 而不能对其进行修改。这就禁用了客户端的 MIME 类型嗅探行为,换句话说,也就是意味着网站管理员确定自己的设置没有问题。
# X-Content-Type-Options响应头的缺失使得目标URL更易遭受跨站脚本攻击。
# add_header X-Content-Type-Options: nosniff;
这个响应头的值只能是nosniff
互联网上的资源有各种类型,通常浏览器会根据响应头的Content-Type字段来分辨它们的类型。例如:text/html代表html文档,image/png是PNG图片,text/css是CSS样式文档。然而,有些资源的Content-Type是错的或者未定义。这时,某些浏览器会启用MIME-sniffing来猜测该资源的类型,解析内容并执行。
例如,我们即使给一个html文档指定Content-Type为text/plain,在IE8-中这个文档依然会被当做html来解析。利用浏览器的这个特性,攻击者甚至可以让原本应该解析为图片的请求被解析为JavaScript。在Nginx里通过下面这个响应头可以禁用浏览器的类型猜测行为:
# X-Content-Type-Options HTTP 消息头相当于一个提示标志,被服务器用来提示客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定,
# 而不能对其进行修改。这就禁用了客户端的 MIME 类型嗅探行为,换句话说,也就是意味着网站管理员确定自己的设置没有问题。
# X-Content-Type-Options响应头的缺失使得目标URL更易遭受跨站脚本攻击。
# add_header X-Content-Type-Options: nosniff;
这个响应头的值只能是nosniff
4,Content-Security-Policy
W3C 的 Content Security Policy,简称 CSP。顾名思义,这个规范与内容安全有关,主要是用来定义页面可以加载哪些资源,减少 XSS 的发生。
Chrome 扩展已经引入了 CSP,通过 manifest.json 中的 content_security_policy 字段来定义。一些现代浏览器也支持通过响应头来定义 CSP。下面我们主要介绍如何通过响应头来使用 CSP,Chrome 扩展中 CSP 的使用可以参考 Chrome 官方文档。
# HTTP 响应头Content-Security-Policy允许站点管理者控制用户代理能够为指定的页面加载哪些资源。
# 除了少数例外情况,设置的政策主要涉及指定服务器的源和脚本结束点。
# Content-Security-Policy响应头的缺失使得目标URL更易遭受跨站脚本攻击。
# HTTP 响应头Content-Security-Policy允许站点管理者控制用户代理能够为指定的页面加载哪些资源。
# 除了少数例外情况,设置的政策主要涉及指定服务器的源和脚本结束点。
# Content-Security-Policy响应头的缺失使得目标URL更易遭受跨站脚本攻击。
4.1 如何使用
# 要使用 CSP,只需要服务端输出类似这样的响应头就行了:
Content-Security-Policy: default-src 'self'
# default-src 是 CSP 指令,多个指令之间用英文分号分割;'self' 是指令值,多个指令值用英文空格分割。目前,有这些 CSP 指令:
# 要使用 CSP,只需要服务端输出类似这样的响应头就行了:
Content-Security-Policy: default-src 'self'
# default-src 是 CSP 指令,多个指令之间用英文分号分割;'self' 是指令值,多个指令值用英文空格分割。目前,有这些 CSP 指令:
指令 | 指令值示例 | 说明 |
---|---|---|
default-src | 'self' cnd.a.com | 定义针对所有类型(js、image、css、web font,ajax 请求,iframe,多媒体等)资源的默认加载策略,某类型资源如果没有单独定义策略,就使用默认的。 |
script-src | 'self' js.a.com | 定义针对 JavaScript 的加载策略。 |
style-src | 'self' css.a.com | 定义针对样式的加载策略。 |
img-src | 'self' img.a.com | 定义针对图片的加载策略。 |
connect-src | 'self' | 针对 Ajax 、WebSocket 等请求的加载策略。不允许的情况下,浏览器会模拟一个状态为 400 的响。 |
font-src | font.a.com | 针对 WebFont 的加载策略。 |
object-src | 'self' | 针对 <object> 、<embed> 或 <applet> 等标签引入的 flash 等插件的加载策略。 |
media-src | media.a.com | 针对 <audio> 或 <video> 等标签引入的 HTML 多媒体的加载策略。 |
frame-src | 'self' | 针对 frame 的加载策略。 |
sandbox | allow-forms | 对请求的资源启用 sandbox(类似于 iframe 的 sandbox 属性)。 |
report-uri | /report-uri | 告诉浏览器如果请求的资源不被策略允许时,往哪个地址提交日志信息。 特别的:如果想让浏览器只汇报日志,不阻止任何内容,可以改用 Content-Security-Policy-Report-Only 头。 |
指令值 | 指令示例 | 说明 |
---|---|---|
img-src | 允许任何内容。 | |
'none' | img-src 'none' | 不允许任何内容。 |
'self' | img-src 'self' | 允许来自相同来源的内容(相同的协议、域名和端口)。 |
data: | img-src data: | 允许 data: 协议(如 base64 编码的图片)。 |
www.a.com | img-src img.a.com | 允许加载指定域名的资源。 |
.a.com | img-src .a.com | 允许加载 a.com 任何子域的资源。 |
https://img.com | img-src https://img.com | 允许加载 img.com 的 https 资源(协议需匹配)。 |
https: img-src | https: | 允许加载 https 资源。 |
'unsafe-inline' | script-src 'unsafe-inline' | 允许加载 inline 资源(例如常见的 style 属性,onclick,inline js 和 inline css 等等)。 |
'unsafe-eval' | script-src 'unsafe-eval' | 允许加载动态 js 代码,例如 eval() |
从上面的介绍可以看到,CSP 协议可以控制的内容非常多。而且如果不特别指定 'unsafe-inline' 时,页面上所有 inline 样式和脚本都不会执行;不特别指定 'unsafe-eval',页面上不允许使用 new Function,setTimeout,eval 等方式执行动态代码。在限制了页面资源来源之后,被 XSS 的风险确实小不少。
当然,仅仅依靠 CSP 来防范 XSS 是远远不够的,不支持全部浏览器是它的硬伤。不过,鉴于低廉的开发成本,加上也没什么坏处
5,Strict Transport Security
5.1 什么是Strict Transport Security
一个网站接受一个HTTP的请求,然后跳转到HTTPS,用户可能在开始跳转前,通过没有加密的方式和服务器对话,比如,用户输入http://foo.com或者直接foo.com。这样存在中间人攻击潜在威胁,跳转过程可能被恶意网站利用来直接接触用户信息,而不是原来的加密信息。网站通过HTTP Strict Transport Security通知浏览器,这个网站禁止使用HTTP方式加载,浏览器应该自动把所有尝试使用HTTP的请求自动替换为HTTPS请求
有的网站开启了https,但为了照顾用户的使用体验(因为用户总是很赖的,一般不会主动键入https,而是直接输入域名, 直接输入域名访问,默认就是http访问)同时也支持http访问,当用户http访问的时候,就会返回给用户一个302重定向,重定向到https的地址,然后后续的访问都使用https传输,这种通信模式看起来貌似没有问题,但细致分析,就会发现种通信模式也存在一个风险,那就是这个302重定向可能会被劫持篡改,如果被改成一个恶意的或者钓鱼的https站点,然后,你懂得,一旦落入钓鱼站点,数据还有安全可言吗?
对于篡改302的攻击,建议服务器开启HTTP Strict Transport Security功能,这个功能的含义是:
当用户已经安全的登录开启过htst功能的网站 (支持hsts功能的站点会在响应头中插入:Strict-Transport-Security) 之后,支持htst的浏览器(比如chrome. firefox)会自动将这个域名加入到HSTS列表,下次即使用户使用http访问这个网站,支持htst功能的浏览器就会自动发送https请求(前提是用户没有清空缓存,如果清空了缓存第一次访问还是明文,后续浏览器接收到服务器响应头中的Strict-Transport-Security,就会把域名加入到hsts缓存中,然后才会在发送请求前将http内部转换成https),而不是先发送http,然后重定向到https,这样就能避免中途的302重定向URL被篡改。进一步提高通信的安全性。
上面是我自己的理解,下面是owasp中文站点关于hsts的描述:
HSTS的作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。服务器开启HSTS的方法是,当客户端通过HTTPS发出请求时,在服务器返回的超文本传输协议响应头中包含Strict-Transport-Security字段。非加密传输时设置的HSTS字段无效。
比如,https://example.com/ 的响应头含有Strict-Transport-Security: max-age=31536000; includeSubDomains。这意味着两点:
在接下来的一年(即31536000秒)中,浏览器只要向example.com或其子域名发送HTTP请求时,必须采用HTTPS来发起连接。比如,用户点击超链接或在地址栏输入 http://www.example.com/ ,浏览器应当自动将 http 转写成 https,然后直接向 https://www.example.com/ 发送请求。
在接下来的一年中,如果 example.com 服务器发送的TLS证书无效,用户不能忽略浏览器警告继续访问网站。
HSTS可以用来抵御SSL剥离攻击。SSL剥离攻击是中间人攻击的一种,由Moxie Marlinspike于2009年发明。他在当年的黑帽大会上发表的题为“New Tricks For Defeating SSL In Practice”的演讲中将这种攻击方式公开。SSL剥离的实施方法是阻止浏览器与服务器创建HTTPS连接。它的前提是用户很少直接在地址栏输入https://,用户总是通过点击链接或3xx重定向,从HTTP页面进入HTTPS页面。所以攻击者可以在用户访问HTTP页面时替换所有https://开头的链接为http://,达到阻止HTTPS的目的。
HSTS可以很大程度上解决SSL剥离攻击,因为只要浏览器曾经与服务器创建过一次安全连接,之后浏览器会强制使用HTTPS,即使链接被换成了HTTP
另外,如果中间人使用自己的自签名证书来进行攻击,浏览器会给出警告,但是许多用户会忽略警告。HSTS解决了这一问题,一旦服务器发送了HSTS字段,用户将不再允许忽略警告。
0×03. Strict-Transport-Security的一些不足
用户首次访问某网站是不受HSTS保护的。这是因为首次访问时,浏览器还未收到HSTS,所以仍有可能通过明文HTTP来访问。解决这个不足目前有两种方案,一是浏览器预置HSTS域名列表,Google Chrome、Firefox、Internet Explorer和Spartan实现了这一方案。二是将HSTS信息加入到域名系统记录中。但这需要保证DNS的安全性,也就是需要部署域名系统安全扩展。截至2014年这一方案没有大规模部署。
由于HSTS会在一定时间后失效(有效期由max-age指定),所以浏览器是否强制HSTS策略取决于当前系统时间。部分操作系统经常通过网络时间协议更新系统时间,如Ubuntu每次连接网络时,OS X Lion每隔9分钟会自动连接时间服务器。攻击者可以通过伪造NTP信息,设置错误时间来绕过HSTS。解决方法是认证NTP信息,或者禁止NTP大幅度增减时间。比如Windows 8每7天更新一次时间,并且要求每次NTP设置的时间与当前时间不得超过15小时
有的网站开启了https,但为了照顾用户的使用体验(因为用户总是很赖的,一般不会主动键入https,而是直接输入域名, 直接输入域名访问,默认就是http访问)同时也支持http访问,当用户http访问的时候,就会返回给用户一个302重定向,重定向到https的地址,然后后续的访问都使用https传输,这种通信模式看起来貌似没有问题,但细致分析,就会发现种通信模式也存在一个风险,那就是这个302重定向可能会被劫持篡改,如果被改成一个恶意的或者钓鱼的https站点,然后,你懂得,一旦落入钓鱼站点,数据还有安全可言吗?
对于篡改302的攻击,建议服务器开启HTTP Strict Transport Security功能,这个功能的含义是:
当用户已经安全的登录开启过htst功能的网站 (支持hsts功能的站点会在响应头中插入:Strict-Transport-Security) 之后,支持htst的浏览器(比如chrome. firefox)会自动将这个域名加入到HSTS列表,下次即使用户使用http访问这个网站,支持htst功能的浏览器就会自动发送https请求(前提是用户没有清空缓存,如果清空了缓存第一次访问还是明文,后续浏览器接收到服务器响应头中的Strict-Transport-Security,就会把域名加入到hsts缓存中,然后才会在发送请求前将http内部转换成https),而不是先发送http,然后重定向到https,这样就能避免中途的302重定向URL被篡改。进一步提高通信的安全性。
上面是我自己的理解,下面是owasp中文站点关于hsts的描述:
HSTS的作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。服务器开启HSTS的方法是,当客户端通过HTTPS发出请求时,在服务器返回的超文本传输协议响应头中包含Strict-Transport-Security字段。非加密传输时设置的HSTS字段无效。
比如,https://example.com/ 的响应头含有Strict-Transport-Security: max-age=31536000; includeSubDomains。这意味着两点:
在接下来的一年(即31536000秒)中,浏览器只要向example.com或其子域名发送HTTP请求时,必须采用HTTPS来发起连接。比如,用户点击超链接或在地址栏输入 http://www.example.com/ ,浏览器应当自动将 http 转写成 https,然后直接向 https://www.example.com/ 发送请求。
在接下来的一年中,如果 example.com 服务器发送的TLS证书无效,用户不能忽略浏览器警告继续访问网站。
HSTS可以用来抵御SSL剥离攻击。SSL剥离攻击是中间人攻击的一种,由Moxie Marlinspike于2009年发明。他在当年的黑帽大会上发表的题为“New Tricks For Defeating SSL In Practice”的演讲中将这种攻击方式公开。SSL剥离的实施方法是阻止浏览器与服务器创建HTTPS连接。它的前提是用户很少直接在地址栏输入https://,用户总是通过点击链接或3xx重定向,从HTTP页面进入HTTPS页面。所以攻击者可以在用户访问HTTP页面时替换所有https://开头的链接为http://,达到阻止HTTPS的目的。
HSTS可以很大程度上解决SSL剥离攻击,因为只要浏览器曾经与服务器创建过一次安全连接,之后浏览器会强制使用HTTPS,即使链接被换成了HTTP
另外,如果中间人使用自己的自签名证书来进行攻击,浏览器会给出警告,但是许多用户会忽略警告。HSTS解决了这一问题,一旦服务器发送了HSTS字段,用户将不再允许忽略警告。
0×03. Strict-Transport-Security的一些不足
用户首次访问某网站是不受HSTS保护的。这是因为首次访问时,浏览器还未收到HSTS,所以仍有可能通过明文HTTP来访问。解决这个不足目前有两种方案,一是浏览器预置HSTS域名列表,Google Chrome、Firefox、Internet Explorer和Spartan实现了这一方案。二是将HSTS信息加入到域名系统记录中。但这需要保证DNS的安全性,也就是需要部署域名系统安全扩展。截至2014年这一方案没有大规模部署。
由于HSTS会在一定时间后失效(有效期由max-age指定),所以浏览器是否强制HSTS策略取决于当前系统时间。部分操作系统经常通过网络时间协议更新系统时间,如Ubuntu每次连接网络时,OS X Lion每隔9分钟会自动连接时间服务器。攻击者可以通过伪造NTP信息,设置错误时间来绕过HSTS。解决方法是认证NTP信息,或者禁止NTP大幅度增减时间。比如Windows 8每7天更新一次时间,并且要求每次NTP设置的时间与当前时间不得超过15小时
6, X-XSS-Protection
这个响应头是用来防范XSS的。最早我是在介绍IE8的文章里看到这个,现在主流浏览器都支持,并且默认都开启了XSS保护,用这个header可以关闭它。它有几种配置
#减少点击劫持
add_header X-Xss-Protection "1;mode=block" always; #开启XSS过滤器
add_header X-Content-Type-Options 'nosniff'; #禁止嗅探文件类型
0:# 禁用XSS保护;
1:# 启用XSS保护;
1; # mode=block:启用XSS保护,并在检查到XSS攻击时,停止渲染页面(例如IE8中,检查到攻击时,整个页面会被一个#替换);
# HTTP X-XSS-Protection 响应头是 Internet Explorer,Chrome 和 Safari 的一个特性,
# 当检测到跨站脚本攻击 (XSS)时,浏览器将停止加载页面。
# X-XSS-Protection响应头的缺失使得目标URL更易遭受跨站脚本攻击。
# 浏览器提供的XSS保护机制并不完美,但是开启后仍然可以提升攻击难度,总之没有特别的理由,不要关闭它。
#减少点击劫持
add_header X-Xss-Protection "1;mode=block" always; #开启XSS过滤器
add_header X-Content-Type-Options 'nosniff'; #禁止嗅探文件类型
0:# 禁用XSS保护;
1:# 启用XSS保护;
1; # mode=block:启用XSS保护,并在检查到XSS攻击时,停止渲染页面(例如IE8中,检查到攻击时,整个页面会被一个#替换);
# HTTP X-XSS-Protection 响应头是 Internet Explorer,Chrome 和 Safari 的一个特性,
# 当检测到跨站脚本攻击 (XSS)时,浏览器将停止加载页面。
# X-XSS-Protection响应头的缺失使得目标URL更易遭受跨站脚本攻击。
# 浏览器提供的XSS保护机制并不完美,但是开启后仍然可以提升攻击难度,总之没有特别的理由,不要关闭它。
CSP
什么是 XSS 攻击
跨站脚本(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了 HTML 以及用户端脚本语言。
跨域脚本攻击(XSS 攻击)通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是 JavaScript,但实际上也可以包括 Java,VBScript,ActiveX,Flash 甚至是普通的 HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、私密网页、会话和 cookie 等各种内容。
为了防止它,要采取很多编程对策,成本较高。很多人发出呼声,能不能让浏览器自己禁止外部注入恶意脚本呢?这时,CSP 应运而生
什么是 CSP
CSP 定义了页面中哪些资源可以加载。
所以 CSP 的实质就是白名单,Web 端明确地告诉客户端,只有哪些外部资源可以加载可以执行,相当于提供一份白名单,“我的规则里没提到的全部拜拜,不给进来”。
因此 CSP 大大增强了网页的安全性。即使攻击者发现可趁之机,也没法注入脚本
CSP 的两种启用方式
一种是使用网页的 标签
<meta http-equiv="Content-Security-Policy" content="default-src ${value}; script-src ${value}; style-src ${value}; img-src ${value}; font-src ${value}; media-src ${value}; object-src ${value}; connect-src ${value}; child-src ${value}; sandbox ${value}; report-uri ${value}">
<meta http-equiv="Content-Security-Policy" content="default-src ${value}; script-src ${value}; style-src ${value}; img-src ${value}; font-src ${value}; media-src ${value}; object-src ${value}; connect-src ${value}; child-src ${value}; sandbox ${value}; report-uri ${value}">
一种是使用 HTTP 响应头
Content-Security-Policy: "default-src ${value}; script-src ${value}; style-src ${value}; img-src ${value}; font-src ${value}; media-src ${value}; object-src ${value}; connect-src ${value}; child-src ${value}; sandbox ${value}; report-uri ${value}"
Content-Security-Policy: "default-src ${value}; script-src ${value}; style-src ${value}; img-src ${value}; font-src ${value}; media-src ${value}; object-src ${value}; connect-src ${value}; child-src ${value}; sandbox ${value}; report-uri ${value}"
CSP 规则
http://note.youdao.com/noteshare?id=a6f38bb91d2cf0af9e78e3edb45e5322
CSP 在 Nginx 中的启用
add_header Content-Security-Policy "default-src ${value}; script-src ${value}; style-src ${value}; img-src ${value}; font-src ${value}; media-src ${value}; object-src ${value}; connect-src ${value}; child-src ${value}; sandbox ${value}; report-uri ${value}";
add_header Content-Security-Policy "default-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://www.w3.org https://avatars0.githubusercontent.com; font-src 'none'; media-src 'none'; object-src 'none'; connect-src 'self' https://github.com https://api.github.com; child-src 'none'" always;
add_header Content-Security-Policy "default-src ${value}; script-src ${value}; style-src ${value}; img-src ${value}; font-src ${value}; media-src ${value}; object-src ${value}; connect-src ${value}; child-src ${value}; sandbox ${value}; report-uri ${value}";
add_header Content-Security-Policy "default-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://www.w3.org https://avatars0.githubusercontent.com; font-src 'none'; media-src 'none'; object-src 'none'; connect-src 'self' https://github.com https://api.github.com; child-src 'none'" always;
将下面的Nginx配置文件代码放入到对应站点的.conf配置文件[server]里,然后重启Nginx即可生效
if ($request_method !~* GET|POST) { return 444; }
#使用444错误代码可以更加减轻服务器负载压力。
#防止SQL注入
if ($query_string ~* (\$|'|--|[+|(%20)]union[+|(%20)]|[+|(%20)]insert[+|(%20)]|[+|(%20)]drop[+|(%20)]|[+|(%20)]truncate[+|(%20)]|[+|(%20)]update[+|(%20)]|[+|(%20)]from[+|(%20)]|[+|(%20)]grant[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]where[+|(%20)]|[+|(%20)]select[+|(%20)]|[+|(%20)]and[+|(%20)]|[+|(%20)]or[+|(%20)]|[+|(%20)]count[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]chr[+|(%20)]|[+|(%20)]mid[+|(%20)]|[+|(%20)]like[+|(%20)]|[+|(%20)]iframe[+|(%20)]|[\<|%3c]script[\>|%3e]|javascript|alert|webscan|dbappsecurity|style|confirm\(|innerhtml|innertext)(.*)$) { return 555; }
if ($uri ~* (/~).*) { return 501; }
if ($uri ~* (\\x.)) { return 501; }
#防止SQL注入
if ($query_string ~* "[;'<>].*") { return 509; }
if ($request_uri ~ " ") { return 509; }
if ($request_uri ~ (\/\.+)) { return 509; }
if ($request_uri ~ (\.+\/)) { return 509; }
#if ($uri ~* (insert|select|delete|update|count|master|truncate|declare|exec|\*|\')(.*)$ ) { return 503; }
#防止SQL注入
if ($request_uri ~* "(cost\()|(concat\()") { return 504; }
if ($request_uri ~* "[+|(%20)]union[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]and[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]select[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]or[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]delete[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]update[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]insert[+|(%20)]") { return 504; }
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { return 505; }
if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "proc/self/environ") { return 505; }
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") { return 505; }
if ($query_string ~ "base64_(en|de)code\(.*\)") { return 505; }
if ($query_string ~ "[a-zA-Z0-9_]=http://") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") { return 506; }
if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { return 507; }
if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") {return 507; }
if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { return 507; }
if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { return 507; }
#这里大家根据自己情况添加删减上述判断参数,cURL、wget这类的屏蔽有点儿极端了,但要“宁可错杀一千,不可放过一个”。
if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|wget|curl|Java|python) { return 508; }
#同上,大家根据自己站点实际情况来添加删减下面的屏蔽拦截参数。
if ($http_user_agent ~* "Go-Ahead-Got-It") { return 508; }
if ($http_user_agent ~* "GetWeb!") { return 508; }
if ($http_user_agent ~* "Go!Zilla") { return 508; }
if ($http_user_agent ~* "Download Demon") { return 508; }
if ($http_user_agent ~* "Indy Library") { return 508; }
if ($http_user_agent ~* "libwww-perl") { return 508; }
if ($http_user_agent ~* "Nmap Scripting Engine") { return 508; }
if ($http_user_agent ~* "~17ce.com") { return 508; }
if ($http_user_agent ~* "WebBench*") { return 508; }
if ($http_user_agent ~* "spider") { return 508; } #这个会影响国内某些搜索引擎爬虫,比如:搜狗
#拦截各恶意请求的UA,可以通过分析站点日志文件或者waf日志作为参考配置。
if ($http_referer ~* 17ce.com) { return 509; }
#拦截17ce.com站点测速节点的请求,所以明月一直都说这些测速网站的数据仅供参考不能当真的。
if ($http_referer ~* WebBench*") { return 509; }
#拦截WebBench或者类似压力测试工具,其他工具只需要更换名称即可
if ($request_method !~* GET|POST) { return 444; }
#使用444错误代码可以更加减轻服务器负载压力。
#防止SQL注入
if ($query_string ~* (\$|'|--|[+|(%20)]union[+|(%20)]|[+|(%20)]insert[+|(%20)]|[+|(%20)]drop[+|(%20)]|[+|(%20)]truncate[+|(%20)]|[+|(%20)]update[+|(%20)]|[+|(%20)]from[+|(%20)]|[+|(%20)]grant[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]where[+|(%20)]|[+|(%20)]select[+|(%20)]|[+|(%20)]and[+|(%20)]|[+|(%20)]or[+|(%20)]|[+|(%20)]count[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]chr[+|(%20)]|[+|(%20)]mid[+|(%20)]|[+|(%20)]like[+|(%20)]|[+|(%20)]iframe[+|(%20)]|[\<|%3c]script[\>|%3e]|javascript|alert|webscan|dbappsecurity|style|confirm\(|innerhtml|innertext)(.*)$) { return 555; }
if ($uri ~* (/~).*) { return 501; }
if ($uri ~* (\\x.)) { return 501; }
#防止SQL注入
if ($query_string ~* "[;'<>].*") { return 509; }
if ($request_uri ~ " ") { return 509; }
if ($request_uri ~ (\/\.+)) { return 509; }
if ($request_uri ~ (\.+\/)) { return 509; }
#if ($uri ~* (insert|select|delete|update|count|master|truncate|declare|exec|\*|\')(.*)$ ) { return 503; }
#防止SQL注入
if ($request_uri ~* "(cost\()|(concat\()") { return 504; }
if ($request_uri ~* "[+|(%20)]union[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]and[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]select[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]or[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]delete[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]update[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]insert[+|(%20)]") { return 504; }
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { return 505; }
if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "proc/self/environ") { return 505; }
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") { return 505; }
if ($query_string ~ "base64_(en|de)code\(.*\)") { return 505; }
if ($query_string ~ "[a-zA-Z0-9_]=http://") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") { return 506; }
if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { return 507; }
if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") {return 507; }
if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { return 507; }
if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { return 507; }
#这里大家根据自己情况添加删减上述判断参数,cURL、wget这类的屏蔽有点儿极端了,但要“宁可错杀一千,不可放过一个”。
if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|wget|curl|Java|python) { return 508; }
#同上,大家根据自己站点实际情况来添加删减下面的屏蔽拦截参数。
if ($http_user_agent ~* "Go-Ahead-Got-It") { return 508; }
if ($http_user_agent ~* "GetWeb!") { return 508; }
if ($http_user_agent ~* "Go!Zilla") { return 508; }
if ($http_user_agent ~* "Download Demon") { return 508; }
if ($http_user_agent ~* "Indy Library") { return 508; }
if ($http_user_agent ~* "libwww-perl") { return 508; }
if ($http_user_agent ~* "Nmap Scripting Engine") { return 508; }
if ($http_user_agent ~* "~17ce.com") { return 508; }
if ($http_user_agent ~* "WebBench*") { return 508; }
if ($http_user_agent ~* "spider") { return 508; } #这个会影响国内某些搜索引擎爬虫,比如:搜狗
#拦截各恶意请求的UA,可以通过分析站点日志文件或者waf日志作为参考配置。
if ($http_referer ~* 17ce.com) { return 509; }
#拦截17ce.com站点测速节点的请求,所以明月一直都说这些测速网站的数据仅供参考不能当真的。
if ($http_referer ~* WebBench*") { return 509; }
#拦截WebBench或者类似压力测试工具,其他工具只需要更换名称即可
案例
google+
# x-content-type-options: nosniff
# x-frame-options: SAMEORIGIN
# x-xss-protection: 1; mode=block
# x-content-type-options: nosniff
# x-frame-options: SAMEORIGIN
# x-xss-protection: 1; mode=block
Twitter
# strict-transport-security: max-age=631138519
# x-frame-options: SAMEORIGIN
# x-xss-protection: 1; mode=block
# strict-transport-security: max-age=631138519
# x-frame-options: SAMEORIGIN
# x-xss-protection: 1; mode=block
Paypal
# X-Frame-Options: SAMEORIGIN
# Strict-Transport-Security: max-age=14400
# X-Frame-Options: SAMEORIGIN
# Strict-Transport-Security: max-age=14400
facebook
strict-transport-security: max-age=60
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 0
content-security-policy: default-src *;script-src https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.google-analytics.com *.virtualearth.net *.google.com 127.0.0.1:* *.spotilocal.com:* chrome-extension://lifbcibllhkdhoafpjfnlhfpfgnpldfl 'unsafe-inline' 'unsafe-eval' https://*.akamaihd.net http://*.akamaihd.net;style-src * 'unsafe-inline';connect-src https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.spotilocal.com:* https://*.akamaihd.net ws://*.facebook.com:* http://*.akamaihd.net https://fb.scanandcleanlocal.com:*;
strict-transport-security: max-age=60
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 0
content-security-policy: default-src *;script-src https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.google-analytics.com *.virtualearth.net *.google.com 127.0.0.1:* *.spotilocal.com:* chrome-extension://lifbcibllhkdhoafpjfnlhfpfgnpldfl 'unsafe-inline' 'unsafe-eval' https://*.akamaihd.net http://*.akamaihd.net;style-src * 'unsafe-inline';connect-src https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.spotilocal.com:* https://*.akamaihd.net ws://*.facebook.com:* http://*.akamaihd.net https://fb.scanandcleanlocal.com:*;