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