HTTP Strict Transport Security (HSTS) in ASP.NET Core


  本文是《9012年了,還不會Https》的后篇,本文着重聊一聊 HTTP Strict Transport Security協議的概念和應用。

啟用HTTPS還不夠安全

  站點通過HTTPS 對外提供服務,用戶在訪問某站點,往往會直接輸入站點域名,而不是完整的HTTPS地址,站點一般會發送301重定向,要求瀏覽器升級到HTTPS連接。

將所有非安全請求重定向到安全URL是常規做法,但是中間人仍然可以在重定向發生前劫持連接。

  HSTS指示瀏覽器只能使用HTTPS訪問域名,來處理潛在的中間人劫持風險。即使用戶輸入或使用普通的HTTP連接,瀏覽器也嚴格將連接升級到HTTPS。

HSTS

HSTS是一種可選的安全增強策略,已經由IETF RFC6797中指定。

服務端通過Strict-Transport-Security響應頭來通知客戶端應用 HSTS協議。

Strict-Transport-Security: max-age=31536000; includeSubDomains
# inclueSubDomains 是可選參數,告知瀏覽器將HSTS策略用到當前域的子域。

一旦瀏覽器認可這個響應頭,知曉訪問這個域名的所有請求必須使用HTTPS連接,將會在1年時間內緩存這個約定。

當支持 HSTS的瀏覽器認可該響應頭:

  • 瀏覽器為域名存儲(阻止請求使用HTTP連接)配置,瀏覽器將強制所有請求通過 HTTPS
  • 瀏覽器阻止用戶使用不安全/無效證書,會顯示禁用提示(允許用戶臨時信任該證書)

因為HSTS策略由客戶端強制執行,有一些前置條件:

  • 客戶端必須支持 HSTS 協議
  • 必須要有一次成功的HTTPS請求,這樣才能建立HSTS 策略

Preload HSTS

細心的你可能發現,HSTS還是存在一個薄弱漏洞,那就是瀏覽器沒有當前HSTS信息,或者第一次訪問; 或者新操作系統,瀏覽器重裝,清除瀏覽器緩存;HSTS信息的max-age過期;

依然需要一次明文HTTP請求和重定向才能升級到HTTPS並 刷新HSTS信息,這一次依然給攻擊者可乘之機,針對以上攻擊,HSTS的應對辦法是在瀏覽器內置一個域名列表,這個列表內域名,瀏覽器都會使用HTTPS發起連接,這個列表由Chrome維護,主流瀏覽器均在使用。

Nginx

在Nginx中設置 HSTS相對簡單:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# always 參數確保所有的響應都有 STS Header, 舊版本(低於1.7.5)不支持always參數。

nginx add_header 的繼承規則:

 如果某個配置塊包含一個add_header 指令,那么將不會繼承上層的headers, 因此你需要在內部配置塊重申 add_header 指令。

server {
    listen 443 ssl;

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

    # This 'location' block inherits the STS header
    location / {
        root /usr/share/nginx/html;
    }

    # Because this 'location' block contains another 'add_header' directive,
    # we must redeclare the STS header
    location /servlet {
        add_header X-Served-By "My Servlet Handler";
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        proxy_pass http://localhost:8080;
    }
}

 

ASP.NETCore的福利時間

若使用 Kestrel 作為邊緣(face-to-internet) web服務器, 參見下面的服務配置

  • 為STS header設置了preload參數,Preload不是RFC HSTS規范的一部分,但是瀏覽器支持在全新安裝時預加載HSTS網站
  • 指定子域或排除的子域 使用HSTS協議
  • 設置瀏覽器緩存 [訪問站點的請求均使用HTTPS協議] 這一約定的時間,默認是30天。
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddHsts(options =>
    {
        options.Preload = true;
        options.IncludeSubDomains = true;
        options.MaxAge = TimeSpan.FromDays(60);
        options.ExcludedHosts.Add("example.com");
        options.ExcludedHosts.Add("www.example.com");
    });

    services.AddHttpsRedirection(options =>
    {
        options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
        options.HttpsPort = 5001;
    });
}

請注意: UseHsts 對於本地回送 hosts 並不生效

  • localhost: IPv4回送地址
  • 127.0.0.1    IPv4回送地址
  • [::1]             IPv6回送地址

這也是開發者在本地啟動時 抓不到  Strict-Transport-Security 響應頭的原因。

 

下面兩動圖演示用戶首次、后續 直接輸入域名訪問HTTPS+HSTS站點的過程, 請注意響應碼的差異。

-   動圖1 (瀏覽器無站點HSTS信息): HTTP協議請求----> 返回301,要求重定向使用HTTPS協議 -----> 使用HTTPS協議請求, 被nginx 種下HSTS信息

-  動圖2 (瀏覽器存在站點HSTS信息): HTTP 協議請求----> 307 internal redirect (瀏覽器監測到存在站點HSTS信息,直接更改為HTTPS發起請求)------> 使用HTTPS協議請求

 

 

+ nginx 啟用HSTS:  https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/

+ chrome清除HSTS信息: https://www.ssl2buy.com/wiki/how-to-clear-hsts-settings-on-chrome-firefox-and-ie-browsers

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM