什么是 HSTS?它如何防止 SSL 剥离攻击?
简化版
SSL 剥离(SSL Stripping)是一种降级攻击:你首次用 http:// 访问网站时,中间人拦截,让你和它走明文 HTTP、它再和服务器走 HTTPS,从而窃听一切。**HSTS(HTTP 严格传输安全)**是防范手段——服务器返回一个 Strict-Transport-Security 响应头,告诉浏览器「以后访问本站一律强制用 HTTPS」,这样浏览器根本不会发出明文 HTTP 请求,剥离攻击就无从下手。
详细版
SSL 剥离攻击的原理:漏洞在于首次访问。用户通常直接输 example.com(默认走 HTTP)或点一个 http 链接,浏览器先发一个明文 HTTP 请求,服务器再用 301/302 重定向到 HTTPS。中间人就利用这个明文窗口:
你 --HTTP(明文)--> 中间人 --HTTPS(加密)--> 服务器
中间人对你保持明文 HTTP(把服务器的 HTTPS 响应「剥离」成 HTTP 转发给你),对服务器则用正常 HTTPS。你以为在正常浏览,其实全程明文,中间人尽收眼底——而且浏览器不会报警(因为你这边确实是「正常的 HTTP」)。
HSTS 的防范:服务器在 HTTPS 响应里加一个头:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
浏览器收到后记住:在 max-age(这里一年)内,对该域名的所有请求一律强制用 HTTPS——用户就算输 http 或点 http 链接,浏览器也会在本地直接改成 https 再发出,根本不产生明文请求。剥离攻击赖以生存的「首次明文窗口」被堵死。
完整版教学
一、问题根源:从 HTTP 跳 HTTPS 的那一下
即使一个网站全站 HTTPS,也有个薄弱环节:用户第一次是怎么到达的。
- 用户很少手动输
https://,通常直接输域名或点链接,默认发起 HTTP 请求; - 服务器收到 HTTP 请求,回一个 301 重定向到 HTTPS;
- 浏览器再发 HTTPS 请求。
问题就在这第一个明文 HTTP 请求 + 重定向上——它是明文的,中间人可以在这里动手,让你「永远停留在 HTTP」,不给你升级到 HTTPS 的机会。这就是 SSL 剥离的切入点。
二、HSTS 如何堵住这个窗口
HSTS 的思路是:让浏览器「记住」这个网站只能用 HTTPS,从而在客户端本地就完成升级,压根不发明文请求。
- 用户首次成功用 HTTPS 访问后,服务器通过
Strict-Transport-Security头下发 HSTS 策略; - 浏览器记住:今后
max-age时间内,访问该域名强制 HTTPS; - 之后用户再输
http://example.com或点 http 链接,浏览器在发出请求前就本地改写成 https(内部 307 重定向),明文请求根本不出现在网络上。
没有了明文请求,中间人就无法「剥离」——它连拦截的对象都没有了。
三、首次访问问题与 preload
HSTS 本身还有个缺口:第一次访问(浏览器还没收到过该网站的 HSTS 头)时,仍可能走明文,这次仍可能被剥离。解决办法是 HSTS Preload(预加载列表):
- 网站把域名提交到浏览器厂商维护的 HSTS Preload List;
- 这个列表内置在浏览器里,浏览器出厂就知道「这些域名必须 HTTPS」;
- 于是连第一次访问都强制 HTTPS,彻底消除首次明文窗口。
Strict-Transport-Security 头里的 preload 指令就是声明希望被加入预加载列表(还需满足 includeSubDomains、足够长的 max-age 等条件并提交申请)。
四、HSTS 头的三个指令
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age:策略有效期(秒),期间强制 HTTPS。设太短保护弱,一般设一年(31536000)。includeSubDomains:对所有子域名也生效。preload:声明加入浏览器预加载列表(消除首次访问窗口)。
注意 HSTS 头必须通过 HTTPS 响应下发才有效(HTTP 响应里的 HSTS 头浏览器会忽略,否则中间人可伪造)。
五、常见误区
- ❌ 以为全站 HTTPS 就没有降级风险——首次的明文 HTTP 请求 + 重定向是 SSL 剥离的切入点。
- ❌ 以为 SSL 剥离会触发浏览器警告——不会,你这侧是「正常的 HTTP」,很隐蔽。
- ❌ 以为 HSTS 能防首次访问被剥离——普通 HSTS 首次仍有窗口,要靠 preload 才彻底解决。
- ❌ 把 HSTS 头配在 HTTP 响应里——必须走 HTTPS 下发才有效,HTTP 里的会被忽略。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| SSL 剥离 | 攻击者阻止 HTTP 升级 HTTPS,让用户停留在明文 |
| HSTS | 浏览器记住该域名只能用 HTTPS |
| preload | 首次访问前就内置强制 HTTPS 规则 |
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
HSTS 防的是“第一次 HTTP 跳 HTTPS 被拦截”这个窗口。
- 误区:HSTS 是服务器重定向规则。 HSTS 是浏览器安全策略,收到头后以后直接使用 HTTPS。
- 误区:HSTS 能修复证书错误。 证书无效时浏览器仍会拦截,HSTS 不能让坏证书变可信。
- 误区:第一次访问普通 HTTP 时 HSTS 已经生效。 除非进入 preload 列表,否则首次访问仍可能有被剥离窗口。
- 追问:includeSubDomains 有什么风险? 会把所有子域名都强制 HTTPS,子域证书和服务必须准备好。
- 追问:preload 怎么工作? 浏览器内置预加载列表,用户首次访问前就知道该域名必须 HTTPS。
- 追问:max-age 设置太长有什么影响? 一旦误配,用户浏览器会长期强制 HTTPS,回滚困难。
七、加强记忆
SSL 剥离是中间人利用「首次明文 HTTP 请求 + 重定向到 HTTPS」的窗口,把你降级到明文并居中窃听,且不触发警告。HSTS 通过 Strict-Transport-Security 响应头让浏览器记住该域名强制 HTTPS、本地把 http 改写成 https,堵死明文窗口;配合 preload 预加载列表可消除首次访问的窗口。HSTS 头须经 HTTPS 下发才生效。