普通的 XSS,是經過服務端(好比模板技術)將數據輸出到 HTML 中。而 DOM Based 類型 的 XSS,是經過 JS 將數據輸出到 HTML 中。javascript
請看下例:java
<script type="text/javascript">
var x='<來源於 input 輸入框>';
document.write("<a href='"+x+"'>demo</a>")
</script>
複製代碼
這裏的 x 變量,其值來源於用戶所輸入的內容。網站開發者使用普通 XSS 的防護方法(DefaultEncoder.getInstance().encodeForJavaScript(str)
)對該變量進行編碼,以免 XSS 攻擊。bash
假設,攻擊者使用 'onclick=alert('dom_based_xss');//'
做爲輸入內容,那麼通過 encodeForJavaScript 編碼,變量 x 變爲這樣:cookie
<script type="text/javascript">
var x='\x27onclick\x3Dalert\x28\x27dom_based_xss\x27\x29\x3B\x2F\x2F\x27';
document.write("<a href='"+x+"'>demo</a>")
</script>
複製代碼
攻擊結果:dom
難道 ESAPI 也防護不了基於 DOM Based 類型的 XSS 攻擊了嗎?咱們來分析分析。xss
這是由於 encodeForJavaScript 只能保護 JS。而編碼過的惡意腳本,經過 document.write()
方法輸出到 HTML 頁面時,又會被解碼還原回去,從而致使 XSS 攻擊成功。網站
那是否對上述場景應用 HtmlEncode 就解決問題了呢?請看下面這一段代碼:ui
var y=xxx'; document.write("<a href=# onclick='alert(\""+y+"\")'>demo2</a>");
複製代碼
假設攻擊者編寫的攻擊字符串是這樣的:正常邏輯");alert('dom_based_xss');///
,通過 HtmlEncode 編碼爲:正常逻辑");alert('dom_based_xss');///
編碼
攻擊結果: spa
第一次仍然會執行正常邏輯,第二次就被 XSS 注入攻擊咯。因此單純使用 HtmlEncode 編碼,仍然防不住被攻擊。
終極防護方法爲:輸出到 <script>
時,先使用 encodeForJavaScript 對其編碼。而後在 doucment.write() 方法中作判斷,若是是輸出到 HTML 頁面,則再使用 encodeForHTML 二次編碼;若是是輸出到 JavaScript,則使用 encodeForJavaScript 二次編碼。這樣,才能確保萬無一失。
可能發生 DOM Based 類型的 XSS 攻擊,有如下這些方法:
如下這些地方有可能成爲 DOM Based 類型的 XSS 攻擊字符串的注入點,也須要注意防範: