編者按:很多人認(rèn)為,互聯(lián)網(wǎng)在傳遞信息的同時(shí)也傳遞著威脅和安全隱患。而Web網(wǎng)站24小時(shí)在互聯(lián)網(wǎng)上開(kāi)放某些端口、提供相關(guān)服務(wù),同時(shí),全球的Web站點(diǎn)不勝枚舉、應(yīng)有盡有。所以,Web網(wǎng)站也成為最容易被攻擊者利用的目標(biāo)。本期的兩篇文章,一篇是關(guān)于瀏覽器的內(nèi)容安全策略頭(CSP,Content Security Policy)的技術(shù)文章,另一篇?jiǎng)t是企業(yè)對(duì)Web安全網(wǎng)關(guān)的應(yīng)用案例,兩個(gè)側(cè)面、兩個(gè)維度,為讀者提供應(yīng)對(duì)普遍存在,甚至就發(fā)生在身邊的Web安全威脅的思路。
2013年11月,Veracode給出的報(bào)告指出,全球前一百萬(wàn)個(gè)網(wǎng)站中僅有269個(gè)網(wǎng)站使用了W3C規(guī)范的內(nèi)容安全策略頭(CSP,Content Security Policy)。ZoomEye在2014年2月給出的測(cè)試報(bào)告中,中國(guó)排名前7千的域名沒(méi)有使用CSP的,國(guó)內(nèi)1000的域名(含子域名)中僅發(fā)現(xiàn)7個(gè)使用了CSP策略,其中還有3個(gè)網(wǎng)站CSP出現(xiàn)語(yǔ)法使用錯(cuò)誤。
如果說(shuō)CSP是一個(gè)偉大的安全策略,為何全球范圍內(nèi)網(wǎng)站使用率如此之低?是CSP自身的設(shè)計(jì)存在問(wèn)題,還是網(wǎng)站管理員們沒(méi)有去充分了解和利用它?CSP到底是一個(gè)什么樣的安全策略,是像人們普遍說(shuō)的它是XSS攻擊的終結(jié)者嗎?
帶著以上的疑問(wèn),本文將從CSP的概念、發(fā)展時(shí)間軸、語(yǔ)法使用、如何正確部署CSP、CSP的自有特性、如何利用CSP產(chǎn)生攻擊報(bào)告、CSP當(dāng)前使用率、Bypass CSP等眾多方面,來(lái)給大家全面介紹CSP這個(gè)偉大而又被忽視的安全策略。
CSP是以可信白名單作機(jī)制,限制網(wǎng)站中是否可以包含某來(lái)源內(nèi)容。默認(rèn)配置下不允許執(zhí)行內(nèi)聯(lián)代碼(
內(nèi)聯(lián)事件
內(nèi)聯(lián)樣式
雖然CSP中已經(jīng)對(duì)script-src和style-src提供了使用“unsafe-inline”指令來(lái)開(kāi)啟執(zhí)行內(nèi)聯(lián)代碼,但為了安全起見(jiàn)還是慎用“unsafe-inline”。
2.EVAL相關(guān)功能被禁用
用戶輸入字符串,然后經(jīng)過(guò)eval()等函數(shù)轉(zhuǎn)義,進(jìn)而被當(dāng)作腳本去執(zhí)行。這樣的攻擊方式比較常見(jiàn)。于是乎CSP默認(rèn)配置下,eval(),newFunction(),setTimeout([string], ...)和setInterval([string], ...)都被禁止運(yùn)行。
比如:
alert(eval("foo.bar.baz"));
window.setTimeout("alert('hi')", 10);endprint
window.setInterval("alert('hi')", 10);
new Function("return foo.bar.baz");
如果想執(zhí)行可以把字符串轉(zhuǎn)換為內(nèi)聯(lián)函數(shù)去執(zhí)行。
alert(foo && foo.bar && foo.bar.baz);
window.setTimeout(function() { alert('hi'); }, 10);
window.setInterval(function() { alert('hi'); }, 10);
function() { return foo && foo.bar && foo.bar.baz };
同樣CSP也提供了“unsafe-eval”去開(kāi)啟執(zhí)行eval()等函數(shù),但強(qiáng)烈不建議使用“unsafe-eval”這個(gè)指令。
CSP例子
例子1:網(wǎng)站管理員想要所有的內(nèi)容均來(lái)自網(wǎng)站自己的域,不包括子域。
Content-Security-Policy: default-src 'self‘
例子2:網(wǎng)站管理員想要所有的內(nèi)容來(lái)自網(wǎng)站自己的域,還有其他子域的內(nèi)容。
Content-Security-Policy: default-src
'self' *.mydomain.com
例子3:網(wǎng)站管理員想要網(wǎng)站接受信任任意域的圖像,指定域的音頻視頻和指定域的腳本。
Content-Security-Policy: default-src 'self'; img-src *;
media-src media1.com media2.com;
script-src userscripts.example.com
在這條策略中,默認(rèn)情況下,網(wǎng)站只允許加載自己域的內(nèi)容,但也有例外:
img-src * 使用*通配符可以加載任意域的圖片。
media-src media1.com media2.com 視頻音頻只允許加載這兩個(gè)域的
script-src userscripts.example.com 腳本只能加載
userscripts.example.com 域的
例子4 :網(wǎng)站管理員確保在線銀行所有內(nèi)容都通過(guò)SSL加載,確保信息不會(huì)被截獲。
Content-Security-Policy: default-src
https://onlinebanking.jumbobank.com
例子5 :github.com上的真實(shí)CSP例子。Github允許加載任何域的內(nèi)容,但只能加載指定域的腳本,只能加載指定域的樣式并可以執(zhí)行內(nèi)聯(lián)樣式,只能通過(guò)SSL加載指定域的flash插件。
Content-Security-Policy:default-src *;
script-src 'self'
https://github.global.ssl.fastly.net
https://ssl.google-analytics.com
https://collector-cdn.github.com
https://embed.github.com
https://raw.github.com;
style-src 'self' 'unsafe-inline'
https://github.global.ssl.fastly.net;
object-src https://github.global.ssl.fastly.net
在線CSP編寫(xiě),可以協(xié)助和幫助網(wǎng)站管理員編寫(xiě)出適合自己站點(diǎn)的CSP,請(qǐng)參考http://cspisawesome.com/。
CSP的錯(cuò)誤使用
CSP的語(yǔ)法和指令其實(shí)并不復(fù)雜,但如果沒(méi)有充分了解網(wǎng)站業(yè)務(wù)和安全需求,錯(cuò)誤的使用CSP則會(huì)適得其反。
(1)筆者在2013年底訪問(wèn)http://www.grosshandel-hahn.de/,發(fā)現(xiàn)CSP策略明顯使用錯(cuò)誤。該網(wǎng)站使用了X-Content-Security-Policy-Report-Only。此頭的意思是讓瀏覽器只匯報(bào)日志,不阻止任何內(nèi)容。但這條策略里卻沒(méi)有給出接收信息日志的地址。
(2)Content-Security-Policy: default-src https:; frame-src test.com;。這個(gè)策略方案是有問(wèn)題的,此頭限制https以外的所有資源,但又允許iframe通過(guò)http進(jìn)行加載。現(xiàn)實(shí)中,這樣的場(chǎng)景應(yīng)該很難出現(xiàn)。
CSP分析報(bào)告
對(duì)于網(wǎng)站管理員來(lái)說(shuō),CSP的一個(gè)強(qiáng)大功能是它可以產(chǎn)生試圖攻擊你網(wǎng)站的分析報(bào)告。你可以用report-uri指令使瀏覽器發(fā)送HTTP POST請(qǐng)求把攻擊報(bào)告以JSON格式傳送到你指定的地址。接下來(lái)給大家介紹你的站點(diǎn)如何配置來(lái)接收攻擊報(bào)告。
啟用報(bào)告
默認(rèn)情況下,違規(guī)報(bào)告不會(huì)發(fā)送。為了能使用違規(guī)報(bào)告,你必須使用report-uri指令,并至少提供一個(gè)接收地址。
Content-Security-Policy: default-src self; report-uri http://reportcollector.example.com/collector.cgi
如果想讓瀏覽器只匯報(bào)報(bào)告,不阻止任何內(nèi)容,可以改用Content-Security-Policy-Report-Only頭。endprint
違規(guī)報(bào)告語(yǔ)法
該報(bào)告JSON對(duì)象包含以下數(shù)據(jù):
blocked-uri:被阻止的違規(guī)資源
document-uri:攔截違規(guī)行為發(fā)生的頁(yè)面
original-policy:Content-Security-Policy頭策略的所有內(nèi)容
referrer:頁(yè)面的referrer
status-code:HTTP響應(yīng)狀態(tài)
violated-directive:違規(guī)的指令
CSP的使用率統(tǒng)計(jì)
CSP全球范圍使用率非常低,而且增加也非常緩慢。而使用Content-Security-Policy-Report-Only進(jìn)行單獨(dú)接收攻擊報(bào)告的網(wǎng)站只有24個(gè)。統(tǒng)計(jì)中也指出,發(fā)現(xiàn)大量網(wǎng)站使用unsafe-inline這個(gè)指令,分析其原因可能是由于開(kāi)發(fā)人員很難在頁(yè)面中徹底消除內(nèi)聯(lián)腳本,這很讓人失望,所以只能要求制定的CSP策略更加嚴(yán)謹(jǐn)。
對(duì)于國(guó)內(nèi)網(wǎng)站使用CSP的情況,筆者委托ZoomEye對(duì)此進(jìn)行了統(tǒng)計(jì)。2014年2月發(fā)來(lái)的統(tǒng)計(jì)結(jié)果在非常不樂(lè)觀。根據(jù)ZoomEye的統(tǒng)計(jì):國(guó)內(nèi)排名前7000的域名沒(méi)有使用CSP,國(guó)內(nèi)1000萬(wàn)的域名(含子域名)中發(fā)現(xiàn)7個(gè)使用了CSP策略,其中還有3個(gè)網(wǎng)站CSP語(yǔ)法使用錯(cuò)誤。7個(gè)域名中3個(gè)是知乎網(wǎng),值得表?yè)P(yáng)。7個(gè)域名列表如下:
www.zhihu.com
www.zhi.hu
zhimg.com
www.applysquare.com
www.pipapai.com CSP語(yǔ)法錯(cuò)誤
www.icyprus.cn CSP語(yǔ)法錯(cuò)誤
www.uyitec.cn CSP語(yǔ)法錯(cuò)誤
在網(wǎng)站安全防御方面,我們還要有很長(zhǎng)的路要走。雖然CSP安全策略頭只是網(wǎng)站安全整體防御中的一小部分,但合理的利用還是可以起到很好的防護(hù)作用。然而在我們分析的百萬(wàn)網(wǎng)站中,CSP的使用率極其低,從這一點(diǎn)來(lái)說(shuō)CSP在中國(guó)應(yīng)該廣泛對(duì)網(wǎng)站管理員進(jìn)行科普。
CSP Bypass
一個(gè)安全策略從誕生開(kāi)始將會(huì)時(shí)不時(shí)有一個(gè)叫“Bypass”的小伙伴跟隨左右。而從辯證角度來(lái)講,多加載一種安全策略,就多了一種Bypass的維度。一旦Bypass出現(xiàn),就意味著將有一種設(shè)計(jì)者沒(méi)有考慮到的方法或技巧,將破壞策略的原有規(guī)則。
CSP亦是如此,在一次次被繞過(guò)然后在一次次修復(fù)過(guò)程中,來(lái)完善自己的語(yǔ)法和指令。
CSP總結(jié)
充分了解CSP安全策略的語(yǔ)法和指令,并最大程度地合理利用和部署這些策略,努力把安全策略發(fā)揮到極致,使其最終把危害降低到最低。
CSP并不能消除內(nèi)容注入攻擊,但可以有效地檢測(cè)并緩解跨站攻擊和內(nèi)容注入攻擊帶來(lái)的危害。
CSP不是作為防御內(nèi)容注入(如XSS)的第一道防線而設(shè)計(jì),而最適合部署在縱深防御體系中。
至于為什么CSP的使用率如此之低,究其原因,CSP雖然提供了強(qiáng)大的安全保護(hù),但是它也造成了如下問(wèn)題:Eval及相關(guān)函數(shù)被禁用,內(nèi)嵌的JavaScript代碼將不會(huì)執(zhí)行,只能通過(guò)白名單來(lái)加載遠(yuǎn)程腳本。這些問(wèn)題阻礙了CSP的普及。如果要使用CSP技術(shù)保護(hù)自己的網(wǎng)站,開(kāi)發(fā)者就不得不花費(fèi)大量時(shí)間分離內(nèi)聯(lián)的JavaScript代碼和做一些調(diào)整。
沒(méi)有被繞過(guò)的策略不是好的策略,從辯證角度來(lái)講,多加載一種安全策略,就多了一種Bypass的維度。在安全領(lǐng)域的“Bypass”是一個(gè)曼妙而鬼魅的名字。
應(yīng)該把CSP安全策略視為是一把可以直插心臟的鋒利的尖刀,而不是一根電線桿子杵在那。
(文章有刪減,瀏覽本文完整版請(qǐng)登錄中國(guó)計(jì)算機(jī)行業(yè)網(wǎng)www.ciw.com.cn查詢。)endprint