HTTP Strict Transport Security

Strict-Transport-Security是一个httpresponse header,可以告诉浏览器要用https来访问网站,而不是http。hsts就是http strict transport security

语法

1
2
3
Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; preload

指令

  • max-age=<expire-time>
    设置在浏览器收到这个请求后的<expire-time>秒的时间内,凡是访问这个域名下的请求都使用https请求。
  • includeSubDomains | 可选
    如果这个可选的参数被指定,那么说明此规则也适用于该网站的所有子域名。
  • preload | 可选
    这个指令不是标准规定的,而是谷歌和火狐浏览器维护的一个hsts列表,像一个白名单,只要在这个列表内的网站,永远启用hsts

介绍

一般现在部署https的网站,都会同时兼容httphttps的访问,后端服务器配置http强制重定向到https访问。在这种场景中,对用户而言,最终都会转化为https访问,但是如果用户每次都是通过http连接发起的访问,那么每次始终都会有一次http请求,之后才是https请求。 这样的访问过程中,首次的http访问,有被攻击的风险。 中间人可以劫持这次访问,收集用户的信息、给用户返回钓鱼网站。当用户的手机接入公共wifi的时候,假如这个公共wifi是一个黑客的笔记本热点,那这种攻击很有可能就会发生。

Strict-Transport-Security可以防范此类攻击,只要浏览器记录过一个网站的Strict-Transport-Security值,并且这个值没有过期,当用户下次使用http访问这个网站的时候,就会自动替换为https访问。

Strict-Transport-Security还有一个作用,就是如果用户发起https请求过程中,检测到证书无效,则浏览器会弹出警告,并且用户不能忽视,从而完全阻止用户访问该网站。

浏览器如何处理

只有在用户第一次使用https请求,访问网站,并且网站设置了Strict-Transport-Security,浏览器才会记录这个header的值,之后用户尝试访问这个网站的http请求都会被替换为https

这个规则非常关键,当使用http访问网站时,即使响应这种包含有Strict-Transport-Security也会被浏览器忽略,因为这是http返回的Strict-Transport-Security的头部,这是不可信的,很有可能被中间人篡改过。只有https返回的Strict-Transport-Security,浏览器才会信任。

这间接地说明Strict-Transport-Security对安全的防范也不是百分之百的,用户最起码需要进行一次https访问之后,Strict-Transport-Security才能生效,那么在https访问之前,如果存在http访问,那依然是有被攻击的风险的。

每次浏览器接收到Strict-Transport-Security头,它都会更新这个网站的过期时间,所以网站可以刷新这些信息,防止过期发生。当Strict-Transport-Security头设置的过期时间到了,后面通过http的访问恢复到正常模式,不会再自动跳转到https

Chrome、Firefox等浏览器里,当尝试访问该域名下的内容时,会产生一个307 Internal Redirect(内部跳转),自动跳转到https请求。

需注意的问题

网上说提到的chrome hsts 失效的问题,其实正是hsts生效的原因,而网上有些人提到的解决方案,竟然都是如何去清理hsts相关的域名,这既不符合用户体验,也不符合hsts这项标准的内涵。 什么情况下会出现下面这种因为hsts导致的访问拦截呢?

上面图片已经说得非常明显了:

可能是因为有攻击者试图冒充xxxx.com,或wifi登录屏幕中断了此次连接。

上面这个图片是怎么出来的呢?是我在对xxxx.com进行已设置hsts的进行了https访问后,修改了xxxx.com的证书,然后对它发起http访问后出现的。 我这个测试情况,就是上述图片中所说的有人在冒充xxxx.com;因为我修改了xxxx.com的证书后,浏览器根据修改后的证书,无法判断xxxx.com的身份了。所以针对这种情况,进行阻止,是符合安全规范的。

第二种情况:wifi登录屏幕中断了此次连接。这是什么情况呢?比如xxxx.com开启了hsts,并且你事先访问过xxxx.com,可以保证浏览器内的strict transport security已生效,然后你去连接星巴克、麦当劳等使用http了进行认证的wifi网络,当你发起一个对xxxx.comhttp访问后,浏览器会默认替换为https进行访问,但是因为还没有连入wifi,所以星巴克、麦当劳的httpwifi认证生效,拦截了你被替换后的https请求,返回了一个基于http的wifi登录页面,浏览器本来需要一个https的响应,结果返回了一个http响应,自然就触发了安全警告机制。

strict transport security过期并不会导致出现上面类似的安全警告,只是不会再自动将http替换为https访问。如果要关闭掉hsts,不能把strict transport security这个头去掉,而是要明确的将max-age设置为0,不然之前hsts已生效的浏览器在过期之前会一直使用hsts

1
strict-transport-security:max-age=0