HSTS原理及实践

2019-08-08

Https连接

Https通过加密传输和身份认证保证了http协议传输过程的安全性,然而这并不意味着你开启了https网站就绝对安全了。大部分用户都很少直接在地址栏输入https://,而是直接输入网址。此时浏览器默认发起http请求,再由服务端进行30x重定向(通常是301永久重定向)到https。如下图:

Https连接


SSL剥离攻击

用户第一次发起的是http请求,存在被中间人劫持的风险。黑客可以用下图的方式劫持用户请求,阻止浏览器与服务器创建HTTPS连接。

SSL剥离攻击

1.用户向服务器发起http请求;

2.黑客劫持了这个http请求;

3.黑客向服务器发起相同的https请求,服务器返回数据;

4.黑客把返回的数据作为http请求的响应返回给用户;

5.用户拿到响应数据,其实所有通信内容(包括密码等敏感数据)已经被黑客知道了;


这种典型的中间人攻击方式被称为“SSL剥离攻击”,由Moxie Marlinspike在2009年黑帽大会上发表的《New Tricks For Defeating SSL In Practice》演讲中公开。


HSTS原理及实践

想要尽可能避免SSL剥离攻击,就得让浏览器一开始就发起https请求,而不是默认发起http请求。这个安全策略机制就是“HTTP Strict Transport Security”(HTTP严格传输安全),缩写HSTS。网站一旦启用HSTS策略,浏览器会强制使用HTTPS网站进行通信,以减少会话劫持风险。


服务器开启HSTS的方法很简单。当浏览器发起Https请求的时候,在响应头中增加Strict-Transport-Security字段。你可以在框架层添加,也可以nginx配置增加一行:

add_header Strict-Transport-Security "max-age=31536000";


浏览器收到这个字段后,在后续一段时间内向这个域名发起的任何请求,都必须采用https来发起连接。本博客已经开启HSTS,您可以打开浏览器的控制台查看响应头作为例子。HSTS Header的语法如下:

Strict-Transport-Security: <max-age=>[; includeSubDomains][; preload]


需要特别注意:


保护首次请求

HSTS只能在第二次请求的时候生效,不能保护首次请求,因为首次访问的时候浏览器还未收到HSTS。解决这个问题当前有两个方案,一个是把HSTS信息加入到DNS记录中,但这需要保证DNS的安全,目前应用并不广泛;另一个是把HSTS信息加入到浏览器中,即浏览器的Preload List。


Google Chromium维护的HSTS Preload List项目,是目前业界的事实标准,Chrome/FireFox/Safari/IE都在使用。一旦加入这个列表,以后浏览器直接输入你的网站域名,首次请求就默认走https协议。


加入Preload List的方式很简单,访问https://hstspreload.org/,输入你的网站域名即可。添加的域名需要满足以下要求:


总结

SSL剥离攻击可以劫持用户发起的http请求,让服务端的https配置形同虚设。因此需要开启HSTS,强制客户端使用https连接,保障网站的安全。


参考文献

  1. https://tools.ietf.org/html/rfc6797



本文未经许可禁止转载,如需转载关注微信公众号【工程师加一】并留言。