在.NET下如何預防XXE注入攻擊

接下來關於.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

LINQ to XML

System.Xml.Linq 類庫下的 XElement和 XDocment 對於XXE注入而言默認都是安全的。XElement 僅解析XML中的元素,直接忽略了 DTDs。XDocment 默認禁止 DTDs,其僅在基於非安全的XML解析器構建時纔是不安全的。git

XmlDictionaryReader

System.Xml.XmlDictionaryReader 默認狀況下是安全的,當它嘗試解析 DTDs 時,編譯器會拋出一個 「CData elements not valid at top level of an XML document」 的異常,其僅在基於非安全的XML解析器構建時纔是不安全的。github

XmlDocment

在.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(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

若是你使用非空且具備默認或不安全設置的 XmlResolver,那麼 XmlDocument 將沒法預防XXE。若是你須要容許處理 DTD,這篇MSDN的文章詳細介紹瞭如何安全的處理 DTD。函數

XmlNodeReader

System.Xml.XmlNodeReader 默認狀況下是安全的,且就算它是基於非安全的XML解析器構建,或被封裝到其它非安全的XML解析器時,它也不會處理而是忽略掉 DTDs。單元測試

XmlReader

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。測試

XmlTextReader

在.NET Framework 4.5.2以前的版本中,System.Xml.XmlTextReader 默認是不安全的。下面是在不一樣的.NET版本中進行安全設置:ui

4.0以前的版本

.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!!
  • 1
  • 2

.NET 4.0 - .NET 4.5.2

.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!!
  • 1
  • 2

或者你能夠將 DtdProcessing 設置爲 Ignore,這樣就算有<!DOCTYPE>程序也不會拋出異常,而是簡單的跳過且不處理它。最後,你能夠將 DtdProcessing 屬性設置爲 Parse 來容許處理內聯DTDs。

.NET 4.5.2及以後的版本

.NET4.5.2及其以後的版本中,XmlTextReader 的 XmlResolver 屬性(可訪問性爲internal)默認被設置爲null,這樣默認XmlTextReader 將會忽略DTDs。當使用非空且具備默認或不安全設置的 XmlResolver 時,XmlTextReader 將會變得不安全。

XPathNavigator

在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();
  • 1
  • 2
  • 3
  • 4

XslCompiledTransform

只要給定的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

相關文章
相關標籤/搜索