html中alert的用法_【渗透实战】通过HTML命名空间混淆绕过DOMPurify实现XSS
我們首先了解下DOMPurify通常是如何使用的。假設我們需要將html Markup中一個不受信任的HTML賦值給某個div,我們可以通過以下代碼使用DOMPurify對該內容進行過濾,在賦值給div:
div.innerHTML = DOMPurify.sanitize(htmlMarkup)在解析、系列化以及處理DOM樹的過程中,上訴代碼實際上會執行以下操作:
htmlMarkup被解析為DOM樹
DOMPurify過濾DOM樹(簡而言之,這個過程中DOMPurify會遍歷DOM樹中的所有元素以及屬性,并刪除不在允許列表中的所有節點)
DOM樹被序列化回HTML標記
賦值給innerHTML之后,瀏覽器將再次解析HTML標記
解析的DOM樹被附加到文檔的DOM樹中
這就是DOMPurify.sanitize返回的結果。然后瀏覽器在賦值給innerHTML時會再次解析該標記。
DOM樹與DOMPurify處理過的樹相同,然后將其附加到目標文檔中。
簡而言之,按順序,以上過程可以總結成:解析->序列化->解析。直觀上,大家可能會覺得系列化DOM樹,并再次解析后,應該會返回初始的DOM樹,但事實并非如此。
HTML規范中,關于系列化HTML片段的警告信息表明:如果使用HTML解析器進行解析,則此算法[序列化HTML]的輸出可能不會返回初始的樹結構。HTML解析器本身也有可能輸出不往返序列化和重新解析步驟的樹結構,盡管這種情況通常不符合要求。
值得注意的是,序列號-重新解析的往返操作并不一定能返回初始的DOM樹,這也是造成mutation XSS(突變XSS) 的根本原因。通常這類情況是由于某些解析器、序列化器錯誤所導致的結果,但有兩種特殊情況符合上訴警告信息所描述的場景。
3嵌套FORM元素其中一種情況涉及FORM元素,它是HTML里非常特殊的一個元素,因為它本身不能嵌套。HTML規范中,明確指出FORM元素不可以是某個FORM元素的后繼。
可以在任何瀏覽器中使用以下標記進行驗證:
<form id=form1>INSIDE_FORM1<form id=form2>INSIDE_FORM2該片段會生成以下DOM樹:
第2個form在DOM樹中會被完全忽略,就像從未存在過一樣。
接下來是比較有趣的部分。如果我們繼續閱讀HTML規范,會發現它實際上給出了一個示例,該示例通過帶有錯誤嵌套標簽的標記成功創建了一個嵌套式表單。如下所示:
<form id="outer"><div>form><form id="inner"><input>結果會生成以下包含一個嵌套表單元素的DOM樹:
這并不是特定瀏覽器的bug,它直接來自HTML規范,并且在解析HTML的算法中也有描述。大意如下所示:
當我們打開標簽時,解析器需要記錄該標簽是由表單元素指針打開的。如果指針不為空,則無法創建表單元素。
當我們結束標簽時,表單元素指針始終設置為null。
因此,回到以下片段:
<form id="outer"><div>form><form id="inner"><input>首先,表單元素指針設置為id =“outer”,然后開始解析div,碰到閉合標簽后,表單元素指針會被設置為null。由于指針為null,因此可以創建下一個id=“ inner”的表單。并且由于我們當前位于div內,因此可以成功創建一個嵌套式表單。
現在,如果我們嘗試序列化生成的DOM樹,將獲得以下標記:
<form id="outer"><div><form id="inner"><input>form>div>form>值得注意的是,該標記將不包含任何錯誤嵌套的標簽。當再次解析標記時,將創建以下DOM樹:
綜上,我們證明了經過序列化、重解析后并不一定能返回原始的DOM樹。更有趣的是,這基本上是一種符合規范的突變。
當我發現這一點后,便意識到可以通過某種方式濫用這種特性以繞過HTML過濾器。思考了很久后,偶然間發現HTML規范中的另一個異常點。在繼續討論該問題前,我們先來了解下HTML規范中的潘多拉魔盒:外部內容(foreign content)。
4外部內容外部內容就好比一把瑞士軍刀,可以用來破壞解析器及過濾器。該方法曾被我用來繞過DOMPurify以及Ruby過濾庫。
HTML解析器可以使用三個命名空間元素創建DOM樹:?
HTML命名空間(http://www.w3.org/1999/xhtml)?
SVG命名空間(http://www.w3.org/2000/svg)?
MathML命名空間(http://www.w3.org/1998/Math/MathML)?
默認情況下,所有元素都位于HTML命名空間中。但是,如果解析器遇到或元素,則它將分別“切換”到SVG和MathML命名空間。這兩個命名空間都會產生外部內容。
在外部內容中,標記的解析過程與普通的HTML不同。尤其是在解析
思考以下標記:
它將被解析成以下DOM樹:
備注:從現在開始,本文DOM樹中的所有元素都將包含一個命名空間。因此html style意味著它是HTML命名空間中的
最終的DOM樹證實我的觀點:html style僅包含文本內容,而svg style會像普通元素一樣被解析。?
繼續分析,我們可能會猜想:如果我們位于或內部,則所有元素也都會位于非HTML命名空間中。但事實并非如此,HTML規范中包含MathML文本集成點和HTML集成點,這些元素的子元素都具有HTML命名空間(但某些情況除外)。?
思考以下示例:
它將被解析成以下DOM樹
請注意觀察,在MathML命名空間中,style元素是如何成為math的直接子元素的,而mtext中的style元素則位于HTML命名空間中。這是因為mtext是MathML文本集成點,并使用解析器切換命名空間。
MathML文本集成點包括:
math mi
math mo
math mn
math ms
HTML集成點包括:
math annotation-xml(如果其具有encoding屬性,并且屬性值等于text/html或者application/xhtml+xml)
svg foreignObject
svg desc
svg title
我之前一直以為MathML文本集成點或HTML集成點的所有子級,默認情況下都具有HTML命名空間,但事實并非如此。HTML規范指出,默認情況下,MathML文本集成點的子級都位于HTML命名空間中。但有兩種例外情況:mglyph和malignmark。只有當它們是MathML文本集成點的直接子級時,才會發生這種情況。
我們可以通過以下標記進行檢查:
注意,作為mtext的直接子元素的mglyph在MathML命名空間中,而作為html元素的子元素的mglyph在HTML命名空間中。
假設我們想確定一個“當前元素”的命名空間。此時我已經制定了一些經驗法則:
除非滿足以下條件,否則當前元素將位于其父元素的命名空間中。
如果當前元素為或,且其父元素在HTML命名空間中,則當前元素分別位于SVG或MathML命名空間中。?
如果當前元素的父元素是HTML集成點,則當前元素位于HTML命名空間中,除非它是或。?
如果當前元素的父元素是MathML集成點,則當前元素位于HTML命名空間中,除非它是,,或。
如果當前元素是,,
,,
,,,,,,, ,,,
,
,
,
,
,,,,,
- ,,,,,,
,
,,,,或,并定義了color,face或size屬性,那么堆棧上的所有元素將關閉,直到看到MathML文本集成點、HTML集成點或HTML命名空間中的元素為止。然后,當前元素也會位于HTML命名空間中。
5
DOMPurify繞過
DOMPurify的典型使用方法致使HTML標記被解析兩次。
HTML規范中存在特殊情況,可以創建嵌套form元素。但是,在重新解析時,第二個form會被忽略。
mglyph和malignmark是HTML規范中的特殊元素,即使默認情況下其他所有標簽都位于HTML命名空間中,但如果它們是MathML文本集成點的直接子元素,那么它們也將位于MathML命名空間中。
結合以上幾點,我們可以創建一個具有兩個form元素和mglyph元素的標記,這些標記最初位于HTML命名空間中,但是在重新解析時位于MathML命名空間中,從而使后續的style標簽的解析方式有所不同,導致XSS。
end
總結
以上是生活随笔為你收集整理的html中alert的用法_【渗透实战】通过HTML命名空间混淆绕过DOMPurify实现XSS的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: it项目经理带一个项目的完整_如何控制I
- 下一篇: 内置host_浏览器内置对象应用实践