HTTP Public Key Pinning
小心
从 Chrome 72 开始 HPKP 支持已被完全移除。
HTTP Public Key Pinning 简称 HPKP
本文翻译自 MDN,原文版本为 Jan 31, 2017, 11:00:31 PM
HPKP 是一个 HTTP 安全扩展,它告诉网络客户端服务器公钥的哈希值以减少中间人伪造证书攻击的风险。
为了确保在 TLS 会话中服务器公钥的真实性,公钥应该使用被 CA 数字证书认证机构
签名的 X.509 证书进行包装。网络用户例如浏览器信任许多这样的 CA,这些 CA 可以为任意的域名创建证书。如果一个黑客能够控制一个 CA,他们就可以在多样的 TLS 链接中发起中间人攻击
。HPKP 可以告诉客户端哪一个公钥属于真正的网站服务器以规避这样的风险。
HPKP 是一个『信任第一次使用』Trust on First Use
的技术。第一次服务器通过一个特殊的 HTTP 响应头告诉客户端哪一个公钥属于这个服务器,客户端则会在给定的时间内记住这些信息。当这个客户端再一次访问这一个服务器时,它会期望在服务器提供的证书链中找到一个指纹与通过 HPKP 得到的指纹相同的证书。如果这个服务器提供了一个未知的公钥,这个客户端应该显示一个警告给用户。
警告
Firefox and Chrome disable pin validation for pinned hosts whose validated certificate chain terminates at a user-defined trust anchor(rather than a built-in trust anchor).
这意味着如果用户导入了一个自定义的根证书,那么所有已经固定了的公钥都会被 Firefox 和 Chrome 忽视。
启用 HPKP
想要为你的服务器启用这项安全特性,你需要在服务器接收到一个通过 HTTPS 发起的请求时返回一个 Public-Key-Pins HTTP 响应头:
- pin-sha256
- 一个带引号的 SPKI
Subject Public Key Information
指纹的 Base64 字符串。不同的公钥可以被指定多个固定值。一些浏览器可能在未来允许 SHA-256 以外其他的哈希算法。如何获得证书或者公钥的这个信息请看下文。
- 一个带引号的 SPKI
- max-age
- 浏览器应该只使用这一个确定的公钥的时长。以秒作为单位。
- includeSubDomains
可选
- 如果这一个参数被指定了,则这一个规则适用于该站点的所有子域名。
- report-uri
可选
- 如果这一个参数被指定了,则公钥固定失败时会发送报告至给定的 URL。
警告
正在使用的规则中需要包含一个第二固定公钥。这样会允许服务器更换公钥而不会破坏已经固定了公钥的客户端。这对于更换公钥非常重要。
获得公钥信息的 Base64 编码
警告
虽然这一个示例展示了如何去为服务器设置一个固定值,但是还是建议将 CA 的中间证书也一起固定来缓解更新证书带来的麻烦。
首先你需要从你的证书中导出公钥的信息然后再将它用 Base64 编码。
下面的命令可以帮助你导出证书信息的 Base64 编码。
下面的命令可以导出一个网站的信息。
示例 HPKP 响应头
在这一个例子当中,pin-sha256=“cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=”固定了服务器的公钥。第二个值 pin-sha256=“M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE=”同样固定了备份的公钥。max-age=5184000 则告诉了客户端应该储存这些信息两个月,两个月是 IETF RFC 中建议的最好时间长度。由 includeSubDomains 可知公钥固定同样适用于所有的子域名。最后,report-uri=“https://www.example.net/hpkp-report” 则告知了应该向何处报告固定失败。
Report-Only 响应头
除了使用 Public-Key-Pins 响应头外,你可以同时使用 Public-Key-Pins-Report-Only 响应头。这个响应头将使浏览器在公钥固定失败的时候发送一个报告到 report-uri 上。如果仅仅使用 Public-Key-Pins-Report-Only 响应头,那么浏览器只会发送报告而不会阻止加载。
为你的服务器设置 HPKP 响应头
下面的步骤取决于你的服务器类型。
警告
下面的例子使用的 max-age 为两个月并且适用于子域名。请在部署到服务器之前再三确认是否合适你的服务器。
小心
如果错误地配置了 HPKP,那么用户将在很长的一段时间内无法访问你的网站!建议将备份公钥和 / 或 CA 的证书同时固定。
Apache
在你的服务器设置中修改并加入以下代码就能在你的 Apache 上启用 HPKP。这需要启用 mod_headers。
Nginx
在你的服务器设置中加入以下代码并插入一个适当的 pin-sha256=”…“值就能在你得 Nginx 上启用 HPKP。需要 ngx_http_headers_module。
Lighttpd
加入并修改以下代码。
** 注意:** 需要通过以下代码启用 mod_setenv server.module
IIS
加入并修改以下代码。
规范
规范 | 标题 |
---|---|
RFC 7469, section 2.1: Public-Key-Pins | HTTP 的公钥固定扩展 |
浏览器兼容性
桌面系统
特性 | Chrome | Edge | FireFox | IE | Opera | Safari | Servo |
---|---|---|---|---|---|---|---|
Public-Key-Pins | (yes) | ? | 35.0 | ? | (yes) | ? | ? |
Public-Key-Pins-Report-Only | 46 | ? | 不支持 1 | ? | 33 | ? | ? |
手机系统
特性 | Android | Chrome For Android | Edge Mobile | FireFox for Android | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|---|
Public-Key-Pins | (Yes) | (Yes) | ? | 35.0 | ? | (yes) | ? |
Public-Key-Pins-Report-Only | (Yes) | (Yes) | ? | 不支持 | ? | 33 | ? |
参考资料
(^o^)/~ 本文已完成。