在網(wǎng)站全站HTTPS后,,如果用戶手動敲入網(wǎng)站的HTTP地址,或者從其它地方點擊了網(wǎng)站的HTTP鏈接,,通常依賴于服務(wù)端301/302跳轉(zhuǎn)才能使用HTTPS服務(wù),。而第一次的HTTP請求就有可能被劫持,,導(dǎo)致請求無法到達服務(wù)器,,從而構(gòu)成HTTPS降級劫持,。這個問題目前可以通過HSTS(HTTP Strict Transport Security,,RFC6797)來解決,。
HSTS簡介
HSTS(HTTP Strict Transport Security)是國際互聯(lián)網(wǎng)工程組織IETF發(fā)布的一種互聯(lián)網(wǎng)安全策略機制,。采用HSTS策略的網(wǎng)站將保證瀏覽器始終連接到該網(wǎng)站的HTTPS加密版本,不需要用戶手動在URL地址欄中輸入加密地址,,以減少會話劫持風(fēng)險,。
HSTS響應(yīng)頭格式
Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]
-
max-age,,單位是秒,用來告訴瀏覽器在指定時間內(nèi),,這個網(wǎng)站必須通過HTTPS協(xié)議來訪問,。也就是對于這個網(wǎng)站的HTTP地址,瀏覽器需要先在本地替換為HTTPS之后再發(fā)送請求,。
-
includeSubDomains,,可選參數(shù),如果指定這個參數(shù),,表明這個網(wǎng)站所有子域名也必須通過HTTPS協(xié)議來訪問,。
-
preload,可選參數(shù),,一個瀏覽器內(nèi)置的使用HTTPS的域名列表,。
HSTS Preload List
雖然HSTS可以很好的解決HTTPS降級攻擊,但是對于HSTS生效前的首次HTTP請求,,依然無法避免被劫持,。瀏覽器廠商們?yōu)榱私鉀Q這個問題,提出了HSTS Preload List方案:內(nèi)置一份可以定期更新的列表,,對于列表中的域名,,即使用戶之前沒有訪問過,也會使用HTTPS協(xié)議,。
目前這個Preload List由Google Chrome維護,,Chrome、Firefox,、Safari,、IE 11和Microsoft Edge都在使用。如果要想把自己的域名加進這個列表,,首先需要滿足以下條件:
-
擁有合法的證書(如果使用SHA-1證書,,過期時間必須早于2016年);
-
將所有HTTP流量重定向到HTTPS,;
-
確保所有子域名都啟用了HTTPS;
-
輸出HSTS響應(yīng)頭:
-
max-age不能低于18周(10886400秒),;
-
必須指定includeSubdomains參數(shù),;
-
必須指定preload參數(shù);
即便滿足了上述所有條件,,也不一定能進入HSTS Preload List,,更多信息可以查看:https://hstspreload.org/。
通過Chrome的chrome://net-internals/#hsts工具,,可以查詢某個網(wǎng)站是否在Preload List之中,,還可以手動把某個域名加到本機Preload List,。
HSTS缺點
HSTS并不是HTTP會話劫持的完美解決方案。用戶首次訪問某網(wǎng)站是不受HSTS保護的,。這是因為首次訪問時,,瀏覽器還未收到HSTS,所以仍有可能通過明文HTTP來訪問,。
如果用戶通過HTTP訪問HSTS保護的網(wǎng)站時,,以下幾種情況存在降級劫持可能:
-
以前從未訪問過該網(wǎng)站
-
最近重新安裝了其操作系統(tǒng)
-
最近重新安裝了其瀏覽器
-
切換到新的瀏覽器
-
切換到一個新的設(shè)備,如:移動電話
-
刪除瀏覽器的緩存
-
最近沒訪問過該站并且max-age過期了
解決這個問題目前有兩種方案:
方案一:在瀏覽器預(yù)置HSTS域名列表,,就是上面提到的HSTS Preload List方案,。該域名列表被分發(fā)和硬編碼到主流的Web瀏覽器??蛻舳嗽L問此列表中的域名將主動的使用HTTPS,,并拒絕使用HTTP訪問該站點。
方案二:將HSTS信息加入到域名系統(tǒng)記錄中,。但這需要保證DNS的安全性,,也就是需要部署域名系統(tǒng)安全擴展。
其它可能存在的問題
由于HSTS會在一定時間后失效(有效期由max-age指定),,所以瀏覽器是否強制HSTS策略取決于當(dāng)前系統(tǒng)時間,。大部分操作系統(tǒng)經(jīng)常通過網(wǎng)絡(luò)時間協(xié)議更新系統(tǒng)時間,如Ubuntu每次連接網(wǎng)絡(luò)時,,OS X Lion每隔9分鐘會自動連接時間服務(wù)器,。攻擊者可以通過偽造NTP信息,設(shè)置錯誤時間來繞過HSTS,。
解決方法是認證NTP信息,,或者禁止NTP大幅度增減時間。比如:Windows 8每7天更新一次時間,,并且要求每次NTP設(shè)置的時間與當(dāng)前時間不得超過15小時,。
支持HSTS瀏覽器
目前主流瀏覽器都已經(jīng)支持HSTS特性,具體可參考下面列表:
-
Google Chrome 4及以上版本
-
Firefox 4及以上版本
-
Opera 12及以上版本
-
Safari從OS X Mavericks起
-
Internet Explorer及以上版本
HSTS部署
服務(wù)器開啟HSTS的方法是:當(dāng)客戶端通過HTTPS發(fā)出請求時,,在服務(wù)器返回的超文本傳輸協(xié)議響應(yīng)頭中包含Strict-Transport-Security字段,。非加密傳輸時設(shè)置的HSTS字段無效。
最佳的部署方案是部署在離用戶最近的位置,,例如:架構(gòu)有前端反向代理和后端Web服務(wù)器,,在前端代理處配置HSTS是最好的,否則就需要在Web服務(wù)器層配置HSTS,。如果Web服務(wù)器不明確支持HSTS,,可以通過增加響應(yīng)頭的機制。如果其他方法都失敗了,,可以在應(yīng)用程序?qū)釉黾親STS,。
HSTS啟用比較簡單,,只需在相應(yīng)頭中加上如下信息:
Strict-Transport-Security: max-age=63072000; includeSubdomains;preload;
Strict-Transport-Security是Header字段名,max-age代表HSTS在客戶端的生效時間,。 includeSubdomains表示對所有子域名生效,。preload是使用瀏覽器內(nèi)置的域名列表。
HSTS策略只能在HTTPS響應(yīng)中進行設(shè)置,,網(wǎng)站必須使用默認的443端口,;必須使用域名,不能是IP,。因此需要把HTTP重定向到HTTPS,,如果明文響應(yīng)中允許設(shè)置HSTS頭,中間人攻擊者就可以通過在普通站點中注入HSTS信息來執(zhí)行DoS攻擊,。
Apache上啟用HSTS
$ vim /etc/apache2/sites-available/hi-linux.conf # 開啟HSTS需要啟用headers模塊 LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so <VirtualHost *:80> ServerName www.hi-linux.com ServerAlias hi-linux.com ... #將所有訪問者重定向到HTTPS,解決HSTS首次訪問問題,。 RedirectPermanent / https://www.hi-linux.com/ </VirtualHost> <VirtualHost 0.0.0.0:443> ... # 啟用HTTP嚴格傳輸安全 Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" ... </VirtualHost>
重啟Apache服務(wù)
$ service apche2 restart
Nginx上啟用HSTS
$ vim /etc/nginx/conf.d/hi-linux.conf server { listen 443 ssl; server_name www.hi-linux.com; add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; ... } server { listen 80; server_name www.hi-linux.com; return 301 https://www.hi-linux.com$request_uri; ... }
重啟Nginx服務(wù)
$ service nginx restart
IIS啟用HSTS
要在IIS上啟用HSTS需要用到第三方模塊,具體可參考:https://hstsiis.codeplex.com/
測試設(shè)置是否成功
設(shè)置完成了后,,可以用curl命令驗證下是否設(shè)置成功,。如果出來的結(jié)果中含有Strict-Transport-Security的字段,那么說明設(shè)置成功了,。
$ curl -I https://www.hi-linux.com HTTP/1.1 200 OK Server: nginx Date: Sat, 27 May 2017 03:52:19 GMT Content-Type: text/html; charset=utf-8 ... Strict-Transport-Security: max-age=63072000; includeSubDomains; preload X-Frame-Options: deny X-XSS-Protection: 1; mode=block X-Content-Type-Options: nosniff ...
對于HSTS以及HSTS Preload List,,建議是只要不能確保永遠提供HTTPS服務(wù),就不要啟用,。因為一旦HSTS生效,,之前的老用戶在max-age過期前都會重定向到HTTPS,造成網(wǎng)站不能正確訪問,。唯一的辦法是換新域名,。
參考文檔
http://www.google.com
http://t.cn/RSzfyBb
https://yuan.ga/hsts-strict-https-enabled-site/
https://imququ.com/post/sth-about-switch-to-https.html
http://www.ttlsa.com/web/hsts-for-nginx-apache-lighttpd/
http://www.jianshu.com/p/66ddc3124006