配置 HSTS(HTTP Strict-Transport-Security头缺失或不安全)
HSTS是一种 安全策略,即— HTTP Strict Transport Security,HTTP严格传输安全。假设TLS连接没有错误,兼容的浏览器将会在 max-age 参数指定的保留期内激活HSTS。它告诉浏览器:“只能用HTTPS来访问我的网站,不要用HTTP哦!”这样,即使有人尝试用不安全的方式(HTTP)来访问网站,浏览器也会自动切换到安全的方式(HTTPS)。
一旦站点启用了HSTS,用户的后续访问就会直接进入443端口,然而你还需要确保那些访问到80端口的用户能被重定向到正确的地址。为了支持这个重定向,而且由于在明文响应中HSTS响应头是不被允许的。
需要配置重定向
HTTP响应中包含 Strict-Transport-Security 头实现网站HSTS,像下面这样配置,就实现了HSTS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
- 1.
Nginx配置HSTS的示例代码:
server {
listen 80;
server_name example.com;
# 重定向所有HTTP请求到HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
# SSL证书和其他SSL配置...
# 添加HSTS头部
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always ;
# 其他配置...
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
要注意 add_header 这个指令的继承方式,如果一个子配置块中设置了add_header 指令,那么在上层配置块中的 add_header 指令是不会被继承的。如果你需要在子配置中添加额外的add_header 指令,那么有关HSTS那部分要复制到子配置中。
https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header
这个配置做了什么呢?
- 重定向HTTP请求到HTTPS:在第一个server块中,我们监听HTTP 80端口,然后使用return 301 指令将所有HTTP请求重定向到HTTPS。
- 添加HSTS头部:在第二个server块中,我们监听HTTPS 443端口,并使用add_header指令添加一个名为Strict-Transport-Security的头部。这个头部告诉浏览器:“在接下来的31536000秒(也就是1年)内,只能用HTTPS来访问这个网站,而且也包括它的所有子域名。另外,如果你支持的话,请把这个策略预加载到你的缓存里。”
Strict-Transport-Security头部的参数解释:
max-age=31536000
:表示这个HSTS策略的有效期是31536000(单位是秒,31536000/3600*24 = 365天 =1年)。在这段时间内,浏览器会自动使用HTTPS来访问网站。includeSubDomains
:表示这个HSTS策略也适用于网站的所有子域名。preload
:是一个可选的参数,是一个为了解决第一次访问的用户,无法预先得知HSTS设置而创建的。它告诉浏览器:“如果你支持的话,请把这个HSTS策略预加载到你的缓存里。”这样,即使用户第一次访问网站时没有用HTTPS,浏览器也会知道应该使用HTTPS。always
:表示无论哪种请求都将HSTS的头发送给客户端,也包括错误响应。默认情况404等是不发送HSTS头的。
配置 CSP(Content-Security-Policy)
HTTP
Content-Security-Policy
响应头允许网站运营者能够控制遵循CSP的用户代理(通常是浏览器)可以为特定页面加载的资源,通过控制要启用哪些功能,以及从哪里下载内容,可以减少网站的***面。除了少数例外,策略主要涉及指定服务器来源和脚本终端节点。这有助于防范跨站点脚本G击 ( Cross-site_scripting )。CSP的主要目的是,用于检测并削弱某些特定类型的G击,包括跨站脚本(cross-ste scripting, XSS)和数据注入G击等。无论是数据盗取、网站内容污染还是恶*软件分发,这些G击都是主要的手段。例如,CSP可以完全禁止内联的JavaScript,并且控制外部代码从哪里加载。它也可以禁止动态代码执行。禁用了所有的这些源,XSS变得更加困难。一个网站通过设置 Content-Security-Policy 响应头启用所需的CSP策略。
为使 CSP 可用,你需要配置你的网络服务器返回 Content-Security-Policy HTTP 标头(有时你会看到
X-Content-Security-Policy
标头,但那是旧版本,并且你无须再如此指定它)。
句法
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy
Content-Security-Policy: <policy-directive>; <policy-directive>
- 1.
其中<policy-directive>
由以下部分组成: <directive> <value>
没有内部标点符号。
Fetch directives 通过获取指令来控制某些可能被加载的确切的资源类型的位置。
具体指令:
default-src:
默认策略script-src:
限制 JavaScript 的源地址。style-src:
样式,限制层叠样式表文件源。img-src:
限制图片和图标的源地址。connect-src:
链接,限制能通过脚本接口加载的 URL。font-src:
字体,设置允许通过 @font-face 加载的字体源地址。object-src:
插件<object>, <embed> 或者<applet>等media-src:
多媒体<audio>,<video>之类frame-src:
设置允许通过类似 <frame> 和 <iframe> 标签加载的内嵌内容的源地址。sandbox:
类似 <iframe> sandbox 属性,为请求的资源启用沙盒。Referrer-Policy:
用来指定会离开当前页面的跳转链接的 referer header 信息。可取值与含义:
*:
任意来源none:
任何来源的都不加载self:
同源,与请求同源的资源可以加载https:
要求来源是https协议的https://xxx.com:
要求来源是https协议的某个站点css.test.com:
要求来源是某个站点*.test.com:
要求来源是某个站点及其所有的子站点blob:
允许加载 Blob 资源,通常用于 Web 应用的文件处理或视频流。data:
允许使用data:
协议加载数据 URI(如内嵌图片或字体)。但这也可能被用于 XSS G击,通常建议限制使用。unsafe-inline:
行内代码可以执行'unsafe-eval':允许动态代码执行,例如 JavaScript的 eval()方法unsafe-eval:
控制多种脚本执行方法,这些方法可根据字符串创建代码。
CSP 被设计成完全向后兼容(除 CSP2 在向后兼容有明确提及的不一致; 更多细节查看 这里 章节 1.1)。不支持 CSP 的浏览器也能与实现了 CSP 的服务器正常工作,反之亦然:不支持 CSP 的浏览器只会忽略它,如常运行,默认为网页内容使用标准的同源策略。如果网站不提供 CSP 标头,浏览器也使用标准的 同源策略。
Nginx配置CSP的示例代码
这里 script-src 放开了允许内联js 'unsafe-inline'
,其实这里并不是很安全,但公司项目的前端架构已经成型改动代码工作量太大,先跟着指定的ip或域名访问这样配置着。后面有时间在出动态生成 nonce属性值的文档。
#使用 CSP
add_header Content-Security-Policy "default-src 'self' *.demo.com(该地址按需修改); script-src 'self' 'unsafe-inline' *.demo.com(该地址按需修改); connect-src 'self'; img-src * data: blob:; style-src 'self' 'unsafe-inline' 'unsafe-eval' *.demo.com(该地址按需修改) https:; frame-ancestors 'self'; font-src * https: data:";
- 1.
- 2.
页面结果:
参考文献:
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP
- https://www.w3.org/TR/CSP2/#directive-frame-ancestors
更多Nginx配置安全策略总结
“X-Content-Type-Options”头缺失或不安全
# 禁止服务器自动解析资源类型,防止浏览器对内容类型进行猜测,提升安全性
add_header X-Content-Type-Options nosniff;
- 1.
- 2.
nosniff 是禁止嗅探 ,服务器提示客户端一定按照 Content-Type 首部中的 MIME 类型来解析,而不能对其进行修改。
禁用了客户端的 MIME 类型嗅探行为,防止**代码的注入。开启 X-Content-Type-Options 要注意,要保证所传输的内容都要有正确 Content-Type 属性,要是没有这个属性,可能会造成加载不成功和无法运行;因为关闭了浏览器自动识别这一项。有些浏览器 如 IE9 ,IE11 在无法获得类型时,就不加载内容。
“X-XSS-Protection”头缺失或不安全
# 防止XSS跨站脚本G击
add_header X-Xss-Protection "1; mode=block";
- 1.
- 2.
XSS***:跨站脚本***:
X-Xss-Protection:4个选项值:
- 0: 不开启XSS保护
- 1: 开启保护(浏览器中一般默认),检测到跨站点脚本***,浏览器将删除不安全的部分。
- 1; mode=block 检测到***,浏览器将阻止页面的呈现
- 1; report=<reporting-uri> 检测到跨站点脚本***,浏览器将清理页面并报告违规行为。这使用CSP report-uri功能发送报告;只有chrome支持发送报告。
X-Frame-Options响应头防点击劫持
# 防止嵌入 到frame 中;避免点击劫持***
add_header X-Frame-Options DENY ;
- 1.
- 2.
X-Frame-Options 3个选项值:
- DENY: 拒绝一个页以frame方式加载
- SAMEORIGIN: 同源域名下的页面,可以用frame方式加载
- ALLOW-FROM: 允许指定的域名以frame形式加载
点击劫持,是在某个自身不安全站点的某个页面上有一个iframe加载了你的网站的某个页面,***者可以篡改这个iframe,诱使用户去点击,所以最好还是禁止iframe去加载你的页面;或者是同源和个别指定站点可以以frame形式加载你的页面。
发现可高速缓存的SSL页面
# “Cache-Control: no-store”和“Pragma: no-cache”或“Cache-Control: no-cache”
add_header Cache-Control max-age=3600;
- 1.
- 2.
检测到SHA-1密码套件
ssl_ciphers ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE:!SHA-1;
ssl_prefer_server_ciphers on;
- 1.
- 2.
检测到隐藏目录
location ^~ /(html|static|img) {
deny all;
}
location ^~ /地址名称/对应的目录/ {
deny all;
}
error_page 403 =404 /404.html;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
检测到支持较老的TLS版本
# TLSv1.2 以上版本即可
ssl_protocols TLSv1.2 TLSv1.3;
- 1.
- 2.
未实施加密
set $open_http 0;
if ($scheme = http) {
set $open_http "${open_http}1";
}
if ($scheme = https) {
set $open_http "${open_http}0";
}
if ($request_uri ~* "/地址名称/ajax/libs/") {
set $open_http "${open_http}0";
}
if ($request_uri ~* "/地址名称/js/") {
set $open_http "${open_http}0";
}
if ($open_http = "010") {
return 403;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
启用了不安全的“OPTIONS”HTTP 方法
server {
...
# 如果我们在服务器环境中,最好使用这样的结构:
add_header Allow "GET, HEAD, POST" always;
if ($request_method !~ ^(GET|HEAD|POST)$) {
# 您还可以在“if”上下文中使用“add_header”:
# add_header Allow "GET, HEAD, POST" always;
return 405;
}
...
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.