如何防止XXE攻击(.net中的XmlDocument)

我们对代码进行了安全审核,他们提到我们的代码容易受到外部实体(XXE)攻击。 我正在使用以下代码 –

string OurOutputXMLString= "00000Logince_useridce_subscribernamece_subscriberidce_groupidUnitTester9pDhE5AsKBHw85Sqgg6qdKQ==tOlkiae9epM=" XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(OurOutputXMLString); 

在审计报告中,他们说它失败了,因为XML实体可以包含可以在预期的控制之外解析的URL。 XML实体解析器将尝试解析和检索外部引用。 如果可以将攻击者控制的XML提交给其中一个function,则攻击者可以访问有关内部网络,本地文件系统或其他敏感数据的信息。 为了避免这种情况,我编写了以下代码,但它不起作用。

 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)。 任何人都可以帮我错过的地方吗? 任何帮助表示赞赏!

使用通过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()是一个自定义函数,用于检查是否允许给定主机。 有关一些想法,请参阅此处的post 。 只需从ResolveUri()返回null即可保存代码免受此类攻击。 如果允许URI,您只需返回默认的XmlUrlResolver.ResolveUri()实现。

要使用它:

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

有关如何解析XML外部资源的更多详细信息,请阅读解决 MS Docs上的外部资源 。 如果您的代码比此示例更复杂,那么您一定要阅读XmlDocument.XmlResolver属性的备注部分 。

所以它更好用

 new XmlDocument { XmlResolver = null }; 

有趣的是,从.net 4.5.2和4.6开始,默认解析器的行为有所不同,并且不会在前面隐式使用XmlUrlResolver来解析我看到的任何URL或位置。

 //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();