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

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

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

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

IP 信譽基於的是黑名單和垃圾郵件列表,再加上公共 IP 全部權數據。只要你的公司沒有垃圾郵件,而且可以快速檢測和阻止惡意軟件感染,那麼一般這些軟件應該就是乾淨的。HTTP 安全報頭使用的計算方式與Mozilla Observatory的工做方式相似。spring

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

設置正確的響應報頭能夠快速實現(一般不須要進行大量測試),並能提升網站的安全性,如今還能夠幫助咱們贏得具備安全意識的客戶。django

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

在本文中,我將介紹經常使用的評估響應報頭,及每一個報頭的推薦安全值,並給出一個響應報頭設置的示例。在本文的最後,還將給出常見的應用程序和 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

相關文章
相關標籤/搜索