最全 HTTP 安全响应头设置指南

销售“安全记分卡”的公司正在崛起,并已开始成为企业销售的一个因素。这些公司组合使用 HTTP 安全报头和 IP 信誉来进行评级。不过,在很大程度上,公司的得分取决于对外开放网站上设置的安全响应报头。本文介绍了经常使用的安全响应报头及对应的推荐安全值,并给出了示例。css

销售“安全记分卡”的公司正在崛起,并已开始成为企业销售的一个因素。我从客户那里了解到,他们对从评级低的供应商那里的采购很不放心,至少有案例代表,他们依据最初的评级改变了采购决策。前端

我调查了这些评级公司是如何计算公司安全性得分的,结果发现他们组合使用了 HTTP 安全报头和 IP 信誉。正则表达式

IP 信誉基于的是黑名单和垃圾邮件列表,再加上公共 IP 全部权数据。只要你的公司没有垃圾邮件,而且可以快速检测和阻止恶意软件感染,那么一般这些软件应该就是干净的。HTTP 安全报头使用的计算方式与Mozilla Observatory的工做方式相似。spring

所以,对于大多数公司来讲,在很大程度上,他们的得分取决于对外开放的网站上设置的安全响应报头。express

设置正确的响应报头能够快速实现(一般不须要进行大量测试),并能提升网站的安全性,如今还能够帮助咱们赢得具备安全意识的客户。django

我对这种测试方法的价值以及这些公司提出的太高的订价方案持怀疑态度。我不认为它与真正的产品安全性有那么大的关联。然而,这无疑增长了设置响应报头并维护其正确性的重要性,值得为此投入时间。浏览器

在本文中,我将介绍经常使用的评估响应报头,及每一个报头的推荐安全值,并给出一个响应报头设置的示例。在本文的最后,还将给出常见的应用程序和 Web 服务器的设置示例。缓存

重要的安全响应报头

Content-Security-Policy(CSP)

CSP 经过指定容许加载哪些资源的形式,来防止跨站脚本注入。在本文所列的安全响应报头中,正确地设置和维护 CSP,多是最耗时的,也是最容易出现风险的。在开发 CSP 的过程当中,要谨慎充分地测试它——以“合法”的方式阻塞站点使用的内容源会破坏站点的功能。安全

建立 CSP 初稿的一个很好的工具是Mozilla 实验室的 CSP 浏览器扩展。在浏览器中安装此扩展程序,首先充分地浏览要为其设置 CSP 的站点,而后在站点中使用生成的 CSP。理想状况下,还能够重构 JavaScript,使其没有残留的任何内联脚本,从而使咱们能够删除“unsafe inline”指令设置。服务器

CSP 的指令设置可能比较复杂,也很混乱,所以,若是你想更深刻的了解 CSP,请访问其官方网站

一个好的 CSP 开始多是以下这样的(在真正的站点上使用时,可能须要进行大量的修改)。在包含该站点的每一个部分中都添加域名。

复制代码
 
 
# 默认状况下,仅容许访问当前站点的内容
 
# 容许访问当前站点和 imgur.com 的图片资源
 
# 不容许访问 Flash、Java 等对象
 
# 仅容许访问当前站点的脚本
 
# 仅容许访问当前站点的样式
 
# 仅容许嵌入当前站点的内嵌
 
# 将 <base> 标记中的 URL 限制在当前站点
 
# 表单仅容许提交到当前站点
 
Content-Security-Policy: default-src 'self'; img-src 'self' https://i.imgur.com; object-src 'none'; script-src 'self'; style-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';

Strict-Transport-Security(HSTS)

该响应报头告诉浏览器,只能经过 HTTPS 访问网站——若是网站启用过 HTTPS,它将会一直生效。若是使用子域名,还建议在任何使用过的子域名对此加以强制。

复制代码
 
 
Strict-Transport-Security: max-age=3600; includeSubDomains

X-Content-Type-Options

该响应报头确保浏览器遵照应用程序设置的 MIME 类型。这有助于防止某些类型的跨站脚本注入攻击。

它还能减小浏览器“猜想”某些内容不正确时的意外应用程序行为,例如,当开发人员将某个页面标记为“HTML”,但浏览器认为它更像 JavaScript,并试图将其渲染为 JavaScript 时。该响应报头能确保浏览器始终遵照服务端设置的 MIME 类型。

复制代码
 
 
X-Content- Type-Options: nosniff

Cache-Control(缓存控制)

这个响应报头比其余的要稍微复杂一些,由于咱们可能须要根据内容类型的不一样而使用不一样的缓存策略。

任何具备敏感数据的页面,如用户页面或客户结算页面,都应该设置成无缓存。其中一个缘由是,防止共享计算机上的某我的按回退按钮或浏览历史记录又能查看到我的信息。

可是,对于像静态资产(图像、CSS 文件和 JS 文件)等不多变动的页面,很适合使用缓存。既能够经过逐页设置的方式来实现,也能够经过在服务端配置使用正则表达式的方式来实现。

复制代码
 
 
# 默认状况不使用缓存
 
Header set Cache-Control no-cache
   
 
# 静态资产设置成缓存 1 天
 
<filesMatch ".(css|jpg|jpeg|png|gif|js|ico)$">
 
Header set Cache-Control "max-age=86400, public"
 
</filesMatch>

Expires(过时时间)

该响应报头能设置当前请求缓存的过时时间。若是设置了 Cache-Control 的 max-age 响应报头,它将会被忽略,所以,在不考虑使用 Cache-Control 而进行本地缓存测试时,才设置它。

为了安全起见,咱们假定浏览器不该该缓存任何内容,所以,咱们能够把过时时间设置为一个总表示过时的数值。

复制代码
 
 
Expires: 0

X-Frame-Options

该响应报头用来代表站点是否容许在 iFrame 中展现。

若是恶意站点将咱们的网站嵌套在 iFrame 中,那么恶意站点就能够经过运行一些 JavaScript 来执行点击劫持攻击,这些 JavaScript 可以捕获 iFrame 上的鼠标点击事件,而后表明用户与该站点进行交互(没必要单击须要单击它们的地方!)。

应该始终将它设置为 deny(拒绝),除非特别须要使用内嵌,在这种状况下,应将其设置为 same-origin(同源)。若是须要在页面中内嵌其余的站点,也能够在此处以白名单的形式列举其余的域名。

还应该注意的是,这个响应报头已经被 CSP 的 frame-ancestors 指令所取代。目前,我仍然建议设置该响应报头来兼容不一样的工具,但未来它可能会被逐步淘汰。

复制代码
 
 
X- Frame-Options: deny

Access-Control-Allow-Origin

经过该响应报头能够告诉浏览器,容许哪些其余站点的前端 JavaScript 代码对页面发出请求。除非须要设置此响应报头,不然一般默认值就是正确的设置。

例如,若是站点 A 使用了一些 JavaScript,该 JavaScript 想要向站点 B 发出请求,那么站点 B 必须使用指定了容许站点 A 发出此请求的报头来提供响应。若是须要设置多个源,请参见MDN 上的详情介绍页面

这可能有点难以理解,所以,我画了一个图表来讲明这个响应报头是如何工做的:

Access-Control-Allow-Origin 对应的数据流

``` Access-Control-Allow-Origin: http://www.one.site.com ```

Set-Cookie

确保 cookie 仅能经过 HTTPS(加密)传送,而且不能经过 JavaScript 访问。若是站点也支持 HTTPS(站点应该支持 HTTPS),那么就只能发送 HTTPS cookie。咱们一般须要设置以下标志:

  • Secure

  • HttpOnly

一个定义 Cookie 的示例:

复制代码
 
 
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly

请参阅Mozilla 文档中的 cookies 部分以了解更多相关信息。

X-XSS-Protection

该响应报头用来指示浏览器中止执行跨站脚本攻击检测。通常来讲,设置它的风险很低,但在投入生产前仍须要进行测试。

复制代码
 
 
X-XSS-Protection: 1; mode=block

Web 服务器的配置示例

一般,最好在服务器配置中添加站点范围内的响应报头。在此,cookie 是一个例外,由于它们一般是在应用程序内定义的。

在将任何响应报头添加到站点以前,我建议首先检查 Observatory 或手动查看响应报头,以查看已经设置了哪些响应报头。有些框架和服务器会自动设置其中一些响应报头,所以,咱们只需设置咱们须要的或想要变动的响应报头便可。

Apache 配置

.htaccess 中的 Apache 设置示例:

复制代码
 
 
<IfModule mod_headers.c>
 
## CSP
 
Header set Content-Security-Policy: default-src 'self'; img-src 'self' https://i.imgur.com; object-src 'none'; script-src 'self'; style-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';
   
 
## 通用的安全响应报头
 
Header set X-XSS-Protection: 1; mode=block
 
Header set Access-Control-Allow-Origin: http://www.one.site.com
 
Header set X-Frame-Options: deny
 
Header set X-Content-Type-Options: nosniff
 
Header set Strict-Transport-Security: max-age=3600; includeSubDomains
   
 
## 缓存策略
 
# 默认状况下不使用缓存
 
Header set Cache-Control no-cache
 
Header set Expires: 0
   
 
# 设置静态资产缓存 1 天
 
<filesMatch ".(ico|css|js|gif|jpeg|jpg|png|svg|woff|ttf|eot)$">
 
Header set Cache-Control "max-age=86400, public"
 
</filesMatch>
   
 
</IfModule>

Nginx 设置

复制代码
 
 
## CSP
 
add_header Content-Security-Policy: default-src 'self'; img-src 'self' https://i.imgur.com; object-src 'none'; script-src 'self'; style-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';
   
 
## 通用的安全响应报头
   
 
add_header X-XSS-Protection: 1; mode=block;
 
add_header Access-Control-Allow-Origin: http://www.one.site.com;
 
add_header X-Frame-Options: deny;
 
add_header X-Content-Type-Options: nosniff;
 
add_header Strict-Transport-Security: max-age=3600; includeSubDomains;
   
 
## 缓存策略
   
 
** 默认不使用缓存 **
   
 
add_header Cache-Control no-cache;
 
add_header Expires: 0;
   
 
** 设置静态资产缓存 1 天 **
   
 
location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ {
 
try_files $uri @rewriteapp;
 
add_header Cache-Control "max-age=86400, public";
 
}

应用程序级的响应报头设置

若是咱们没有访问 Web 服务器的权限,或者须要设置复杂的响应报头,那么咱们就可能须要在应用程序内设置这些响应报头了。这一般能够在整个站点的框架中间件中实现,也能够在每次响应的基础上进行一次性的报头设置。

为了简便起见,在示例中,只包含了一个响应报头。所需的所有响应报头都是以相同的方式经过该方法来添加的。

Node 及 express:

添加一个全局挂载路径:

复制代码
 
 
app.use( function(req, res, next) {
 
res.header( 'X-XSS-Protection', 1; mode=block);
 
next();
 
});

Java 及 Spring:

我没有太多的 Spring 实践经验,但Baeldung对在 Spring 中如何设置响应报头提供了很好的指导。

PHP:

我对各类 PHP 框架不是很熟悉。查找了可以处理请求的中间件。对于单个响应,它的设置很是简单。

复制代码
 
 
header( "X-XSS-Protection: 1; mode=block");

Python 及 Django

Django 包含可配置的安全中间件,经过该中间件来处理全部响应报头的设置。首先启用它们。

对于特定页面,能够将响应视为字典。Django 有一个处理缓存的特殊方法,若是试图以这种方式设置缓存响应报头,那么就应该调研后再使用。

复制代码
 
 
response = HttpResponse()
 
response["X-XSS-Protection"] = "1; mode=block"

总结

设置响应报头相对来讲比较简单快捷。在数据保护、跨站脚本注入和点击劫持方面,站点安全性将会有至关大的提升。

还能够确保咱们不会由于依赖此信息的公司安全评级而失去将来的业务交易。这种作法彷佛愈来愈多,我但愿在将来几年,它能继续在企业销售中发挥做用。

若是以上有所遗漏,你认为还应该包含其余的安全响应报头,请留言回复。

英文原文:https://nullsweep.com/http-security-headers-a-complete-guide

相关文章
相关标签/搜索