最全 HTTP 安全響應頭設置指南


銷售“安全記分卡”的公司正在崛起,並已開始成為企業銷售的一個因素。這些公司組合使用 HTTP 安全報頭和 IP 信譽來進行評級。不過,在很大程度上,公司的得分取決於對外開放網站上設置的安全響應報頭。本文介紹了常用的安全響應報頭及對應的推薦安全值,並給出了示例。

銷售“安全記分卡”的公司正在崛起,並已開始成為企業銷售的一個因素。我從客戶那里了解到,他們對從評級低的供應商那里的采購很不放心,至少有案例表明,他們依據最初的評級改變了采購決策。

我調查了這些評級公司是如何計算公司安全性得分的,結果發現他們組合使用了 HTTP 安全報頭和 IP 信譽。

IP 信譽基於的是黑名單和垃圾郵件列表,再加上公共 IP 所有權數據。只要你的公司沒有垃圾郵件,並且能夠快速檢測和阻止惡意軟件感染,那么通常這些軟件應該就是干凈的。HTTP 安全報頭使用的計算方式與Mozilla Observatory的工作方式類似。

因此,對於大多數公司來說,在很大程度上,他們的得分取決於對外開放的網站上設置的安全響應報頭。

設置正確的響應報頭可以快速實現(通常不需要進行大量測試),並能提高網站的安全性,現在還可以幫助我們贏得具有安全意識的客戶。

我對這種測試方法的價值以及這些公司提出的過高的定價方案持懷疑態度。我不認為它與真正的產品安全性有那么大的關聯。然而,這無疑增加了設置響應報頭並維護其正確性的重要性,值得為此投入時間。

在本文中,我將介紹常用的評估響應報頭,及每個報頭的推薦安全值,並給出一個響應報頭設置的示例。在本文的最后,還將給出常見的應用程序和 Web 服務器的設置示例。

重要的安全響應報頭

Content-Security-Policy(CSP)

CSP 通過指定允許加載哪些資源的形式,來防止跨站腳本注入。在本文所列的安全響應報頭中,正確地設置和維護 CSP,可能是最耗時的,也是最容易出現風險的。在開發 CSP 的過程中,要謹慎充分地測試它——以“合法”的方式阻塞站點使用的內容源會破壞站點的功能。

創建 CSP 初稿的一個很好的工具是Mozilla 實驗室的 CSP 瀏覽器擴展。在瀏覽器中安裝此擴展程序,首先充分地瀏覽要為其設置 CSP 的站點,然后在站點中使用生成的 CSP。理想情況下,還可以重構 JavaScript,使其沒有殘留的任何內聯腳本,從而使我們可以刪除“unsafe inline”指令設置。

CSP 的指令設置可能比較復雜,也很混亂,因此,如果你想更深入的了解 CSP,請訪問其官方網站

一個好的 CSP 開始可能是如下這樣的(在真正的站點上使用時,可能需要進行大量的修改)。在包含該站點的每個部分中都添加域名。

復制代碼
 
 
# 默認情況下,僅允許訪問當前站點的內容
 
# 允許訪問當前站點和 imgur.com 的圖片資源
 
# 不允許訪問 Flash、Java 等對象
 
# 僅允許訪問當前站點的腳本
 
# 僅允許訪問當前站點的樣式
 
# 僅允許嵌入當前站點的內嵌
 
# 將 <base> 標記中的 URL 限制在當前站點
 
# 表單僅允許提交到當前站點
 
Content-Security-Policy: default-src 'self'; img-src 'self' https://i.imgur.com; object-src 'none'; script-src 'self'; style-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';

Strict-Transport-Security(HSTS)

該響應報頭告訴瀏覽器,只能通過 HTTPS 訪問網站——如果網站啟用過 HTTPS,它將會一直生效。如果使用子域名,還建議在任何使用過的子域名對此加以強制。

復制代碼
 
 
Strict-Transport-Security: max-age=3600; includeSubDomains

X-Content-Type-Options

該響應報頭確保瀏覽器遵守應用程序設置的 MIME 類型。這有助於防止某些類型的跨站腳本注入攻擊。

它還能減少瀏覽器“猜測”某些內容不正確時的意外應用程序行為,例如,當開發人員將某個頁面標記為“HTML”,但瀏覽器認為它更像 JavaScript,並試圖將其渲染為 JavaScript 時。該響應報頭能確保瀏覽器始終遵守服務端設置的 MIME 類型。

復制代碼
 
 
X-Content- Type-Options: nosniff

Cache-Control(緩存控制)

這個響應報頭比其他的要稍微復雜一些,因為我們可能需要根據內容類型的不同而使用不同的緩存策略。

任何具有敏感數據的頁面,如用戶頁面或客戶結算頁面,都應該設置成無緩存。其中一個原因是,防止共享計算機上的某個人按回退按鈕或瀏覽歷史記錄又能查看到個人信息。

但是,對於像靜態資產(圖像、CSS 文件和 JS 文件)等很少變更的頁面,很適合使用緩存。既可以通過逐頁設置的方式來實現,也可以通過在服務端配置使用正則表達式的方式來實現。

復制代碼
 
 
# 默認情況不使用緩存
 
Header set Cache-Control no-cache
   
 
# 靜態資產設置成緩存 1 天
 
<filesMatch ".(css|jpg|jpeg|png|gif|js|ico)$">
 
Header set Cache-Control "max-age=86400, public"
 
</filesMatch>

Expires(過期時間)

該響應報頭能設置當前請求緩存的過期時間。如果設置了 Cache-Control 的 max-age 響應報頭,它將會被忽略,因此,在不考慮使用 Cache-Control 而進行本地緩存測試時,才設置它。

為了安全起見,我們假定瀏覽器不應該緩存任何內容,因此,我們可以把過期時間設置為一個總表示過期的數值。

復制代碼
 
 
Expires: 0

X-Frame-Options

該響應報頭用來表明站點是否允許在 iFrame 中展示。

如果惡意站點將我們的網站嵌套在 iFrame 中,那么惡意站點就可以通過運行一些 JavaScript 來執行點擊劫持攻擊,這些 JavaScript 能夠捕獲 iFrame 上的鼠標點擊事件,然后代表用戶與該站點進行交互(不必單擊需要單擊它們的地方!)。

應該始終將它設置為 deny(拒絕),除非特別需要使用內嵌,在這種情況下,應將其設置為 same-origin(同源)。如果需要在頁面中內嵌其他的站點,也可以在此處以白名單的形式列舉其他的域名。

還應該注意的是,這個響應報頭已經被 CSP 的 frame-ancestors 指令所取代。目前,我仍然建議設置該響應報頭來兼容不同的工具,但將來它可能會被逐步淘汰。

復制代碼
 
 
X- Frame-Options: deny

Access-Control-Allow-Origin

通過該響應報頭可以告訴瀏覽器,允許哪些其他站點的前端 JavaScript 代碼對頁面發出請求。除非需要設置此響應報頭,否則通常默認值就是正確的設置。

例如,如果站點 A 使用了一些 JavaScript,該 JavaScript 想要向站點 B 發出請求,那么站點 B 必須使用指定了允許站點 A 發出此請求的報頭來提供響應。如果需要設置多個源,請參見MDN 上的詳情介紹頁面

這可能有點難以理解,因此,我畫了一個圖表來說明這個響應報頭是如何工作的:

Access-Control-Allow-Origin 對應的數據流

``` Access-Control-Allow-Origin: http://www.one.site.com ```

Set-Cookie

確保 cookie 僅能通過 HTTPS(加密)傳送,並且不能通過 JavaScript 訪問。如果站點也支持 HTTPS(站點應該支持 HTTPS),那么就只能發送 HTTPS cookie。我們通常需要設置如下標志:

  • Secure

  • HttpOnly

一個定義 Cookie 的示例:

復制代碼
 
 
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly

請參閱Mozilla 文檔中的 cookies 部分以了解更多相關信息。

X-XSS-Protection

該響應報頭用來指示瀏覽器停止執行跨站腳本攻擊檢測。一般來說,設置它的風險很低,但在投入生產前仍需要進行測試。

復制代碼
 
 
X-XSS-Protection: 1; mode=block

Web 服務器的配置示例

通常,最好在服務器配置中添加站點范圍內的響應報頭。在此,cookie 是一個例外,因為它們通常是在應用程序內定義的。

在將任何響應報頭添加到站點之前,我建議首先檢查 Observatory 或手動查看響應報頭,以查看已經設置了哪些響應報頭。有些框架和服務器會自動設置其中一些響應報頭,因此,我們只需設置我們需要的或想要變更的響應報頭即可。

Apache 配置

.htaccess 中的 Apache 設置示例:

復制代碼
 
 
<IfModule mod_headers.c>
 
## CSP
 
Header set Content-Security-Policy: default-src 'self'; img-src 'self' https://i.imgur.com; object-src 'none'; script-src 'self'; style-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';
   
 
## 通用的安全響應報頭
 
Header set X-XSS-Protection: 1; mode=block
 
Header set Access-Control-Allow-Origin: http://www.one.site.com
 
Header set X-Frame-Options: deny
 
Header set X-Content-Type-Options: nosniff
 
Header set Strict-Transport-Security: max-age=3600; includeSubDomains
   
 
## 緩存策略
 
# 默認情況下不使用緩存
 
Header set Cache-Control no-cache
 
Header set Expires: 0
   
 
# 設置靜態資產緩存 1 天
 
<filesMatch ".(ico|css|js|gif|jpeg|jpg|png|svg|woff|ttf|eot)$">
 
Header set Cache-Control "max-age=86400, public"
 
</filesMatch>
   
 
</IfModule>

Nginx 設置

復制代碼
 
 
## CSP
 
add_header Content-Security-Policy: default-src 'self'; img-src 'self' https://i.imgur.com; object-src 'none'; script-src 'self'; style-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';
   
 
## 通用的安全響應報頭
   
 
add_header X-XSS-Protection: 1; mode=block;
 
add_header Access-Control-Allow-Origin: http://www.one.site.com;
 
add_header X-Frame-Options: deny;
 
add_header X-Content-Type-Options: nosniff;
 
add_header Strict-Transport-Security: max-age=3600; includeSubDomains;
   
 
## 緩存策略
   
 
** 默認不使用緩存 **
   
 
add_header Cache-Control no-cache;
 
add_header Expires: 0;
   
 
** 設置靜態資產緩存 1 天 **
   
 
location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ {
 
try_files $uri @rewriteapp;
 
add_header Cache-Control "max-age=86400, public";
 
}

應用程序級的響應報頭設置

如果我們沒有訪問 Web 服務器的權限,或者需要設置復雜的響應報頭,那么我們就可能需要在應用程序內設置這些響應報頭了。這通常可以在整個站點的框架中間件中實現,也可以在每次響應的基礎上進行一次性的報頭設置。

為了簡便起見,在示例中,只包含了一個響應報頭。所需的全部響應報頭都是以相同的方式通過該方法來添加的。

Node 及 express:

添加一個全局掛載路徑:

復制代碼
 
 
app.use( function(req, res, next) {
 
res.header( 'X-XSS-Protection', 1; mode=block);
 
next();
 
});

Java 及 Spring:

我沒有太多的 Spring 實踐經驗,但Baeldung對在 Spring 中如何設置響應報頭提供了很好的指導。

PHP:

我對各種 PHP 框架不是很熟悉。查找了能夠處理請求的中間件。對於單個響應,它的設置非常簡單。

復制代碼
 
 
header( "X-XSS-Protection: 1; mode=block");

Python 及 Django

Django 包含可配置的安全中間件,通過該中間件來處理所有響應報頭的設置。首先啟用它們。

對於特定頁面,可以將響應視為字典。Django 有一個處理緩存的特殊方法,如果試圖以這種方式設置緩存響應報頭,那么就應該調研后再使用。

復制代碼
 
 
response = HttpResponse()
 
response["X-XSS-Protection"] = "1; mode=block"

總結

設置響應報頭相對來說比較簡單快捷。在數據保護、跨站腳本注入和點擊劫持方面,站點安全性將會有相當大的提高。

還可以確保我們不會因為依賴此信息的公司安全評級而失去未來的業務交易。這種做法似乎越來越多,我希望在未來幾年,它能繼續在企業銷售中發揮作用。

如果以上有所遺漏,你認為還應該包含其他的安全響應報頭,請留言回復。

英文原文:https://nullsweep.com/http-security-headers-a-complete-guide


免責聲明!

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



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