如何防止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();