這裏分兩個方向來說XSS的防禦方法,PART I 是從具體的原理機制上講,PART II 是從業務形式上說;另外,因爲DOM-Based XSS比較特殊,所以另外分成一個PART III 寫對它的防禦。
PART I
- 輸入過濾
- 輸出過濾(編碼-encode)
- 黑名單
- HttpOnly Cookie
1、輸入過濾
在客戶端和服務器端都要進行過濾
1、輸入驗證
- 字符合法
- 字符串長度限制
- 數字範圍
- 字符串格式,如email,tel等
2、數據消毒
過濾和淨化有害輸入,如一些敏感字符< > " ' & javascript
等。
2、輸出過濾(編碼-encode)
對頁面輸出進行編碼,轉義等過濾操作。
X、黑白名單
這個其實就是輸入過濾和輸出過濾的實現機制。顧名思義,沒什麼好說的。我不知道該怎麼去分類了,這裏就讓它在這裏吧。知道這個概念就好。
4、HttpOnly Cookie
這個方法是專門針對竊取cookie而設計的。被加上HttpOnly標誌的cookie會禁止javascript訪問該cookie。
PART II
- 定製過濾策略
- Web安全編碼規範
- 使用防XSS類庫,如Anti_XSS
- 使用WAF
PART III(DOM-Based)
DOM-Based XSS概念
DOM型XSS由客戶端腳本通過DOM動態地輸出數據到頁面中,它不依賴於提交數據到服務器,而是從客戶端獲得DOM中的數據在本地執行。
其實對這段話(DOM型XSS的概念)的理解,網上基本上沒有人說得讓我明白(是我理解不行?),最終竟然在一篇文章上領悟了一下。 [DOM Based Cross Site Scripting or XSS of the Third Kind]http://www.webappsec.org/projects/articles/071105.shtml。(其實還是要結合看過的雖然沒能讓我一下明白的所有的資料來才能開竅的——一個知識積累的過程)。
我就把我的理解,用大白話在這裏寫一遍。
首先,DOM會被解析,寫入HTML。
概念上所謂的“不依賴於提交數據到服務器,而是從客戶端獲得DOM中的數據在本地執行”中,“不依賴於提交數據到服務器”,其實這樣說很誤導人吧,後邊再說明一下。
先說說“從客戶端獲得DOM中的數據”,這個其實就是說,在HTML中,使用DOM語言,獲取一些本地數據,這個數據可以是瀏覽器上的東西,也可以是本地主機上的東西等,比如URL、location、globalStorage等。這一步完全不涉及遠程機器對吧。
攻擊的時候,攻擊者通過URL構造參數傳遞XSS腳本,使得被攻擊方使用DOM將攻擊腳本寫到它的HTML裏(DOM會被解析,寫入HTML),並執行。
e.g.
假設被攻擊方 www.abc*.com/ttt.html
頁面有 document.URL
的操作語句,這個東西存儲着當前頁面的URL,比如你輸入參數user=alim,那麼 document.URL
就等於 www.abc*.com/ttt.html?user=alim
, 或者輸入hong,那麼變成 www.abc*.com/ttt.html?user=hong
,它始終是會隨着參數變化的,總之就是一個 完整的指向當前頁面的 URL。
===>
這樣,當攻擊方將user參數構造爲一個腳本 <script>alert(111)</script>
===>
這段腳本也會被存在被攻擊方的 document.URL
中,而因爲被攻擊方在文檔中執行了 document.URL
操作(具體這裏不考慮了,就這麼帶過),那麼這個腳本也就 假借了URL的名義 被寫入HTML中,而HTML裏的腳本是要被執行的。攻擊成功。
你看攻擊者不是也要輸入內容到服務器嗎?這就對了,概念上說的是不依賴於輸入數據。。。我們上邊輸入的本質上不能叫數據,聯想一下其它兩種XSS方式就可以想清楚這之間的區別。我們這裏的注入只是將它作爲document.URL 的“文本”,而反射型和存儲型XSS中,我們直接將輸入作爲了HTML的數據。
用這樣深的詞彙,真的是隻會誤導人啊。。。
DOM-Based XSS防禦
1、根據上邊的原理,那麼可以分析和強化客戶端javascript代碼。具體可能受到影響的DOM對象有:
從URL獲取的:
- document.URL
- document.URLUnencoded
- document.location
- window.location
Referrer屬性:
- document.referrer
Windowname屬性:
- window.name
本地存儲對象:
- document.cookie
- HTML5 postMessage
- localStorage/globalStorage
- XMLHTTPRequest response
- Input.value