1. 程式人生 > >開啟HSTS讓瀏覽器強制跳轉HTTPS訪問

開啟HSTS讓瀏覽器強制跳轉HTTPS訪問

在網站全站HTTPS後,如果使用者手動敲入網站的HTTP地址,或者從其它地方點選了網站的HTTP連結,通常依賴於服務端301/302跳轉才能使用HTTPS服務。而第一次的HTTP請求就有可能被劫持,導致請求無法到達伺服器,從而構成HTTPS降級劫持。這個問題目前可以通過HSTS(HTTP Strict Transport Security,RFC6797)來解決。

HSTS簡介

HSTS(HTTP Strict Transport Security)是國際網際網路工程組織IETF釋出的一種網際網路安全策略機制。採用HSTS策略的網站將保證瀏覽器始終連線到該網站的HTTPS加密版本,不需要使用者手動在URL位址列中輸入加密地址,以減少會話劫持風險。

HSTS響應頭格式

Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]
  • max-age,單位是秒,用來告訴瀏覽器在指定時間內,這個網站必須通過HTTPS協議來訪問。也就是對於這個網站的HTTP地址,瀏覽器需要先在本地替換為HTTPS之後再發送請求。
  • includeSubDomains,可選引數,如果指定這個引數,表明這個網站所有子域名也必須通過HTTPS協議來訪問。
  • preload,可選引數,一個瀏覽器內建的使用HTTPS的域名列表。

HSTS Preload List

雖然HSTS可以很好的解決HTTPS降級攻擊,但是對於HSTS生效前的首次HTTP請求,依然無法避免被劫持。瀏覽器廠商們為了解決這個問題,提出了HSTS Preload List

方案:內建一份可以定期更新的列表,對於列表中的域名,即使使用者之前沒有訪問過,也會使用HTTPS協議。

目前這個Preload List由Google Chrome維護,Chrome、Firefox、Safari、IE 11和Microsoft Edge都在使用。如果要想把自己的域名加進這個列表,首先需要滿足以下條件:

  • 擁有合法的證書(如果使用SHA-1證書,過期時間必須早於2016年);
  • 將所有HTTP流量重定向到HTTPS;
  • 確保所有子域名都啟用了HTTPS;
  • 輸出HSTS響應頭:
  • max-age不能低於18周(10886400秒);
  • 必須指定includeSubdomains引數;
  • 必須指定preload引數;

即便滿足了上述所有條件,也不一定能進入HSTS Preload List,更多資訊可以檢視:https://hstspreload.org/

通過Chrome的chrome://net-internals/#hsts工具,可以查詢某個網站是否在Preload List之中,還可以手動把某個域名加到本機Preload List。

HSTS缺點

HSTS並不是HTTP會話劫持的完美解決方案。使用者首次訪問某網站是不受HSTS保護的。這是因為首次訪問時,瀏覽器還未收到HSTS,所以仍有可能通過明文HTTP來訪問。

如果使用者通過HTTP訪問HSTS保護的網站時,以下幾種情況存在降級劫持可能:

  • 以前從未訪問過該網站
  • 最近重新安裝了其作業系統
  • 最近重新安裝了其瀏覽器
  • 切換到新的瀏覽器
  • 切換到一個新的裝置,如:行動電話
  • 刪除瀏覽器的快取
  • 最近沒訪問過該站並且max-age過期了

解決這個問題目前有兩種方案:

方案一:在瀏覽器預置HSTS域名列表,就是上面提到的HSTS Preload List方案。該域名列表被分發和硬編碼到主流的Web瀏覽器。客戶端訪問此列表中的域名將主動的使用HTTPS,並拒絕使用HTTP訪問該站點。

方案二:將HSTS資訊加入到域名系統記錄中。但這需要保證DNS的安全性,也就是需要部署域名系統安全擴充套件。

其它可能存在的問題

由於HSTS會在一定時間後失效(有效期由max-age指定),所以瀏覽器是否強制HSTS策略取決於當前系統時間。大部分作業系統經常通過網路時間協議更新系統時間,如Ubuntu每次連線網路時,OS X Lion每隔9分鐘會自動連線時間伺服器。攻擊者可以通過偽造NTP資訊,設定錯誤時間來繞過HSTS。

解決方法是認證NTP資訊,或者禁止NTP大幅度增減時間。比如:Windows 8每7天更新一次時間,並且要求每次NTP設定的時間與當前時間不得超過15小時。

支援HSTS瀏覽器

目前主流瀏覽器都已經支援HSTS特性,具體可參考下面列表:

  • Google Chrome 4及以上版本
  • Firefox 4及以上版本
  • Opera 12及以上版本
  • Safari從OS X Mavericks起
  • Internet Explorer及以上版本

HSTS部署

伺服器開啟HSTS的方法是:當客戶端通過HTTPS發出請求時,在伺服器返回的超文字傳輸協議響應頭中包含Strict-Transport-Security欄位。非加密傳輸時設定的HSTS欄位無效。

最佳的部署方案是部署在離使用者最近的位置,例如:架構有前端反向代理和後端Web伺服器,在前端代理處配置HSTS是最好的,否則就需要在Web伺服器層配置HSTS。如果Web伺服器不明確支援HSTS,可以通過增加響應頭的機制。如果其他方法都失敗了,可以在應用程式層增加HSTS。

HSTS啟用比較簡單,只需在相應頭中加上如下資訊:

Strict-Transport-Security: max-age=63072000; includeSubdomains;preload;

Strict-Transport-Security是Header欄位名,max-age代表HSTS在客戶端的生效時間。 includeSubdomains表示對所有子域名生效。preload是使用瀏覽器內建的域名列表。

HSTS策略只能在HTTPS響應中進行設定,網站必須使用預設的443埠;必須使用域名,不能是IP。因此需要把HTTP重定向到HTTPS,如果明文響應中允許設定HSTS頭,中間人攻擊者就可以通過在普通站點中注入HSTS資訊來執行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服務

$ 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服務

$ service nginx restart

IIS啟用HSTS

測試設定是否成功

設定完成了後,可以用curl命令驗證下是否設定成功。如果出來的結果中含有Strict-Transport-Security的欄位,那麼說明設定成功了。

$ 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服務,就不要啟用。因為一旦HSTS生效,之前的老使用者在max-age過期前都會重定向到HTTPS,造成網站不能正確訪問。唯一的辦法是換新域名。