接下來關於.NET中XXE注入的內容來自Dean Fleming單元測試的Web站點:https://github.com/deanf1/dotnet-security-unit-tests。該站點覆蓋了目前.NET下支持的全部XML解析器,且測試用例均展現了哪些狀況下它們對於XXE注入而言是安全的,哪些狀況下又是不安全的。這些內容更早以前是基於James Jardine這篇關於.NET XXE的傑出文章:https://www.jardinesoftware.net/2016/05/26/xxe-and-net/。與微軟這篇在.NET下如何預防XXE以及XML拒絕服務的老文章http://msdn.microsoft.com/en-us/magazine/ee335713.aspx 相比它提供了更新更全的內容,但與Dean Fleming的Web站點覆蓋的地方相比仍是有些不許確的地方。php
下表羅列了.NET下全部支持的XML解析器其默認的安全級別:node
XML解析器 | 默認是否安全? |
---|---|
LINQ to XML | 是 |
XmlDictionaryReader | 是 |
XmlDocument | |
4.5.2以前的版本 4.5.2及以後的版本 |
否 是 |
XmlNodeReader | 是 |
XmlReader | 是 |
XmlTextReader | |
4.5.2以前的版本 4.5.2及以後的版本 |
否 是 |
XPathNavigator | |
4.5.2以前的版本 4.5.2及以後的版本 |
否 是 |
XslCompiledTransform | 是 |
System.Xml.Linq
類庫下的 XElement
和 XDocment
對於XXE注入而言默認都是安全的。XElement
僅解析XML中的元素,直接忽略了 DTDs。XDocment
默認禁止 DTDs,其僅在基於非安全的XML解析器構建時纔是不安全的。git
System.Xml.XmlDictionaryReader
默認狀況下是安全的,當它嘗試解析 DTDs 時,編譯器會拋出一個 「CData elements not valid at top level of an XML document
」 的異常,其僅在基於非安全的XML解析器構建時纔是不安全的。github
在.NET Framework 4.5.2以前的版本中,System.Xml.XmlDocument
默認是不安全的。要預防XXE,在4.5.2以前的版本中,XmlDocument
下的 XmlResolver
屬性須要手工設置爲null。而在4.5.2及其以後的版本中,XmlResolver
默認就已經被設置爲了null。下面的例子展現瞭如何進行預防:安全
static void Reader() { string xml = @"<?xml version=""1.0"" ?><!DOCTYPE doc [< !ENTITY win SYSTEM ""file:///C:/Users/user/Documents/testdata2.txt"">] >< doc > &win;</ doc >"; XmlReader myReader = XmlReader.Create(new StringReader(xml)); while (myReader.Read()) { Console.WriteLine(myReader.Value); } Console.ReadLine(); }
若是你使用非空且具備默認或不安全設置的 XmlResolver
,那麼 XmlDocument
將沒法預防XXE。若是你須要容許處理 DTD,這篇MSDN的文章詳細介紹瞭如何安全的處理 DTD。函數
System.Xml.XmlNodeReader
默認狀況下是安全的,且就算它是基於非安全的XML解析器構建,或被封裝到其它非安全的XML解析器時,它也不會處理而是忽略掉 DTDs。單元測試
System.Xml.XmlReader
默認狀況下是安全的。在4.0及以前的版本中,其ProhibitDtd
屬性被設置爲 false
,而在4.0及其以後的版本中,其DtdProcessing
屬性被設置爲 Prohibit
。另外,在4.5.2及更高版本中,XmlReader
的 XmlReaderSettings
默認將其XmlResolver
屬性設置爲了null,用於提供額外的安全措施。所以,在4.5.2及以後的版本中,必須同時將 DtdProcessing
屬性設置爲Parse
,且 XmlReaderSetting
的 XmlResolver
屬性必須賦值爲非空且具備默認或不安全設置的相關實現。若是你須要容許處理 DTD,這篇MSDN的文章詳細介紹瞭如何安全的處理 DTD。測試
在.NET Framework 4.5.2以前的版本中,System.Xml.XmlTextReader
默認是不安全的。下面是在不一樣的.NET版本中進行安全設置:ui
.NET4.0以前,在 System.Xml.XmlReaderSettings
和 System.Xml.XmlTextReader
類中,像 XmlTextReader
這類 XmlReader
的DTD解析行爲是由Boolean類型的 ProhibitDtd
屬性來控制的,將該值設置爲 true
將能夠徹底禁止內聯DTDs。spa
XmlTextReader reader = new XmlTextReader(stream); reader.ProhibitDtd = true; // NEEDED because the default is FALSE!!
.NET4.0版本中DTD的解析行爲發生了變化。已再也不推薦經過 ProhibitDtd
屬性進行安全控制,取而代之的是 DtdProcessing
屬性。然而他們並無改變其默認設置,因此在默認狀況下,XmlTextReader
對於XXE而言仍然是易受攻擊的。將 DtdProcessing
設置爲Prohibit
後,若是XML包含 <!DOCTYPE>
元素將會在程序運行時拋出一個異常。你能夠這樣設置這個值:
XmlTextReader reader = new XmlTextReader(stream); reader.DtdProcessing = DtdProcessing.Prohibit; // NEEDED because the default is Parse!!
或者你能夠將 DtdProcessing
設置爲 Ignore
,這樣就算有<!DOCTYPE>
程序也不會拋出異常,而是簡單的跳過且不處理它。最後,你能夠將 DtdProcessing
屬性設置爲 Parse
來容許處理內聯DTDs。
.NET4.5.2及其以後的版本中,XmlTextReader
的 XmlResolver
屬性(可訪問性爲internal
)默認被設置爲null,這樣默認XmlTextReader
將會忽略DTDs。當使用非空且具備默認或不安全設置的 XmlResolver
時,XmlTextReader
將會變得不安全。
在4.5.2版本以前,System.Xml.XPath.XPathNavigator
默認是不安全的。這是由於它像 XmlDocument
那樣實現了 IXPathNavigable
接口,這個接口在4.5.2以前的版本中默認也是不安全的。你能夠經過傳遞安全的Xml解析器(好比 XmlReader
,它默認是安全的)到XPathNavigator
的構造函數中來獲取安全的 XPathNavigator
實例,如下是例子:
XmlReader reader = XmlReader.Create("example.xml"); XPathDocument doc = new XPathDocument(reader); XPathNavigator nav = doc.CreateNavigator(); string xml = nav.InnerXml.ToString();
只要給定的Xml解析器是安全的,那麼 System.Xml.Xsl.XslCompiledTransform
(Xml轉換器)默認就是安全的。它之因此安全是由於Transform()
方法默認的解析器是 XmlReader
,這個解析器默認是安全的(前面有描述)。你能夠在此處查看它的源代碼。有些Transform()
的重構方法接受像 XmlReader
、IXPathNavigable
(好比 XmlDocument
)之類的參數,若是你傳遞的是不安全的Xml解析器,那麼 Transform
方法也將不安全。
英文地址:https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#.NET