HSTS 101 及 Rails 相关配置
tl; dr HTTP严格传输安全
HSTS 101
复制自维基百科
内容
HSTS的作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。服务器开启HSTS的方法是,当客户端通过HTTPS发出请求时,在服务器返回的超文本传输协议(HTTP)响应头中包含
Strict-Transport-Security
字段。非加密传输时设置的HSTS字段无效。[3]比如,https://example.com/ 的响应头含有
Strict-Transport-Security: max-age=31536000; includeSubDomains
。这意味着两点:
作用
HSTS可以用来抵御SSL剥离攻击。SSL剥离攻击是中间人攻击的一种,由Moxie Marlinspike(英语:Moxie Marlinspike)于2009年发明。他在当年的黑帽大会上发表的题为“New Tricks For Defeating SSL In Practice”的演讲中将这种攻击方式公开。SSL剥离的实施方法是阻止浏览器与服务器创建HTTPS连接。它的前提是用户很少直接在地址栏输入
https://
,用户总是通过点击链接或3xx重定向,从HTTP页面进入HTTPS页面。所以攻击者可以在用户访问HTTP页面时替换所有https://
开头的链接为http://
,达到阻止HTTPS的目的。[9]HSTS可以很大程度上解决SSL剥离攻击,因为只要浏览器曾经与服务器创建过一次安全连接,之后浏览器会强制使用HTTPS,即使链接被换成了HTTP[3][10]。
另外,如果中间人使用自己的自签名证书来进行攻击,浏览器会给出警告,但是许多用户会忽略警告。HSTS解决了这一问题,一旦服务器发送了HSTS字段,将不再允许用户忽略警告。
不足
用户首次访问某网站是不受HSTS保护的。这是因为首次访问时,浏览器还未收到HSTS,所以仍有可能通过明文HTTP来访问。解决这个不足当前有两种方案,一是浏览器预置HSTS域名列表,Google Chrome、Firefox、Internet Explorer和Microsoft Edge实现了这一方案[11][12]。二是将HSTS信息加入到域名系统记录中。但这需要保证DNS的安全性,也就是需要部署域名系统安全扩展。截至2016年这一方案没有大规模部署。
由于HSTS会在一定时间后失效(有效期由max-age指定),所以浏览器是否强制HSTS策略取决于当前系统时间。部分操作系统经常通过网络时间协议更新系统时间,如Ubuntu每次连接网络时、OS X Lion每隔9分钟会自动连接时间服务器。攻击者可以通过伪造NTP信息,设置错误时间来绕过HSTS。解决方法是认证NTP信息,或者禁止NTP大幅度增减时间。比如Windows 8每7天更新一次时间,并且要求每次NTP设置的时间与当前时间不得超过15小时。
Rails 关于 https 和 HSTS 的配置
config.force_ssl = true # 例如在 application.rb 或者环境特定配置
这个配置做了三件事
将所有 http 请求重定向至 https
config.ssl_options = { redirect: { status: 307, port: 81 } } # 默认 301,80 端口
在 cookies 设置安全标记,告诉浏览器禁用 http 请求。防止中间人攻击
config.ssl_options = { secure_cookies: false } # 停用该功能
response headers 加上 HSTS
# 杜绝首次访问时尚未启用 hsts 的漏洞,前提是在 hstspreload.org 提交了网站域名。默认 false
config.ssl_options = { hsts: { preload: true } }
# hsts 有效期,默认 1 年
config.ssl_options = { hsts: { expires: 10.days } }
# 告诉浏览器停用 hsts,恢复 http
config.ssl_options = { hsts: false } # 或者 hsts: { expires: 0 }
# 子域名是否也启用 hsts,默认 true
config.ssl_options = { subdomains: false}