header的安全配置指南

wyzsk發表於2020-08-19
作者: 龍臣 · 2014/03/15 11:05

from:https://blog.veracode.com/2014/03/guidelines-for-setting-security-headers/

0x00 背景


在統計了Alexa top 100萬網站的header安全分析之後(2012年11月 - 2013年3月 - 2013年11月),我們發現其實如何正確的設定一個header並不是一件容易的事情。儘管有數不勝數的網站會使用大量有關安全方面的header,但並沒有一個像樣的平臺能夠為開發者們提供必要的資訊,以辨別那些常見的錯誤設定。或者說,即使這些安全方面的header設定正確了,也沒有一個平臺能夠為開發者提供一個系統的測試方法,用來測試正確與否。這些header如果設定錯誤了不僅會產生安全的假象,甚至會對網站的安全產生威脅。veracode認為安全性header是網路防護中非常重要的一環,並且他希望讓開發者們能夠簡捷、正確地設定站點。如果您對某一header或設定有任何疑問,我們有極好的資源能夠追蹤到瀏覽器支援情況。

0x01 細節


1. X-XSS-Protection

目的

這個header主要是用來防止瀏覽器中的反射性xss。現在,只有IE,chrome和safari(webkit)支援這個header。

正確的設定

0 – 關閉對瀏覽器的xss防護  
1 – 開啟xss防護  
1; mode=block – 開啟xss防護並通知瀏覽器阻止而不是過濾使用者注入的指令碼。  
1; report=http://site.com/report – 這個只有chrome和webkit核心的瀏覽器支援,這種模式告訴瀏覽器當發現疑似xss攻擊的時候就將這部分資料post到指定地址。  

通常不正確的設定

0; mode=block; – 記住當配置為0的時候,即使加了mode=block選項也是沒有效果的。需要指出的是,chrome在發現這種錯誤的配置後還是會開啟xss防護。  
1 mode=block; – 數字和選項之間必須是用分號分割,逗號和空格都是錯誤的。但是這種錯誤配置情況下,IE和chrome還是預設會清洗xss攻擊,但是不會阻攔。 

如何檢測

如果過濾器檢測或阻攔了一個反射性xss以後,IE會彈出一個對話方塊。當設定為1時,chrome會隱藏對反射性xss的輸出。如果是設定為 1; mode=block ,那麼chrome會直接將user-agent置為一個空值:, URL  這種形式。

參考文獻

Post from Microsoft on the X-XSS-Protection Header
Chromium X-XSS-Protection Header Parsing Source
Discussion of report format in WebKit bugzilla

2. X-Content-Type-Options

目的

這個header主要用來防止在IE9、chrome和safari中的MIME型別混淆攻擊。firefox目前對此還存在爭議。通常瀏覽器可以透過嗅探內容本身的方法來決定它是什麼型別,而不是看響應中的content-type值。透過設定 X-Content-Type-Options:如果content-type和期望的型別匹配,則不需要嗅探,只能從外部載入確定型別的資源。舉個例子,如果載入了一個樣式表,那麼資源的MIME型別只能是text/css,對於IE中的指令碼資源,以下的內容型別是有效的:

application/ecmascript  
application/javascript  
application/x-javascript  
text/ecmascript  
text/javascript  
text/jscript  
text/x-javascript  
text/vbs  
text/vbscript  

對於chrome,則支援下面的MIME 型別:

text/javascript  
text/ecmascript  
application/javascript  
application/ecmascript  
application/x-javascript  
text/javascript1.1  
text/javascript1.2  
text/javascript1.3  
text/jscript  
text/live script

正確的設定

nosniff – 這個是唯一正確的設定,必須這樣。  

通常不正確的設定

‘nosniff’ – 引號是不允許的  
: nosniff – 冒號也是錯誤的  

如何檢測

在IE和chrome中開啟開發者工具,在控制檯中觀察配置了nosniff和沒有配置nosniff的輸出有啥區別。

參考文獻

Microsoft Post on Reducing MIME type security risks
Chromium Source for parsing nosniff from response
Chromium Source list of JS MIME types
MIME Sniffing Living Standard

3. X-Frame-Options

目的

這個header主要用來配置哪些網站可以透過frame來載入資源。它主要是用來防止UI redressing 補償樣式攻擊。IE8和firefox 18以後的版本都開始支援ALLOW-FROM。chrome和safari都不支援ALLOW-FROM,但是WebKit已經在研究這個了。

正確的設定

DENY – 禁止所有的資源(本地或遠端)試圖透過frame來載入其他也支援X-Frame-Options 的資源。  
SAMEORIGIN – 只允許遵守同源策略的資源(和站點同源)透過frame載入那些受保護的資源。  
ALLOW-FROM http://www.example.com – 允許指定的資源(必須帶上協議http或者https)透過frame來載入受保護的資源。這個配置只在IE和firefox下面有效。其他瀏覽器則預設允許任何源的資源(在X-Frame-Options沒設定的情況下)。 

通常不正確的設定

ALLOW FROM http://example.com – ALLOW和FROM 之間只能透過連字元來連線,空格是錯誤的。  
ALLOW-FROM example.com – ALLOW-FROM選項後面必須跟上一個URI而且要有明確的協議(http或者https)  

如何檢測

可以透過訪問test cases 來檢視各種各樣的選項 和瀏覽器對這些frame中的資源的響應。

參考文獻

X-Frame-Options RFC
Combating ClickJacking With X-Frame-Options

4. Strict-Transport-Security

目的

Strict Transport Security (STS) 是用來配置瀏覽器和伺服器之間安全的通訊。它主要是用來防止中間人攻擊,因為它強制所有的通訊都走TLS。目前IE還不支援 STS頭。需要注意的是,在普通的http請求中配置STS是沒有作用的,因為攻擊者很容易就能更改這些值。為了防止這樣的現象發生,很多瀏覽器內建了一個配置了STS的站點list。
 
正確的設定  
注意下面的值必須在https中才有效,如果是在http中配置會沒有效果。
 

max-age=31536000 – 告訴瀏覽器將域名快取到STS list裡面,時間是一年。  
max-age=31536000; includeSubDomains – 告訴瀏覽器將域名快取到STS list裡面並且包含所有的子域名,時間是一年。  
max-age=0 – 告訴瀏覽器移除在STS快取裡的域名,或者不儲存此域名。  

通常不正確的設定

直接將includeSubDomains設定為 https://www.example.com ,但是使用者依然可以透過 http://example.com 來訪問此站點。如果example.com 並沒有跳轉到 https://example.com 並設定 STS header,那麼訪問 http://www.example.com 就會直接被瀏覽器重定向到 https://www.example.com 。  
max-age=60 – 這個只設定域名儲存時間為60秒。這個時間太短了,可能並不能很好的保護使用者,可以嘗試先透過http來訪問站點,這樣可以縮短傳輸時間。  
max-age=31536000 includeSubDomains – max-age 和 includeSubDomains 直接必須用分號分割。這種情況下,即使max-age的值設定的沒有問題,chrome也不會將此站點儲存到STS快取中。  
max-age=31536000, includeSubDomains – 同上面情況一樣。  
max-age=0 – 儘管這樣在技術上是沒有問題的,但是很多站點可能在處理起來會出差錯,因為0可能意味著永遠不過期。 

如何檢測

判斷一個主機是否在你的STS快取中,chrome可以透過訪問chrome://net-internals/#hsts,首先,透過域名請求選項來確認此域名是否在你的STS快取中。然後,透過https訪問這個網站,嘗試再次請求返回的STS頭,來決定是否新增正確。

參考文獻

Strict Transport Security RFC6797
Wikipedia page on Strict Transport Security (with examples)

5. Public-Key-Pins (起草中)

目的

有關這個header的詳細描述還在起草中,但是它已經有了很清晰的安全作用,所以我還是把它放在了這個list裡面。Public-Key-Pins (PKP)的目的主要是允許網站經營者提供一個雜湊過的公共金鑰儲存在使用者的瀏覽器快取裡。跟Strict-Transport-Security功能相似的是,它能保護使用者免遭中間人攻擊。這個header可能包含多層的雜湊運算,比如pin-sha256=base64(sha256(SPKI)),具體是先將 X.509 證照下的Subject Public Key Info (SPKI) 做sha256雜湊運算,然後再做base64編碼。然而,這些規定有可能更改,例如有人指出,在引號中封裝雜湊是無效的,而且在33版本的chrome中也不會儲存pkp的雜湊到快取中。

這個header和 STS的作用很像,因為它規定了最大子域名的數量。此外,pkp還提供了一個Public-Key-Pins-Report-Only 頭用來報告異常,但是不會強制阻塞證照資訊。當然,這些chrome都是不支援的。

正確的設定

max-age=3000; pin-sha256=”d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=”; – 規定此站點有3000秒的時間來對x.509證照專案中的公共金鑰資訊(引號裡面的內容)做sha256雜湊運算再做base64編碼。  
max-age=3000; pin-sha256=”d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=”; report-uri=”http://example.com/pkp-report” – 同上面一樣,區別是可以報告異常。  

通常不正確的設定

max-age=3000; pin-sha256=d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=; – Not encapsulating the hash value in quotes leads to Chrome 33 not adding the keys to the PKP cache. This mistake was observed in all but one of the four sites that returned this or the report-only header response.沒有新增引號,這樣的話chrome不會將這個key新增到PKP快取中。我們的調查中發現有四分之一的網站存在此問題。

如何檢測

如果站點成功的將pkp雜湊存入了客戶端快取,那麼使用和Strict-Transport-Security (STS)相同的方法檢視pubkey_hashes 資訊就可以了。

參考文獻

Public-Key-Pins draft specification
Chrome issue tracking the implementation of Public-Key-Pins
Chromium source code for processing Public-Key-Pins header

6. Access-Control-Allow-Origin

目的

Access-Control-Allow-Origin是從Cross Origin Resource Sharing (CORS)中分離出來的。這個header是決定哪些網站可以訪問資源,透過定義一個萬用字元來決定是單一的網站還是所有網站可以訪問我們的資源。需要注意的是,如果定義了萬用字元,那麼 Access-Control-Allow-Credentials選項就無效了,而且user-agent的cookies不會在請求裡傳送。

正確的設定

* – 萬用字元允許任何遠端資源來訪問含有Access-Control-Allow-Origin 的內容。  
http://www.example.com – 只允許特定站點才能訪問(http://[host], 或者 https://[host]) 

通常不正確的設定

http://example.com, http://web2.example.com – 多個站點是不支援的,只能配置一個站點。  
*.example.com – 只允許單一的站點  
http://*.example.com – 同上面一樣  

如何檢測

很容易就能確定這個header是否被設定的正確,因為如果設定錯誤的話,CORS請求就會接收不到資料。

參考文獻

W3C CORS specification
Content-Security-Policy 1.0

目的

csp是一些指令的集合,可以用來限制頁面載入各種各樣的資源。目前,IE瀏覽器只支援CSP的一部分,而且僅支援X-Content-Security-Policy header。 相比較而言,Chrome和Firefox則支援CSP的1.0版本,csp的1.1版本則還在開發中。透過恰當的配置csp,可以防止站點遭受很多型別的攻擊,譬如xss和UI補償等相關問題。

csp總共有10種配置形式,每一種都可以用來限制站點何時載入和載入何種型別的資源。他們分別是:

default-src:這種形式預設設定為 script-src, object-src, style-src, img-src, media-src, frame-src, font-src和connect-src.如果上述設定一個都沒有的話,user-agent就會被用來作為default-src的值。

script-src:這種形式也有兩個附加的設定。

1、unsafe-inline:允許資源執行指令碼。舉個例子,on事件的值會被編碼到html程式碼中,或者指令碼元素的text的內容會被混入到受保護的資源中。  
2、unsafe-eval:允許資源動態的執行函式,比如eval,setTimeout, setInterval, new等函式。

object-src – 決定從哪裡載入和執行外掛。
style-src – 決定從哪裡載入css和樣式標記。
img-src – 決定從哪裡載入圖片。
media-src – 決定從哪裡載入影片和音訊資源。
frame-src – 決定哪裡的frames 可以被嵌入。
font-src – 決定從哪裡載入字型。
connect-src – 限制在 XMLHttpRequest, WebSocket 和 EventSource 中可以使用哪些型別的資源。
sandbox – 這是一個可選形式,它決定了沙盒的策略,如何將內容嵌入到沙盒中以保證安全。

當這個策略被特定的url違反了,我們也可以用報告地址直接傳送報告。這樣做有利於debug和當攻擊發生時通知我們。

此外, 我們可以定義Content-Security-Policy-Report-Only 的 header不強制遵守csp,但是會傳送潛在的威脅到一個報告地址。它遵守和csp一樣的語法和規則。

正確的設定

View cspplayground.com compliant examples  

通常不正確的設定:

View cspplayground.com violation examples  

如何檢測

在chrome和firefox中開啟開發者工具或者firebug,在控制檯檢視是否有潛在的威脅。

參考文獻

Content Security Policy 1.0 Specification
Content Security Policy 1.1 Working Draft Specification
cspplayground.com’s excellent collection of resources for CSP
Sublime Text 2 Plugin for validating HTML/JS while you code your site

關於Alexa排名top 100萬網站的安全header的研究

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章