[點(diǎn)晴永久免費(fèi)OA]淺淡XSS跨站腳本攻擊的防御方法
一、HttpOnly屬性 為Cookie中的關(guān)鍵值設(shè)置httponly屬性,眾所周知,大部分XSS(跨站腳本攻擊)的目的都是通過瀏覽器的同源策略,來獲取用戶Cookie,從而冒充用戶登陸系統(tǒng)的。 如果為Cookie中用于用戶認(rèn)證的關(guān)鍵值設(shè)置httponly屬性,瀏覽器將會禁止js通過同源策略訪問cookie中設(shè)有httponly屬性的信息,因此以劫持用戶認(rèn)證cookie為目的XSS攻擊將會失敗。 但很明顯,只為cookie中的值設(shè)置Httponly是不夠的,因?yàn)閄SS攻擊并不是只能獲取用戶COOKIE,它還可以竊取用戶瀏覽器信息,模擬用戶身份執(zhí)行操作等等。(具體內(nèi)容詳見:《白帽子講Web安全》) 二、對用戶輸入進(jìn)行檢查——XSS filter XSS filter是在用戶提交數(shù)據(jù)時(shí)獲取變量,并進(jìn)行XSS 過濾的。此時(shí)的XSS filter只對用戶輸入數(shù)據(jù)進(jìn)行XSS檢查,并沒有結(jié)合渲染頁面的HTML代碼。 所以針對XSS filter需要強(qiáng)調(diào)兩點(diǎn): 1.XSS filter對語境的理解并不完整(比如:無法針對輸出點(diǎn)位置進(jìn)行合適的XSS過濾。所以有時(shí)可能會造成遺漏、破壞原有語義等后果) 2.XSS filter是在服務(wù)器進(jìn)行URL解碼之前生效的,所以要考慮URL編碼繞過的問題。(比如XSS filter過濾了<script>標(biāo)簽,但如果用戶輸入的是經(jīng)過URL編碼后的<script>標(biāo)簽:%3C%73%63%72%69%70%74%3E,這樣就饒過了原本的XSS filter檢測) 三、對用戶輸出進(jìn)行檢查——安全的編碼函數(shù) (1)HtmlEncode 一般來說,在進(jìn)行XSS防御的時(shí)候,至少需要將以下字符做轉(zhuǎn)換處理: 轉(zhuǎn)換前 轉(zhuǎn)換后 & & < < > > " " '' ' / / (2)JavascriptEncode javascriptEncode的編碼方式和HtmlEncode有所不同,它使用 \ 對特殊字符進(jìn)行轉(zhuǎn)義。 常用的JavaScript編碼函數(shù)為:escapeJavascript() 該函數(shù)的功能為:將 ‘ ” < > \ & # 這些個(gè)危險(xiǎn)字符進(jìn)行轉(zhuǎn)義。 舉一個(gè)《白帽子講Web安全》里的例子 var x=1;alert(2); var y="1;alert(2)"; JS環(huán)境內(nèi),第一行的彈窗代碼會被執(zhí)行,第二行則會是安全的,即使攻擊者想要嘗試閉合",輸入的"也會被JavaScript編碼轉(zhuǎn)義為\"。這樣攻擊者相要繞過"的封鎖也會十分苦難。 不過這里需要注意: 1.如果頁面使用的是GBK編碼,可能會被攻擊者利用類似寬字節(jié)注入的方式繞過。 2.用戶的輸出如果是在標(biāo)簽內(nèi),則要求JavascriptEncode的變量輸出點(diǎn)一定要被引號包裹。 如果用戶輸出點(diǎn)太多,導(dǎo)致開發(fā)人員無法針對性的對用戶輸出進(jìn)行編碼、轉(zhuǎn)義。則可以使用更嚴(yán)格的Javascriptencode函數(shù),使用函數(shù)將除了數(shù)字、字母之外的所有字符通通都以"\xHH"的方式進(jìn)行16進(jìn)制編碼。 接下來需要介紹一個(gè)很重要的東西,是我當(dāng)天總結(jié)的重中之重!!?。。?! 相信很多初學(xué)者會和我一樣,非常好奇為什么會有Htmlencode和JavaScriptEncode兩種編碼方式,從功能上來看都可以抵御XSS攻擊,但為什么要將兩者分開使用。這是因?yàn)闉g覽器有兩套不同的自解碼機(jī)制。 1、HTML的自解碼機(jī)制 瀏覽器在解析HTML標(biāo)簽屬性值內(nèi)的代碼前,會先對下列兩種編碼進(jìn)行解碼,然后再對屬性中的代碼進(jìn)行解析。 (1)、進(jìn)制解碼:&#xH;(十六進(jìn)制格式)、&#D;(十進(jìn)制格式)。編碼中最后的分號(;)可以不要。且16進(jìn)制中用來表示10~15的a~f對大小寫不敏感 例子: <iframe src=''javascript:alert`1`''></iframe> 也可寫成 <iframe src=''javascript:alert`1`''></iframe> (2)、HTML 實(shí)體編碼 例子: <input type="button" value="test" οnclick="document.write(''<img src=@ οnerrοr=alert(123) />'')" /> 也可寫成 <input type="button" value="test" οnclick="document.write(''<img src=@ οnerrοr=alert(123) />'')" /> 2、JavaScript 自解碼機(jī)制 (1)、Unicode 形式:\uH(十六進(jìn)制)。 (2)、普通十六進(jìn)制:\xH。 (3)、純轉(zhuǎn)義:\''、\"、\<、\>這樣在特殊字符之前加\進(jìn)行轉(zhuǎn)義。 注:以上三種規(guī)則僅在通過JS更改HTML DOM樹時(shí)才適用( 例如document.write() document.getelementbyid().innerhtml=""),直接在<script>標(biāo)簽內(nèi)使用上述編碼,自解碼規(guī)則不生效。 例子: <input type="button" id="exec_btn" value="exec" /> <script> function $(id){return document.getElementById(id);}; $(''exec_btn'').onclick = function(){ document.write(''<img src=@ οnerrοr=alert(123) />'');//改代碼可執(zhí)行、可彈窗 //在JS執(zhí)行前會先將上面這行代碼先解碼為:document.write(''<img src=@ οnerrοr=alert(123)/>''); }; </script> 但如果直接在<script>標(biāo)簽內(nèi)使用該編碼,則自解碼機(jī)制不生效。 例如: <script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0032\u0033\u0029</script> 其中上述\u編碼內(nèi)容為alert(123),但該代碼并沒有更新DOM樹,所以不會彈窗。 四、針對不同的輸出點(diǎn)使用合適的編碼方式 1.輸出點(diǎn)在HTML標(biāo)簽之間 如<div>輸出點(diǎn)</div> 攻擊者如果想要構(gòu)造XSS語句并執(zhí)行,需要構(gòu)造一個(gè)能執(zhí)行腳本的環(huán)境。示例如下: <div><script>alert`1`</script></div> 此處適合使用HtmlEncode,將攻擊者輸入的<>編碼為<> 使得攻擊者無法構(gòu)造JS環(huán)境,導(dǎo)致XSS失敗。 2.輸出點(diǎn)在HTML屬性中輸出 <div id=''111'' name="輸出點(diǎn)"></div> 普通攻擊者嘗試的方法為將name屬性的雙引號閉合,然后再構(gòu)造xss語句。 <div id=''111'' name=" "><script>alert`1`</script><""></div> 此處同樣推薦使用HtmlEncode 3.輸出點(diǎn)在<script>標(biāo)簽中 在<script>標(biāo)簽中輸出時(shí),首先應(yīng)該確保輸出的變量在引號中,例如 <script> var x="輸出點(diǎn)"</script> 此處的防御思想是:使攻擊者無法閉合標(biāo)簽,導(dǎo)致無論輸入什么參數(shù)都會被瀏覽器當(dāng)作字符串處理。 此處應(yīng)使用JavascriptEncode。 4.在事件中輸出 在事件中輸出和在<script>標(biāo)簽中類似 <a href=# οnclick="funcA(''輸出點(diǎn)'')">超鏈接</a> 攻擊方法舉例: <a href=# οnclick="funcA('''');alert`1`;//'')">超鏈接</a> 5.在CSS中輸出 因?yàn)閷SS不太熟悉,所以此部分暫不介紹。 但根據(jù)白帽子一書中的介紹,推薦使用 encodeForCSS()函數(shù) 6.在地址欄中輸出 在地址欄中的輸出比較復(fù)雜,但總結(jié)起來相較于前面有兩點(diǎn)需要注意: (1).輸出點(diǎn)在路徑或者參數(shù)中。 <a >test</a> 攻擊者可按照如下方式構(gòu)造payload <a οnclick=alert(1) "">test</a> 此處的防御方法為使用URLEncode,是代碼變成下面這樣 <a >test</a> (2).輸出點(diǎn)為整個(gè)URL。 <a href="輸出點(diǎn)">test</a> 此時(shí)就不能單純的使用URLEncode來抵御XSS攻擊了,因?yàn)閰f(xié)議和域名部分是不能夠進(jìn)行URL編碼的,不然會改變原有的語意。 此處攻擊者可能會構(gòu)造偽協(xié)議實(shí)施攻擊 <a href="javascript:alert(1);">test</a> 能被攻擊者利用的偽協(xié)議有:javascript,vbscript,dataURL dataURL這個(gè)偽協(xié)議是Mozila所支持的,能夠?qū)⒁欢未a寫在URL里 <a href="data:text/html;base64,PHNjcmlwdD5hbGVydGAxYDwvc2NyaXB0Pg==">test</a> 這段base64字符串解碼后就是<script>alert`1`</script> 所以此處的防御方法應(yīng)為: <script> <style> <a>等標(biāo)簽的src和href屬性必須以白名單的方式強(qiáng)制為 http://或https://開頭,并且不能有10進(jìn)制和16進(jìn)制編碼的字符串。(此處的做法是防止攻擊者使用偽協(xié)議進(jìn)行XSS攻擊) 7.DOM型XSS的防御 如果用戶的輸出點(diǎn)在<script>之間時(shí),須先進(jìn)行一次JavaScriptEncode,在通過document.write等方式輸出到HTML頁面時(shí),如果輸出點(diǎn)為事件或者腳本,須再進(jìn)行一次JavaScriptEncode,如果輸出點(diǎn)為HTML的內(nèi)容或者屬性,則需要做一次Htmlencode。 五、總結(jié) 輸出到HTML標(biāo)簽內(nèi)或者之間,需使用HtmlEncode編碼進(jìn)行防御。 輸出到JavaScript標(biāo)簽內(nèi)或者之間,需要進(jìn)行JavaScriptencode來進(jìn)行防御。 抵御DOM型XSS,當(dāng)使用document.write等方法向HTML頁面內(nèi)輸入內(nèi)容時(shí),如過輸出點(diǎn)在JS環(huán)境內(nèi)就要再進(jìn)行一次JavascriptEncode,如果輸出點(diǎn)在HTML標(biāo)簽內(nèi),則再進(jìn)行一次HtmlEncode。 以上內(nèi)容大部分參考《白帽子講Web安全》一書。 關(guān)于XSS進(jìn)階教程強(qiáng)烈推薦大家看我的另一篇博客,事我很認(rèn)真,一點(diǎn)點(diǎn)總結(jié)出來的,但訪問量很少。。。鏈接如下:
該文章在 2020/4/8 11:57:26 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |