什么是 XML 外部實體?

XML,即可擴展標記語言,是一種用于存儲、傳輸和重建任意數據的標記語言和文件格式。這種語言在編程領域用于定義以人可讀和機器可讀的格式對文檔進行編碼的規則。這種文件結構如何容易受到攻擊?為什么它會對您的系統構成威脅?默認情況下,大多數 XML 處理工具允許指定外部實體(URI),該實體在解析 XML 文件期間被檢索和處理。發生這種情況時,解析器可以請求并包含 XML 文檔中指定 URI 處的內容。?

此漏洞使系統面臨被利用的風險。例如,惡意攻擊者可以利用此屬性作為獲取服務器上任何資源的途徑。 

XXE(XML 外部實體)注入是一種利用 XML 解析漏洞的攻擊。它針對使用面向用戶的 XML 解析功能的系統,允許攻擊者訪問服務器上的文件和資源。攻擊可能包括泄露包含敏感數據(例如密碼或私人用戶數據)的本地文件,以及在系統標識符中使用文件:方案或相對路徑。 

顯然,一個堅定的攻擊者可能會接管您的服務器,特別是在對服務器結構和您正在使用的技術堆棧的一些信息有充分的了解的情況下。

XML 外部實體示例

現在我們已經解釋了 XML 外部實體攻擊背后的概念,讓我們來看一些例子。 

這是一個包含用戶名 XML 元素的示例 XML 文檔。 

<?xml version="1.0" encoding="ISO-8859-1"?>
<username>John</username>
</xml>

相當無害且簡單。現在,如何向 XML 添加外部實體?嗯,這很簡單。  

可以使用 DOCTYPE 標頭內的系統標識符添加外部 XML 實體。此指令基本上會向 XML 文件結構添加一些屬性。例如,下面的代碼包含一個外部 XML 實體,它將獲取 /secrets.yml 的內容并將其顯示給按用戶名呈現的用戶。

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///secrets.yml" >]>
<username>&xxe;</username>
</xml>

如您所見,這些實體可以訪問服務器中的本地或遠程內容。如果您保存的敏感文件可以為攻擊者提供將整個平臺的控制權交給攻擊者的途徑,那么這將是一個壞消息。其他 XML 外部實體攻擊可以訪問可能不會停止返回數據的本地資源,可能影響應用程序可用性并導致拒絕服務 (DoS) 攻擊。 

如果你留意了,這時你就應該拉響警報并致電你的安全專家。 

這只是對 XML 外部實體主題的簡要說明。它絕不涵蓋所有復雜性和錯綜復雜之處。要保護您的平臺免受網絡上最復雜的攻擊,需要對該技術有廣泛的了解,并牢牢掌握平臺的基礎架構。 

好嗎?繼續。

防止 XML 外部實體攻擊

好吧,那么您如何才能防止您的系統受到這些惡意攻擊,并在此過程中不丟掉工作呢? 

別擔心。緩解 XML 外部實體攻擊非常簡單。通常,只要您不是故意嘗試打開漏洞窗口,并且考慮到您需要加載用戶提供的 XML 文件的功能,Rails 就能很好地保護您。 

讓我們舉例說明。 

正如我們之前提到的,如果應用程序有一個解析 XML 文件的端點,攻擊者就可以向服務器發送特制的有效負載并獲取敏感文件。攻擊者可以訪問的文件取決于您如何設置系統以及如何實施用戶權限。 

因此,為了防止這種情況發生,首先,不要使用支持實體替換的庫(如 LibXML)。相反,請使用 Rails REXML 中包含的內置默認庫。 

現在,如果您已經在使用此庫并且無法更改它,或者關鍵庫需要此庫,請確保禁用實體替換。  

您只需在初始化文件中添加以下代碼即可完成此操作:

require 'xml'
require 'libxml'

# Change the ActiveSupport XML backend from REXML to LibXML
ActiveSupport::XmlMini.backend = 'LibXML'

# Deny entity replacement in LibXML parsing
LibXML::XML.class_eval do
def self.default_substitute_entities
XML.default_substitute_entities = false
end
end

值得慶幸的是,新版本的 LibXML 使得啟用實體替換變得困難。但是,必須記住的是,如果您決定采用這種方式,您在使用 LibXML 時仍然可能容易受到 DoS 攻擊。 

現在,假設您的應用程序實際上利用外部實體來實現某些關鍵功能。在這種情況下,您可以采取的一種方法來最大限度地降低漏洞利用的可能性,就是將已知的外部實體列入安全名單。 

您只需在使用庫解析 XML 文件文檔之前檢查其中是否有包含列表中沒有的“ENTITY”的字符串即可。

require 'nokogiri'
require 'active_record'

ActiveRecord::Base.establish_connection(
adapter: 'mysql2', # or 'postgresql' or 'sqlite3' or 'oracle_enhanced'
host: 'localhost',
database: 'your_database',
username: 'your_username',
password: 'your_password'
)

class Job < ActiveRecord::Base
end

class ExampleData
attr_reader :file

def initialize(file)
@file = file
end

def xml
raise StandardError.new "POTENTIAL ATTACK" if "<!ENTITY".in? file

Nokogiri::XML(open(file))
end

def create_jobs
xml.css('request').each do |node|
Job.create(
:last_name => node['name'],
:telephone => node['phone'],
:street_address => node['address'],
:city => node['city'],
:state => node['state'],
:zip => node['zip'],
:email => node['email'],
:au_chog => node['chogAu'],
:person_type => node['affil'],
:research_use => node['use'],
:subject => node['subject'],
:notes => node['note'],
:start_date => node['startDate'],
:end_date => node['addDate'],
:complete => true,
:time_spend => node['hours']
)
end
end

file = File.dirname(__FILE__) + "/data/old_data.xml"
example_data = ExampleData.new(file)
example_data.create_jobs
end

核選項

最后——我想強調的是——如果應用程序不需要解析 XML,請不要解析。我知道解析 XML 可能會很方便,并允許平臺為用戶提供便捷的功能。不過,有很多方法可以在不使用這些庫的情況下提供類似的功能。最后,最好的緩解策略是不要以任何方式受到攻擊。 

如今,為用戶提供強大而安全的平臺和服務非常復雜。它需要大量的工作和專業知識。對于專注于高效提供快速而富有創意的解決方案的團隊來說,這可能是一項艱巨的任務。 

展望

目前,大多數開發工具包、軟件包和庫都非常強大。它們具有多層保護,可抵御 XXE 等各種漏洞。但是,總是有可能無意中引入漏洞,危及您的工作和公司。因此,保持最新狀態并依靠出色的 Rails 社區來擴展您的選擇至關重要。  

Rails 是一個易于使用且友好的平臺,可用于構建強大而靈活的應用程序。它使防范 XXE 注入漏洞的工作變得簡單直接。無需擺弄復雜的配置或危險的設置。 

文章來源:NodeJS XML External Entities Guide: Examples and Prevention

上一篇:

React XML外部實體指南:示例及預防

下一篇:

開源手冊:為開發者提供的初學者手冊
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費