最近在研讀《白帽子講web安全》和《Web前端黑客技術揭秘》,為了加深印象,閑暇之時做了一些總結。
下面是書中出現的一些專有詞匯:
POC(Proof Of Concept):觀點驗證程序,運行這個程序就可以得出預期的結果,也就驗證了觀點。
Payload:有效負載,在病毒代碼中實現這個功能的部分。
OWASP:開放式Web應用程序安全項目組織,協助個人、企業和機構來發現和使用可信賴軟件。
XSS(Cross Site Script):跨站腳本攻擊,想盡一切辦法將你的腳本內容在目標網站中的目標用戶的瀏覽器中執行。
如果要調試代碼,可以直接在codepen的頁面中進行。
一、XSS的幾種類型
1)反射型XSS
XSS代碼出現在URL中,作為輸入提交到服務器,瀏覽器解析執行。也就是誘使用戶點擊一個惡意鏈接,發起攻擊。
http://www.xss.com?x=<script>alert('xss')</script>
2)存儲型XSS
提交的XSS代碼會存儲在服務器中(數據庫、文件等媒介中),下次請求頁面不用再提交XSS代碼,典型的場景有博客文章、留言板等。
3)DOM Based XSS
與前面兩種不一樣的地方是不需要提交到服務器中,可直接在瀏覽器中執行
//輸入http://www.xss.com#alert(1) //執行錨點內容 顯示提示框 eval(location.hash.substr(1))
常見的輸入輸出點可利用下面這些:
//常見的輸入點: document.URL document.URLUnencoded document.location(and many of its properties) document.referrer window.location(and many of its properties) //常見的輸出點: document.write(…) document.writeln(…) document.body.innerHtml = … //直接修改DOM樹: document.forms[0].action = … (and various other collections) document.attachEvent(…) document.create…(…) document.execCommand(…) document.body.…(accessing the DOM through the body object) window.attachEvent(…) //替換document URL: document.location = … (and assigning to location’ s href, host and hostname) document.location.hostname = … document.location.replace(…) document.location.assign(…) document.URL = … window.navigate(…) //打開或修改新窗口: document.open(…) window.open(…) window.location.href = … (and assigning to location’ s href, host and hostname) //直接執行腳本: eval(…) window.execScript(…) window.setInterval(…) window.setTimeout(…)
二、XSS的危害
1)掛馬
所謂掛馬就是通過各種方法獲得網站管理員賬號,然后登陸網站后台,網頁掛馬可通過嵌入iframe實現。
2)盜取用戶Cookie
通過“document.cookie”讀取Cookie信息,發起劫持,可直接通過加密的Cookie登錄憑證登錄進用戶的賬戶。
3)DDoS(Distributed Denial of Service)分布式拒絕攻擊
在目標瀏覽器中注入Ajax請求的代碼,Ajax請求的響應有同源策略的限制,但請求不會,所以可以同時發起請求攻擊。
4)釣魚攻擊
在網頁中,偽造真實的登錄框,欺騙用戶登錄時,賬號密碼就會被盜取。
5)劫持用戶Web行為
網站的很多操作是通過HTTP的get或post請求完成的,攻擊者可通過代碼發起這兩種請求,例如構造form、ajax等。
6)XSS Worm(蠕蟲)
當被攻擊用戶查看存在XSS蠕蟲代碼的內容時,蠕蟲觸發並開始感染傳播。
用戶之間發生交互行為的頁面,存在存儲型XSS,比較容易發起XSS Worm攻擊。
三、XSS構造技巧
1)利用字符編碼
這里要提一下HTML與JavaScript自解碼機制,能夠自動執行特定的方式。
1. HTML編碼,具體有如下幾種形式:
1. 進制編碼:&#xH;(十六進制格式)、&#D;(十進制格式),最后的分號(;)可以不要。 2. HTML 實體編碼(HtmlEncode),例如“ 、<”等。
<button onclick="document.write('<img src=@ onerror=alert(123) />')">click</button>
2. JavaScript編碼,具體有如下幾種形式:
1. Unicode 形式:\uH (十六進制)。 2. 普通十六進制:\xH。 3. 純轉義: \' 、 \" 、 \< 、 > 這樣在特殊字符之前加 \ 進行轉義。
//顯示彈出框 document.write("\<img src\=@ onerror=alert\(123\) \/\>")
單純的輸入“<script>”等這些代碼可能就會被馬上過濾,但是如果再編碼一次上面的幾種形式,服務器過濾的時候可能就會漏掉。
關於編碼的更多信息可以參考《JavaScript字符集編碼與解碼》。
還可以使用多種編碼混淆在一起,更易於繞過服務器過濾。
<!--10進制編碼background,16進制編碼red--> <div style="background:\72\65\64;">content</div>
3. 標簽天生具備HtmlEncode編碼,包括標簽“title、iframe、noscript、noframes、textarea、xmp、plaintext”。以textarea為例:
<textarea id="textarea"> <div>222</div> </textarea>
//<div>222</div> document.getElementById('textarea').innerHTML
2)base標簽
base標簽定義頁面上所有相對路徑標簽的host地址。
插入此標簽設置域名,然后在遠程服務器上定義相同文件名以及路徑,劫持當前頁面所有使用相對路徑的標簽。
<base href="http://www.pwstrick.com"/> <!--解析為http://www.pwstrick.com/dist/x.jpg--> <img src='/dist/x.jpg' />
3)window.name的使用
window對象不受同源策略的限制,可通過name屬性實現跨域、跨頁面傳遞參數。
window.name="alert(document.cookie)"; //在另外要攻擊的頁面中注入 就能繞過長度限制執行代碼 eval(window.name);
有網友總結了繞過長度限制的技巧,但沒找到排版漂亮的版本,只找到百度文檔中的一篇,湊合一下看看吧《突破XSS字符數量限制》
4)DOM fuzzing技巧
模糊測試(fuzzing)就是生成特定的數據輸入到程序的某個位置,監視程序異常、奔潰、顯示結果等。
在前端中可以將代碼寫到HTML、JavaScript或CSS中都可。
通過在線fuzzing工具Shazzer可以了解更多,不過要注冊Twitter賬號,我注冊成功了但授權沒成功,還是不能創建Vector,可惜了。
不過在網站上還是可以看到別人的編寫的一些代碼。

5)其他
在網上還有個開源小工具XSSProbe,代碼簡單可供參考。
瀏覽器有兼容特點,所以可以針對不同的瀏覽器注入不同代碼,瀏覽器探測可參考《Detecting browsers javascript hacks》
四、XSS防御
1)HttpOnly
瀏覽器將禁止頁面的JS訪問帶有HttpOnly屬性的Cookie。此屬性解決的是XSS后的Cookie劫持攻擊。
Cookie的使用過程大致如下:
1. 瀏覽器向服務器發起請求
2. 服務器響應后發送Set-Cookie頭(此時可設置HttpOnly),向客戶端瀏覽器寫入Cookie
3. 瀏覽器訪問該域下的所有頁面都將發送該Cookie(只要Cookie還沒過期)
<?php header("Set-Cookie: hidden=value; httpOnly");
2)輸入檢查
在服務器與客戶端添加驗證規則,在特定的地方使用特定的規則,例如不匹配“script標簽或<、>特殊符號”等。
啟用“白名單原則”,可用於標簽、屬性或事件,只讓正常的“a、div”等標簽通過。
下面是FindingDOMXSS中對輸入點(sources)的匹配規則:
/(location\s*[\[.])|([.\[]\s*["']?\s*(arguments|dialogArguments|innerHTML|write(ln)?
|open(Dialog)?|showModalDialog|cookie|URL|documentURI|baseURI|referrer|
name|opener|parent|top|content|self|frames)\W)|(localStorage|sessionStorage|Database)/
3)輸出檢查
變量輸出到HTML頁面時,可以使用編碼或轉義的方式防御XSS攻擊。
針對HTML與JavaScript的編碼可通過HtmlEncode和JavaScriptEncode實現,具體的函數內容可參考此處。
在PHP中,可以使用一個開源的項目HTML Purifier實現對XSS的檢查。
在FindingDOMXSS中同樣給出了輸出點(sinks)的匹配規則:
/((src|href|data|location|code|value|action)\s*["'\]]*\s*\+?\s*=)|
((replace|assign|navigate|getResponseHeader|open(Dialog)?|showModalDialog|
eval|evaluate|execCommand|execScript|setTimeout|setInterval)\s*["'\]]*\s*\()/
4)DOM Based XSS防御
DOM Based XSS是直接從“JavaScript”中輸出數據到HTML頁面里,前面提到的都是從“服務器”中輸出。
//x是從服務器中輸出的,並且做了JavaScriptEncode操作 var x="\x20\x27onclick\x3dalert\x281\x29\x3b"; //在輸出后會變成<a href=" " onclick="alert(1);">test</a>還是能執行點擊 document.write("<a href='"+x+">test</a>");
所以要在合適的地方再做一次編碼操作,下面是分情況說明:
如果輸出到事件或腳本中,則再做一次JavaScriptEncode;如果輸出到HTML內容或屬性中,就再做一次HtmlEncode。
在OWASP中有一篇《DOM based XSS Prevention Cheat Sheet》,詳細記錄了發生場景和解決指南。
5)CSP
內容安全策略(CSP,Content Security Policy)用於指定哪些內容可執行。將用戶輸入的部分標為不可執行,就不會產生實際的危害。
為使CSP可用,需要配置HTTP響應頭Content-Security-Policy,它的值可以是connect-src、default-src、script-src等。
參考資料:
