本文小編為大家詳細(xì)介紹“HTML5內(nèi)容安全策略是什么”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“HTML5內(nèi)容安全策略是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來(lái)學(xué)習(xí)新知識(shí)吧。
成都創(chuàng)新互聯(lián)公司是一家專注于網(wǎng)站建設(shè)、網(wǎng)站制作與策劃設(shè)計(jì),南明網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)10多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:南明等地區(qū)。南明做網(wǎng)站價(jià)格咨詢:18982081108
萬(wàn)維網(wǎng)的安全策略植根于同源策略。例如www.mb5u.com的代碼只能訪問(wèn)www.mb5u.com的數(shù)據(jù),而沒(méi)有訪問(wèn)http://www.baidu.com的權(quán)限。每個(gè)來(lái)源都與網(wǎng)絡(luò)的其它部分分隔開(kāi),為開(kāi)發(fā)人員構(gòu)建了一個(gè)安全的沙箱。理論上這是完美的,但是現(xiàn)在攻擊者已經(jīng)找到了聰明的方式來(lái)破壞這個(gè)系統(tǒng)。
這就是XSS跨站腳本攻擊,通過(guò)虛假內(nèi)容和誘騙點(diǎn)擊來(lái)繞過(guò)同源策略。這是一個(gè)很大的問(wèn)題,如果攻擊者成功注入代碼,有相當(dāng)多的用戶數(shù)據(jù)會(huì)被泄漏。
現(xiàn)在我們介紹一個(gè)全新的、有效的安全防御策略來(lái)減輕這種風(fēng)險(xiǎn),這就是內(nèi)容安全策略(ContentSecurity Policy,CSP)。
來(lái)源白名單
XSS攻擊的核心是利用了瀏覽器無(wú)法區(qū)分腳本是被第三方注入的,還是真的是你應(yīng)用程序的一部分。例如Google +1按鈕會(huì)從https://apis.google.com/js/plusone.js加載并執(zhí)行代碼,但是我們不能指望從瀏覽器上的圖片就能判斷出代碼是真的來(lái)自apis.google.com,還是來(lái)自apis.evil.example.com。瀏覽器下載并執(zhí)行任意代碼的頁(yè)面請(qǐng)求,而不論其來(lái)源。
CSP定義了Content-Security-PolicyHTTP頭來(lái)允許你創(chuàng)建一個(gè)可信來(lái)源的白名單,使得瀏覽器只執(zhí)行和渲染來(lái)自這些來(lái)源的資源,而不是盲目信任服務(wù)器提供的所有內(nèi)容。即使攻擊者可以找到漏洞來(lái)注入腳本,但是因?yàn)閬?lái)源不包含在白名單里,因此將不會(huì)被執(zhí)行。
以上面Google +1按鈕為例,因?yàn)槲覀兿嘈臿pis.google.com提供有效的代碼,以及我們自己,所以可以定義一個(gè)策略,允許瀏覽器只會(huì)執(zhí)行下面兩個(gè)來(lái)源之一的腳本。
Content-Security-Policy:script-src 'self' https://apis.google.com
是不是很簡(jiǎn)單?script-src可以為指定頁(yè)面控制腳本相關(guān)權(quán)限。這樣瀏覽器只會(huì)下載和執(zhí)行來(lái)自http://apis.google.com和本頁(yè)自身的腳本。
一旦我們定義了這個(gè)策略,瀏覽器會(huì)在檢測(cè)到注入代碼時(shí)拋出一個(gè)錯(cuò)誤(請(qǐng)注意是什么瀏覽器)。
內(nèi)容安全策略適用于所有常用資源
雖然腳本資源是最明顯的安全隱患,但是CSP還提供了一套豐富的指令集,允許頁(yè)面控制加載各種類型的資源,例如如下的類型:
content-src:限制連接的類型(例如XHR、WebSockets和EventSource)
font-src:控制網(wǎng)絡(luò)字體的來(lái)源。例如可以通過(guò)font-src https://themes.googleusercontent.com來(lái)使用Google的網(wǎng)絡(luò)字體。
frame-src:列出了可以嵌入的frame的來(lái)源。例如frame-src https://youtube.com只允許嵌入YouTube的視頻。。
img-src:定義了可加載圖像的來(lái)源。
media-src:限制視頻和音頻的來(lái)源。
object-src:限制Flash和其他插件的來(lái)源。
style-src:類似于Script-src,只是作用于css文件。
默認(rèn)情況下,所有的設(shè)置都是打開(kāi)的,不做任何限制。你可以以分號(hào)分隔多個(gè)指令,但是類似于script-src https://host1.com;script-src https://host2.com的形式,第二個(gè)指令將會(huì)被忽略。正確的寫法是script-src https://host1.com https://host2.com。
例如,你有一個(gè)應(yīng)用需要從內(nèi)容分發(fā)網(wǎng)絡(luò)(cdn,例如https://cdn.example.net)加載所有的資源,并且知道不需要任何frame和插件的內(nèi)容,你的策略可能會(huì)像下面這樣:
Content-Security-Policy:default-src https://cdn.example.net; frame-src 'none'; object-src 'none'
細(xì)節(jié)
我在例子里使用的HTTP頭是Content-Security-Policy,但是現(xiàn)代瀏覽器已經(jīng)通過(guò)前綴來(lái)提供了支持:Firefox使用x-Content-Security-Policy,WebKit使用X-WebKit-CSP。未來(lái)會(huì)逐步過(guò)渡到統(tǒng)一的標(biāo)準(zhǔn)。
策略可以根據(jù)每個(gè)不同的頁(yè)面而設(shè)定,這提供了很大的靈活度。因?yàn)槟愕恼军c(diǎn)可能有的頁(yè)面有Google +1的按鈕,而有的則沒(méi)有。
每個(gè)指令的來(lái)源列表可以相當(dāng)靈活,你可以指定模式(data:, https:),或者指定主機(jī)名在一個(gè)范圍(example.com,它匹配主機(jī)上的任意來(lái)源、任意模式和任意端口),或者指定一個(gè)完整的URI(https://example.com:443,特指https協(xié)議,example.com域名,443端口)。
你在來(lái)源列表中還可以使用四個(gè)關(guān)鍵字:
“none”:你可能期望不匹配任何內(nèi)容
“self”:與當(dāng)前來(lái)源相同,但不包含子域
“unsafe-inline”:允許內(nèi)聯(lián)Javascript和CSS
“unsafe-eval”:允許文本到JS的機(jī)制例如eval
請(qǐng)注意,這些關(guān)鍵詞需要加引號(hào)。
沙箱
這里還有另外一個(gè)值得討論的指令:sandbox。和其他指令有些不一致,它主要是控制頁(yè)面上采取的行為,而不是頁(yè)面能夠加載的資源。如果設(shè)置了這個(gè)屬性,頁(yè)面就表現(xiàn)為一個(gè)設(shè)置了sandbox屬性的frame一樣。這對(duì)頁(yè)面有很大范圍的影響,例如防止表單提交等。這有點(diǎn)超出了本文的范圍,但是你可以在HTML5規(guī)范的“沙箱標(biāo)志設(shè)置”章節(jié)找到更多信息。
有害的內(nèi)聯(lián)代碼
CSP基于來(lái)源白名單,但是它不能解決XSS攻擊的最大來(lái)源:內(nèi)聯(lián)腳本注入。如果攻擊者可以注入包含有害代碼的script標(biāo)簽(),瀏覽器并沒(méi)有好的機(jī)制來(lái)區(qū)分這個(gè)標(biāo)簽。CSP只能通過(guò)完全禁止內(nèi)聯(lián)腳本來(lái)解決這個(gè)問(wèn)題。
這個(gè)禁止項(xiàng)不僅包括腳本中嵌入的script標(biāo)簽,還包括內(nèi)聯(lián)事件處理程序和javascrpt:這種URL。你需要把script標(biāo)簽的內(nèi)容放到一個(gè)外部文件里,并且用適當(dāng)?shù)腶ddEventListener的方式替換javascript:和。例如,你可能會(huì)把下面的表單:
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
重寫為下面的形式:
// amazing.js
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentReady', function () {
document.getElementById('amazing')
.addEventListener('click', doAmazingThings);
});
無(wú)論是否使用CSP,以上的代碼其實(shí)有更大的優(yōu)點(diǎn)。內(nèi)聯(lián)JavaScript完全混合了結(jié)構(gòu)和行為,你不應(yīng)該這么做。另外外聯(lián)資源更容易進(jìn)行瀏覽器緩存,開(kāi)發(fā)者更容易理解,并且便于編譯和壓縮。如果采用外聯(lián)代碼,你會(huì)寫出更好的代碼。
內(nèi)聯(lián)樣式需要以同樣的方式進(jìn)行處理,無(wú)論是style屬性還是style標(biāo)簽都需要提取到外部樣式表中。這樣可以防止各式各樣神奇的數(shù)據(jù)泄漏方式。
如果你必須要有內(nèi)聯(lián)腳本和樣式,可以為script-src or style-src屬性設(shè)定'unsafe-inline值。但是不要這樣做,禁止內(nèi)聯(lián)腳本是CSP提供的最大安全保證,同時(shí)禁止內(nèi)聯(lián)樣式可以讓你的應(yīng)用變得更加安全和健壯。這是一個(gè)權(quán)衡,但是非常值得。
Eval
即便攻擊者不能直接注入腳本,他可能會(huì)誘使你的應(yīng)用把插入的文本轉(zhuǎn)換為可執(zhí)行腳本并且自我執(zhí)行。eval() , newFunction() , setTimeout([string], ...) 和setInterval([string], ...) 都可能成為這種危險(xiǎn)的載體。CSP針對(duì)這種風(fēng)險(xiǎn)的策略是,完全阻止這些載體。
這對(duì)你構(gòu)建應(yīng)用的方式有一些影響:
通過(guò)內(nèi)置的JSON.parse解析JSON,而不依靠eval。IE8以后的瀏覽器都支持本地JSON操作,這是完全安全的。
通過(guò)內(nèi)聯(lián)函數(shù)代替字符串來(lái)重寫你setTimeout和setInterval的調(diào)用方式。例如:
setTimeout("document.querySelector('a').style.display = 'none';", 10);
可以重寫為:
setTimeout(function () { document.querySelector('a').style.display = 'none'; }, 10);
避免運(yùn)行時(shí)的內(nèi)聯(lián)模版:許多模版庫(kù)都使用new Function()以加速模版的生成。這對(duì)動(dòng)態(tài)程序來(lái)說(shuō)非常棒,但是對(duì)惡意文本來(lái)說(shuō)存在風(fēng)險(xiǎn)。
報(bào)告
CSP可以在服務(wù)器端阻止不可信的資源對(duì)用戶來(lái)說(shuō)非常有用,但是對(duì)于獲取各種發(fā)送到服務(wù)器的通知來(lái)說(shuō)對(duì)我們卻非常有用,這樣我們就能識(shí)別和修復(fù)任何惡意腳本注入。為此你可以通過(guò)report-uri指令指示瀏覽器發(fā)送JSON格式的攔截報(bào)告到某個(gè)地址。
Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
報(bào)告看起來(lái)會(huì)像下面這樣:
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer": "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": "script-src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
}
}
其中包含的信息會(huì)幫助你識(shí)別攔截的情況,包括攔截發(fā)生的頁(yè)面(document-uri),頁(yè)面的referrer,違反頁(yè)面策略的資源(blocked-uri),所違反的指令(violated-directive)以及頁(yè)面所有的內(nèi)容安全策略(original-policy)。
現(xiàn)實(shí)用法
CSP現(xiàn)在在Chrome 16+和Firefox 4+的瀏覽器上可用,并且它在IE10上預(yù)計(jì)會(huì)獲得有限的支持。Safari目前還不支持,但是WebKit每晚構(gòu)建版已經(jīng)可用,所以預(yù)計(jì)Safari將會(huì)在下面的迭代中提供支持。
下面讓我們看一些常用的用例:
實(shí)際案例1:社會(huì)化媒體widget
Google +1 button包括來(lái)自https://apis.google.com的腳本,以及嵌入自https://plusone.google.com的iframe。你的策略需要包含這些源來(lái)使用Google +1的按鈕。最簡(jiǎn)單的策略是script-src https://apis.google.com; frame-src https://plusone.google.com。你還需要確保Google提供的JS片段存放在外部的JS文件里。
Facebook的Like按鈕有許多種實(shí)現(xiàn)方案。我建議你堅(jiān)持使用iframe版本,因?yàn)樗梢院湍阏军c(diǎn)的其它部分保持很好的隔離。這需要使用frame-src https://facebook.com指令。請(qǐng)注意,默認(rèn)情況下,F(xiàn)acebook提供的iframe代碼使用的是相對(duì)路徑//facebook.com,請(qǐng)把這段代碼修改為https://facebook.com,HTTP你沒(méi)有必要可以不使用。
Twitter的Tweet按鈕依賴于script和frame,都來(lái)自于https://platform.twitter.com(Twitter默認(rèn)提供的是相對(duì)URL,請(qǐng)?jiān)趶?fù)制的時(shí)候編輯代碼來(lái)指定為HTTPS方式)。
其它的平臺(tái)有相似的情況,可以類似的解決。我建議把default-src設(shè)置為none,然后查看控制臺(tái)來(lái)檢查你需要使用哪些資源來(lái)確保widget正常工作。
使用多個(gè)widget非常簡(jiǎn)單:只需要合并所有的策略指令,記住把同一指令的設(shè)置都放在一起。如果你想使用上面這三個(gè)widget,策略看起來(lái)會(huì)像下面這樣:
script-src https://apis.google.com https://platform.twitter.com; frame-src https://plusone.google.com https://facebook.com https://platform.twitter.com
實(shí)際案例2:防御
假設(shè)你訪問(wèn)一個(gè)銀行網(wǎng)站,并且希望確保只加載你所需的資源。在這種情況下,開(kāi)始設(shè)置一個(gè)默認(rèn)的權(quán)限來(lái)阻止所有的內(nèi)容(default-src ‘none’),并且從這從頭構(gòu)建策略。
比如,銀行網(wǎng)站需要從來(lái)自https://cdn.mybank.net的CDN加載圖像、樣式和腳本,并且通過(guò)XHR連接到https://api.mybank.com/來(lái)拉取各種數(shù)據(jù),還需要使用frame,但是frame都來(lái)自非第三方的本地頁(yè)面。網(wǎng)站上沒(méi)有Flash、字體和其他內(nèi)容。這種情況下我們可以發(fā)送最嚴(yán)格的CSP頭是:
Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; frame-src 'self'
實(shí)際案例3:只用SSL
一個(gè)婚戒論壇管理員希望所有的資源都通過(guò)安全的方式進(jìn)行加載,但是不想真的編寫太多代碼;重寫大量第三方論壇內(nèi)聯(lián)腳本和樣式的代碼超出了他的能力。所以以下的策略將會(huì)是非常有用的:
Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'
盡管default-src指定了https,腳本和樣式不會(huì)自動(dòng)繼承。每個(gè)指令將會(huì)完全覆蓋默認(rèn)資源類型。
未來(lái)
W3C的Web應(yīng)用安全工作組正在制定內(nèi)容安全策略規(guī)范的細(xì)節(jié),1.0版本將要進(jìn)入最后修訂階段,它和本文描述的內(nèi)容已經(jīng)非常接近。而public-webappsec@郵件組正在討論1.1版本,瀏覽器廠商也在努力鞏固和改進(jìn)CSP的實(shí)現(xiàn)。
CSP 1.1在畫板上有一些有趣的地方,值得單獨(dú)列出來(lái):
通過(guò)meta標(biāo)簽添加策略:CSP的首選設(shè)置方式是HTTP頭,它非常有用,但是通過(guò)標(biāo)記或者腳本設(shè)置會(huì)更加直接,不過(guò)目前還未最終確定。WebKit已經(jīng)實(shí)現(xiàn)了通過(guò)meta元素進(jìn)行權(quán)限設(shè)置的特性,所以你現(xiàn)在可以在Chrome下嘗試如下的設(shè)置:在文檔頭添加
你甚至可以在運(yùn)行時(shí)通過(guò)腳本來(lái)添加策略。
DOM API:如果CSP的下一個(gè)迭代添加了這個(gè)特性,你可以通過(guò)Javascript來(lái)查詢頁(yè)面當(dāng)前的安全策略,并根據(jù)不同的情況進(jìn)行調(diào)整。例如在eval()是否可用的情況下,你的代碼實(shí)現(xiàn)可能會(huì)有些許不同。這對(duì)JS框架的作者來(lái)說(shuō)非常有用;并且API規(guī)范目前還非常不確定,你可以在規(guī)范草案的腳本接口章節(jié)找到最新的迭代版本。
新的指令:許多新指令正在討論中,包括script-nonce:只有明確指定的腳本元素才能使用內(nèi)聯(lián)腳本;plugin-types:這將限制插件的類型;form-action:允許form只能提交到特定的來(lái)源。
讀到這里,這篇“HTML5內(nèi)容安全策略是什么”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過(guò)才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。