繞過XSS filters的幾種方法

YasHigginbo 8年前發布 | 29K 次閱讀 XSS漏洞 JavaScript開發 JavaScript

XSS跨站腳本攻擊是指,黑客向一個頁面中注入Javascript腳本,其它的用戶訪問該頁面時會執行這個腳本。為了防止這一攻擊,一些軟件嘗試從輸入中移除Javascript代碼。這很難正確實現。在這篇文章中我會展示一些試圖移除輸入里的Javascript腳本的代碼,并演示幾中繞過它的方法。

以網上商城軟件 Magento 中的類 Mage_Core_Model_Input_Filter_MaliciousCode 為例。這個類的作用是過濾“惡意代碼”,包括以任何形式插入的Javascript。

代碼如下所示:

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變量包含一個正則表達式列表,preg_replace函數會移除文本中匹配該正則表達式的內容。所以如果你輸入<script>foo</script>,兩個標簽都會被移除,只保留foo。

讓我們看一些繞過這個filter的方法。我們的目標是繞過它傳遞一些執行Javascript的HTML代碼。這個filter有若干表達式,它們的含義是阻止下面的內容:

Javascript URL

可以在URL中使用javascript:…讓該鏈接執行javascript:

<a href="javascript:alert('test')">link</a>

filter移除了代碼中的javascript:,所以我們不能直接用上面的代碼。我們可以試著改變javascript:部分,讓瀏覽器任然執行它并且正則表達式匹配不上。我們試試URL-encode:

<a href="javascript:alert('xss')">link</a>

正則表達式匹配不上了,但瀏覽器在用它之前對該鏈接做了URL-decode操作,所以依然可以執行它。

除了Javascript之外還有VBScript。它在IE11中被棄用并且禁用了,但是在Internet Explorer的老版本中依然可以使用,如果你把IE 11設置為IE 10模擬模式的話也是可用的。我們可以像Javascript鏈接那樣執行相同的代碼。

<a href='vbscript:MsgBox("XSS")'>link</a>

CSS導入

Internet Explorer在CSS中支持Javascript表達式,稱為動態屬性 https://msdn.microsoft.com/en-us/library/ms537634 (v=vs.85).aspx。允許攻擊者加載外部的CSS樣式表是非常危險的,因為攻擊者可以在原始頁面的上下文中執行Javascript。

在惡意的css中:

body {
    color: expression(alert('XSS'));
}

我們可以在CSS中使用反斜杠轉義字符來規避@import過濾。

Internet Explorer允許反斜杠,現在它繞過了我們的filter。

Inline樣式

我們也可以使用Inernet Explorer支持的內嵌樣式中的動態屬性:

<div style="color: expression(alert('XSS'))">

filter會檢查這樣的字符串,style后面跟的不是<并且后面包含expression:

/style=[^<]*((expression\s*?\([^<]*?\))|(behavior\s*:))[^<]*(?=\>)/Uis

因此,我們在那里增加一個<.

<div style="color: '<'; color: expression(alert('XSS'))">

這可以繞過filter,因為[^<]匹配不上<,并且這還是一個有效的CSS,雖然“<”不是一個有效的color,但是其余部分仍然被使用了。

Javascript事件

可以在一個元素上定義事件句柄,如下:

<div onclick="alert('xss')">

這樣,這個Javascript會在有人點擊它的時候執行,但是也有一些事件是在頁面加載后或者用戶移動鼠標的時候觸發。filter移除了許多這樣的事件,但是它并沒有包含所有的事件句柄。比如,漏了onmouseenter:

<div onmouseenter="alert('xss')">

我們的代碼會在用戶把鼠標移動到div上面時執行。

另一個繞過的方法是在屬性和”=”之間加上一個空格。Magento在最新版本的惡意代碼filter中已經修復了它。

<div onclick ="alert('xss')">

Script標簽

Script標簽可以用來定義行內腳本,或者從其它位置加載腳本文件:

我們的filter移除了<script>標簽。然而,它只是做一次,因此我們可以讓我們想要的內容在移除標簽之后出現:

<scr<script>ipt>alert("XSS")</scr<script>ipt>

filter移除了兩個發現的<script>,最后我們還是執行了想要的代碼。實際上,這個嵌套標簽的辦法可以用來規避任意的filter表達式。

結論

盡管filter試圖阻止了幾種腳本注入的辦法,我們都找到了規避的方法。創建一個filter來規避XSS攻擊是不容易的。你必須考慮各種編碼類型以及不同的瀏覽器行為。這讓開發者做起來很難,卻方便了攻擊者。

安全影響

我展示了幾種繞過filter的辦法。這是一個安全威脅,除非沒有對不可信輸入使用這個filter。在 Magento 2.0.1 release notes 中有這樣一段話:

用戶在輸入HTML代碼的時候可以輕易繞過MaliciousCode filter函數。但是,Magento幾乎不用這個filter,并且當前的用法都不允許未授權用戶輸入。

1月23日,我進一步聯系了Magento,他們不認為這是一個安全問題,所以我發布了這篇文章。

*本文譯者:felix,翻譯自: http://www.sjoerdlangkemper.nl/2016/01/29/circumventing-xss-filters/ 

 

來自: http://www.freebuf.com/articles/web/104656.html

 

 本文由用戶 YasHigginbo 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!