为 HTTPS 网站开启 HPKP( Public Key Pinning)

最近在折腾 HPKP ,总结一下

介绍

HPKP 简单说就是在 HTTP 头中定义一组 Base64 编码的 SPKI 指纹,在支持 HPKP 的浏览器中,浏览器会先对比 HTTP 头中的 SPKI 指纹与当前证书的的实际指纹,从而可以一定程度上防止伪造证书的中间人攻击,更多请参考 https://developer.mozilla.org/en-US/docs/Web/Security/Public_Key_Pinning

语法

Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [; includeSubdomains][; report-uri="reportURI"]

要点

  • pin-sha256 至少要有两个,第一个必须在当前证书链中,后面的作为备份证书,必须不在当前的证书链中,也就是说你可以在后面的 pin 中用完全不存在的指纹,但会有安全隐患
  • 你也可以 pin 中继链,这样就不用每次换证书的时候都换指纹,但如果你的 CA 的证书不是很难搞到的话这样也会有隐患(如有错误请指教)
  • 如果需要更换 SSL 证书,需要在定义的 max-age 之前就将新证书的指纹放入备用 pin 中

指纹生成方法

# RSA key
$ openssl rsa -in my.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

# ECDSA (例如 COMODO ECC )
$ openssl ec -in my.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

Nginx 设置

add_header Public-Key-Pins 'pin-sha256="ABCD"; pin-sha256="EFGI"; max-age=86400';

测试

Chrome 中打开 chrome://net-internals/#hsts ,然后请求( query )当前域名后,如果设置正确的话会看到类似下面的结果:

dynamic_sts_domain: ci.sparanoid.com
dynamic_upgrade_mode: STRICT
dynamic_sts_include_subdomains: true
dynamic_sts_observed: 1443522549.33342
dynamic_pkp_domain: ci.sparanoid.com
dynamic_pkp_include_subdomains: true
dynamic_pkp_observed: 1443522549.333427
dynamic_spki_hashes: sha256/6X0iNAQtPIjXKEVcqZBwyMcRwq1yW60549axatu3oDE=,sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=

Firefox 可以在 Web Inspector 的 Network 标签查看

Qualys SSL Labs 可以在测试结果中看到(例子

HPKP Reporting

当浏览器检测到指纹不匹配时,可以 POST 请求到一个制定的地址,这里推荐使用 RequestBin 进行调试:

add_header Public-Key-Pins-Report-Only 'pin-sha256="FAKE"; pin-sha256="EFGI"; max-age=86400; report-uri="http://requestb.in/onk0wkon"';

目前只有 Chrome 46 支持 Public-Key-Pins-Report-Only

还没有评论,快来抢沙发!

发表评论

  • 😉
  • 😐
  • 😡
  • 😈
  • 🙂
  • 😯
  • 🙁
  • 🙄
  • 😛
  • 😳
  • 😮
  • emoji-mrgree
  • 😆
  • 💡
  • 😀
  • 👿
  • 😥
  • 😎
  • ➡
  • 😕
  • ❓
  • ❗
  • 67 queries in 0.365 seconds