繞過WAF保護的XXE
前言
XXE或XML外部實體是2017年OWASP Top 10漏洞列表中的新問題。這是基於來自安全問題資料庫的直接資料證據而引入的唯一一個新問題。XML通常用於從movies到Docker容器的所有內容的元資料,並且是API協議(如REST、WSDL、SOAP、Web-RPC和其他協議)的基礎,而且,一個應用程式可能包含多個連結的XML直譯器,這些直譯器處理來自不同應用程式層的資料。這種通過XML直譯器在應用程式堆疊中的不同位置注入外部實體的潛在隱患使XXE變得很危險。
許多Web應用程式防火牆能夠保護Web伺服器免受XXE攻擊。
在Wallarm CEO, Ivan Novikov的文章 Security Boulevard 中這樣寫道:
實際上,XXE不是一個bug,而是XML解析器的well-documented特性。XML資料格式允許您在XML文件中包含任何外部文字檔案的內容。
包含攻擊程式碼的XML文件示例:

這裡的文字 $attack;
指的是前面註冊的實體的連結。連結中指定的檔案內容將其替換為文件正文中的內容。
上述文件分為三個重要部分:
1.可選標頭, <?xml?>
用於定義基本文件特徵,例如版本和編碼。
2.XML文件模式的可選宣告—— <!DOCTYPE>
。此宣告可用於設定外部連結。
<! DOCTYPE>
正確配置的XML直譯器要麼不接受包含XML連結的文件進行處理,要麼將驗證連結及其來源,如果缺少驗證,則可以通過連結載入任意檔案並將其整合到文件體中,如上面的示例所示。
在本文中,我們將根據WAF處理XML驗證的方式來研究兩種型別的WAF:
1.成熟的waf——使用自己的解析器預處理XML文件的WAFs。
2.基於正則表示式。僅搜尋資料中的特定子字串或正則表示式的WAFS。
不幸的是,這兩種型別的WAF都可以繞過。
下面我們展示了攻擊者可以用來騙過WAF並獲得XXE的幾種方法。
方法1:文件中的額外空格
由於XXE通常在XML文件的開頭,所以比較省事兒的WAF可以避免處理整個文件,而只解析它的開頭。但是,XML格式允許在格式化標記屬性時使用任意數量的空格,因此攻擊者可以在 <?xml?>
或 <!DOCTYPE>
中插入額外的空格,從而繞過此類WAF。
方法2:格式無效
為了繞過WAF,攻擊者可能會發送特殊格式的XML文件,以便WAF認為它們無效。
連結到未知實體
比較成熟的WAF設定通常不會讀取連結檔案的內容。這種策略通常是有意義的,否則,WAF本身也可能成為攻擊的目標。問題是,外部資源的連結不僅可以存在於文件的第三部分(正文),還可以存在於宣告<! DOCTYPE>中 。
這意味著未讀取檔案內容的WAF將不會讀取文件中實體的宣告。而指向未知實體的連結又會阻止XML解析器導致錯誤。
幸運的是,防止這樣的繞過非常簡單——命令WAF中的XML解析器在遇到未知實體後不要關閉。
方法三:外來編碼(Exotic encodings)
除了前面提到的xml文件的三個部分之外,還有位於它們之上的第四個部分,它們控制文件的編碼(例如<?xml?>)——文件的第一個位元組帶有可選的BOM(位元組順序標記)。
更多資訊: https://www.w3.org/TR/xml/#sec-guessing
一個xml文件不僅可以用UTF-8編碼,也可以用UTF-16(兩個變體 - BE和LE)、UTF-32(四個變體 - BE、LE、2143、3412)和EBCDIC編碼。
在這種編碼的幫助下,使用正則表示式可以很容易地繞過WAF,因為在這種型別的WAF中,正則表示式通常僅配置為單字符集。
外來編碼也可用於繞過成熟的WAF,因為它們並不總是能夠處理上面列出的所有編碼。例如,libxml2解析器只支援一種型別的utf-32 - utf-32BE,特別是不支援BOM。
方法4:在一個文件中使用兩種型別的編碼
在上一節中,我們演示了文件的編碼通常由其第一個位元組指定。但是當包含編碼屬性的<?xml?>標記引用文件開頭的不同字符集時會發生什麼?在這種情況下,一些解析器更改編碼,使檔案的開頭有一組字元,其餘的是另一組編碼。。也就是說,不同的解析器可能在不同的時間轉換編碼。Java解析器(javax.xml.parsers)在<?xml?>結束後嚴格地更改字符集,而libxml2解析器可以在執行“編碼”屬性的值之後或在處理<?xml?>之前或之後切換編碼。
只有在根本不處理這些檔案時,比較成熟的WAF才能可靠地防止這些檔案中的攻擊。我們還必須記住,有許多同義詞編碼,例如UTF-32BE和UCS-4BE。此外,有些編碼可能不同,但從編碼文件初始部分 <?xml?>
的角度來看,它們是相容的。例如,看似UTF-8的文件可能包含字串 <?xml version=”1.0” encoding=”windows-1251”?>
。
這裡有一些例子。為了簡明扼要,我們不把XXE放在文件裡。
libxml2解析器將文件視為有效,但是,javax.xml.parsers set中的Java引擎認為它無效:
反之亦然,文件對於javax.xml.parser是有效的,但對於libxml2解析器是無效的:
libxml2的文件,在標記中間將編碼從utf-16le更改為utf-16be:
libxml2的文件,編碼從utf-8改為ebcdic-us:

正如你所看到的,有許多繞過方法。防止XXE的最好方法是配置應用程式本身,以安全的方式初始化XML解析器。為此,應該禁用兩個選項:
外部實體
外部DTD架構
我們將繼續我們的研究XXE WAF繞過。敬請關注。
翻譯:https://lab.wallarm.com/xxe-that-can-bypass-waf-protection-98f679452ce0