2013-01-09 221 views
20

我們對我們的代碼進行了安全審計,他們提到我們的代碼易受外部實體(XXE)攻擊。我使用下面的代碼 -如何防止XXE攻擊(.net中的XmlDocument)

string OurOutputXMLString= 
"<ce><input><transaction><length>00000</length><tran_type>Login</tran_type></transaction><user><user_id>ce_userid</user_id><subscriber_name>ce_subscribername</subscriber_name><subscriber_id>ce_subscriberid</subscriber_id><group_id>ce_groupid</group_id><permissions></permissions></user><consumer><login_details><username>UnitTester9</username><password>pDhE5AsKBHw85Sqgg6qdKQ==</password><pin>tOlkiae9epM=</pin></login_details></consumer></input></ce>" 

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml(OurOutputXMLString); 

在審計報告中,他們說,它的失敗,因爲XML實體可以包含可以解決預期contronl之外的URL。 XML實體解析器將嘗試解析和檢索外部引用。如果攻擊者控制的XML可以提交給其中一個功能,那麼攻擊者可以訪問關於內部網絡,本地文件系統或其他敏感數據的信息。 爲了避免這種情況,我寫了下面的代碼,但它不起作用。

MemoryStream stream = 
    new MemoryStream(System.Text.Encoding.Default.GetBytes(OurOutputXMLString)); 

XmlReaderSettings settings = new XmlReaderSettings(); 

settings.DtdProcessing = DtdProcessing.Prohibit; 
settings.MaxCharactersFromEntities = 6000; 
XmlReader reader = XmlReader.Create(stream, settings); 
XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.Load(reader); 

但我可以在這裏看到,讀者沒有任何價值加載到xmlDoc(XmlDocument)。 任何人都可以幫助我失去東西的地方? 任何幫助表示讚賞!

+4

如果您確定不打算使用外部資源,則可以控制XmlDocument的XMLResolver使用的憑據。有關示例,請參閱http://msdn.microsoft.com/zh-cn/library/system.xml.xmldocument.xmlresolver.aspx。在這種情況下,您可以將XmlResolver的憑據設置爲僅具有有限訪問權限的帳戶,因此任何嘗試檢索資源都可以通過NT權限進行控制。 – dash

+2

事實上,這裏是一個非常有用的MSDN文章,它解決了您的問題:http://msdn.microsoft.com/en-us/magazine/ee335713.aspx – dash

回答

28

外部資源使用通過XmlDocument.XmlResolver屬性提供的XmlResolver解決。如果你的XML文檔**不應包含任何外部資源**(例如DTD或模式),只需將此屬性設置爲null

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.XmlResolver = null; 
xmlDoc.LoadXml(OurOutputXMLString); 

如果要篩選,其中這些URL來自(例如允許只有某些域)從XmlUrlResolver中派生出自己的類並覆蓋ResolveUri()方法。在那裏你可以檢查URL是什麼,並對其進行清理(例如,你可以只允許你的本地網絡或可信來源的URL)。

例如:

class CustomUrlResovler : XmlUrlResolver 
{ 
    public override Uri ResolveUri(Uri baseUri, string relativeUri) 
    { 
     Uri uri = new Uri(baseUri, relativeUri); 
     if (IsUnsafeHost(uri.Host)) 
      return null; 

     return base.ResolveUri(baseUri, relativeUri); 
    } 

    private bool IsUnsafeHost(string host) 
    { 
     return false; 
    } 
} 

哪裏IsUnsafeHost()是檢查給定主機允許或不允許的自定義功能。參見SO上的this post,因爲這些想法很少。只需將nullResolveUri()複製到保存您的代碼就是來自這種攻擊。在允許URI的情況下,您可以簡單地返回默認的XmlUrlResolver.ResolveUri()實現。

要使用它:

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.XmlResolver = new CustomUrlResolver(); 
xmlDoc.LoadXml(OurOutputXMLString); 

有關XML外部資源是如何解決的只是MS文檔閱讀Resolving External Resources更多細節。如果你的代碼比這個例子更復雜,那麼你肯定應該閱讀Remarks sectionXmlDocument.XmlResolver屬性。

+0

哇!感謝Adriano爲此工作,併爲我工作。感謝破折號的信息。 –

2

所以它能夠更好地使用

new XmlDocument { XmlResolver = null }; 

有趣的是,從.NET 4.5.2和4.6,默認的解析器行爲不同,不使用前期隱含解決任何網址或地點,因爲我看到的XmlUrlResolver。

//In pre 4.5.2 it is a security issue. 
//In 4.5.2 it will not resolve any more the url references in dtd and such, 
//Still better to avoid the below since it will trigger security warnings. 
new XmlDocument();