書(shū)接上文——《JS 安全策略》,我們速覽了一些 Web 開(kāi)發(fā)中常見(jiàn)到的安全策略;本文繼續(xù)展開(kāi),講講另一種Web防御策略——HTTP安全標(biāo)頭(Security Header)。
概述
HTTP Headers 是客戶端和服務(wù)器在 HTTP 傳輸過(guò)程中添加的附屬信息抠璃。一個(gè)請(qǐng)求頭由名稱(不區(qū)分大小寫(xiě))后跟一個(gè)冒號(hào):
,再跟一個(gè)具體的值(不帶換行符)組成脱惰。常見(jiàn)的 Http 頭有好多種搏嗡,如:
- auth 類(lèi):Authorization,WWW-Authenticate,Proxy-Authenticate 等等
- cache 類(lèi):Age采盒,Expires旧乞,Cache-Control 等等
- 條件請(qǐng)求類(lèi):If-Match,If-Modified-Since 等等
上面這些標(biāo)頭應(yīng)該是耳熟能詳了磅氨;不過(guò)尺栖,對(duì)于安全類(lèi)的 HTTP 頭,我問(wèn)了周邊的小伙伴烦租,很多人都不熟悉延赌;所以,這期就借機(jī)介紹幾個(gè)非常實(shí)用的安全頭叉橱,大家看看自己用過(guò)幾個(gè)挫以。
Trusted Types (可信任類(lèi)型)
我們從之前提過(guò)的可信任類(lèi)型說(shuō)起。Trusted Types 主要用于防御基于 DOM 的跨站點(diǎn)腳本攻擊(DOM-based XSS)窃祝。
DOM-based XSS: 一種將惡意數(shù)據(jù)傳遞給動(dòng)態(tài)語(yǔ)言接收器的攻擊手段屡贺;在 JS 語(yǔ)言中,最常被攻擊的接收器就是:
eval()
和.innerHTML
了锌杀。
Trusted Types 就是一種黑名單機(jī)制,限制那些有安全隱患的 Web API 被瀏覽器調(diào)用泻仙。除此之外糕再,主流的瀏覽器廠商現(xiàn)在都提供了一個(gè)特殊的對(duì)象來(lái)代替上述 API,人稱 trustedTypes
玉转。
啟用 Trusted Types 的方法很簡(jiǎn)單突想,服務(wù)器返回的 HTTP 消息中帶上如下安全頭即可:
Content-Security-Policy: require-trusted-types-for 'script'
啟用后,如下代碼——修改.innerHTML
——就會(huì)直接拋出異常了究抓。
el.innerHTML = "<img src=x onerror=alert(1)>"; // This throws an exception.
至于替代手段猾担,就是利用 trustedTypes
生成的字符串繞開(kāi)檢查罷了。下例中刺下,通過(guò)使用 trustedTypes绑嘹,讓開(kāi)發(fā)人員有意識(shí)地把 inner html 中的 tag 標(biāo)簽——<
和 >
——替換為特殊符號(hào)(<
和 >
)以防止 XSS 注入。
const policy = trustedTypes.createPolicy("escapePolicy", {
createHTML: (str) => {
return str.replace(/\</g, "<").replace(/>/g, ">");
},
});
// accepted operation
const escaped = policy.createHTML("<img src=x onerror=alert(1)>");
el.innerHTML = escaped; // '<img src=x onerror=alert(1)>'
Content Security Policy(CSP)
CSP 我們講過(guò)很多次橘茉,我們?cè)倏焖龠^(guò)一遍工腋。CSP 主要用于阻止跨站點(diǎn)腳本執(zhí)行的一種安全策略。通常建議所有的 Web 應(yīng)用都開(kāi)啟 CSP:
- 如果是服務(wù)端渲染的腳本畅卓,請(qǐng)至少啟用 CSP 的 nonce 機(jī)制
- 如果是靜態(tài)資源器托管的腳本擅腰,請(qǐng)至少啟用 CSP 的 Integrity 機(jī)制
X-Content-Type-Options
部分瀏覽器(如 IE < 8.0)會(huì)出現(xiàn)一種加 MIME 混淆的情況。舉個(gè)通俗的例子翁潘,某些圖片會(huì)包含一些合法的 HTML 標(biāo)記(大家懂的)趁冈,當(dāng)那些瀏覽器加載這類(lèi)圖片時(shí)會(huì)執(zhí)行里面的 HTML 腳本,引發(fā)所謂的基于 MIME 的腳本攻擊拜马。
但是渗勘,如果服務(wù)器響應(yīng)標(biāo)頭里加上 X-Content-Type-Options: nosniff
沐绒,這種攻擊就可以避免了。因?yàn)榇藭r(shí)的瀏覽器將強(qiáng)制要求加載的資源帶上 MINE 類(lèi)型描述——Content-Type
呀邢,不然拋出異常洒沦,比如 IE 的異常如下:
SEC7112: Script from http://xxx.com was blocked due to mime type mismatch script.asp
而對(duì)于帶有 MIME 類(lèi)型的圖片資源(如image/jpeg
),瀏覽器將視作靜態(tài)資源价淌,就不會(huì)繼續(xù)執(zhí)行里面的腳本了申眼。
X-Frame-Options
X-Frame-Options 顧名思義蝉衣,和 iframe 嵌入相關(guān)的安全頭了。部分網(wǎng)站可能會(huì)將你的網(wǎng)頁(yè)當(dāng)作 iframe 嵌入濒翻,然后劫持你的用戶操作有送;一些不明真相的用戶會(huì)被劫持的反饋引向不安全的網(wǎng)站,或是泄露敏感信息雀摘。這就是經(jīng)典的 Spectre-type attacks(幽靈漏洞攻擊)阵赠。
假如你不打算別人嵌入你的網(wǎng)站肌稻,那就帶一個(gè)安全頭 X-Frame-Options: DENY
,它的<frame>
枷邪、<iframe>
齿风、<embed>
和 <object>
就對(duì)你失效了救斑。
HTTP Strict Transport Security (HSTS)
HSTS這個(gè)頭也很容易理解:強(qiáng)制使用 HTTPS 傳輸。HTTP 是不加密的連接脸候,容易被網(wǎng)絡(luò)竊聽(tīng)者截取运沦,開(kāi)啟Strict-Transport-Security
頭后携添,瀏覽器將不再加載 HTTP 相關(guān)的資源的,取而代之的是HTTPS資源羞秤。
Strict-Transport-Security: max-age=31536000
Cross-Origin(跨域)
還有一些常見(jiàn)的安全機(jī)制與跨域相關(guān)瘾蛋,我們快速過(guò)一下:
-
Cross-Origin Resource Policy (CORP)
瀏覽器的默認(rèn)機(jī)制是同源策略矫限,即不能加載跨域資源。但是取董,有些情況下我們想改變這種默認(rèn)機(jī)制甲葬,這時(shí)就可以啟用 CORP 了懈贺。CORP 只接受三個(gè)值:
same-origin
、same-site
和cross-origin
梭灿,顧名思義同源(默認(rèn))堡妒、同站點(diǎn)皮迟,以及接受跨域資源三種策略伏尼。Cross-Origin-Resource-Policy: same-origin
-
Cross-Origin Resource Sharing (CORS)
上面提到瀏覽器同源策略,開(kāi)啟同源后爆阶,我們可以通過(guò)添加白名單的形式應(yīng)對(duì)一些特殊站點(diǎn)辨图,這就是著名的 CORS 了。你只要把信任的網(wǎng)站加到安全頭上吱韭,指定的跨域資源就允許加載了:
Access-Control-Allow-Origin: https://example.com Access-Control-Allow-Credentials: true
-
Cross-Origin Embedder Policy (COEP)
COEP(跨源嵌入程序政策)通常與 CORP 和 CORS 結(jié)合使用理盆,讓嵌入你站點(diǎn)的資源(script 或 worker)也只能加載在 CORP 或是 CORS 配置后的跨域資源鸳吸。啟用方式如下:
Cross-Origin-Embedder-Policy: require-corp
COEP 的好處是開(kāi)啟跨域隔離,你可以通過(guò)
if( self.crossOriginIsolated ) {...}
來(lái)判斷坎拐。隔離成功后哼勇,就可以使用瀏覽器默認(rèn)禁止了的SharedArrayBuffer
呕乎、performance.measureUserAgentSpecificMemory()
等一些 JS Self-Profiling API 了猬仁。 -
Cross-Origin Opener Policy (COOP)
COOP 主要應(yīng)對(duì)的是用戶隱私策略湿刽,一些網(wǎng)站通過(guò)
window.open()
或是target="_blank"
的形式在瀏覽器新標(biāo)簽內(nèi)打開(kāi)其他網(wǎng)站;但是這種操作會(huì)被對(duì)方網(wǎng)站獲取到溯源信息渴庆,造成用戶隱私泄露或發(fā)起其他有害攻擊襟雷。為了避免這種意外仁烹,我們通產(chǎn)會(huì)價(jià)格 COOP 頭,防止用戶隱私泄露:Cross-Origin-Opener-Policy: same-origin-allow-popups
小結(jié)
本文列出了一些保護(hù)站點(diǎn)安全的 HTTP 標(biāo)頭叙赚。大家回去后也可以自我審查一下項(xiàng)目里有沒(méi)有使用到這些頭;如果沒(méi)有的話胧砰,要盡快開(kāi)啟尉间。這些都是久經(jīng)考驗(yàn)的策略哲嘲,開(kāi)啟后百利無(wú)一弊的眠副。
文章同步發(fā)布于an-Onion 的 Github竣稽。碼字不易,歡迎點(diǎn)贊娃弓。