38

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

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 实体可以包含可以在预期控制之外解析的 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);

但我可以在这里看到 reader 没有任何价值可以加载到xmlDoc(XmlDocument). 任何人都可以在我遗漏的地方提供帮助吗?

4

3 回答 3

51

XmlResolver使用提供的 via属性解析外部资源XmlDocument.XmlResolver。如果您的 XML 文档**不应包含任何外部资源**(例如 DTD 或模式),只需将此属性设置为null

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

如果您想过滤这些 URL 的来源(例如只允许某些域),只需从中派生您自己的类XmlUrlResolver并覆盖该ResolveUri()方法。在那里,您可以检查 URL 是什么并对其进行清理(例如,您可以只允许本地网络中的 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 上的这篇文章。只需返回以null保存的代码免受此类攻击。如果允许 URI,您可以简单地返回默认实现。ResolveUri()XmlUrlResolver.ResolveUri()

要使用它:

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

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

于 2013-01-09T08:40:18.427 回答
6

所以更好用

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(); 
于 2016-11-23T17:06:26.850 回答
0

将 XmlReaderSettings.DtdProcessing 设置为 DtdProcessing.Prohibit 在 .NET 4.7.2 中完全可以正常工作。这是我用来测试的。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE demo 
[
  <!ELEMENT demo ANY >
  <!ENTITY % extentity SYSTEM "https://www.hl7.org/documentcenter/public/wg/structure/CDA.xsl">
  %extentity;
]>
<test>
    Some random content
</test>

将上述内容保存在一个文件中,并从以下 c# 代码片段中读取该文件。

XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
settings.MaxCharactersFromEntities = 6000;
//The following stream should be the filestream of the above content.
XmlReader reader = XmlReader.Create(stream, settings);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);

我得到以下异常。

For security reasons DTD is prohibited in this XML document. To enable DTD 
processing set the DtdProcessing property on XmlReaderSettings to Parse and 
pass the settings into XmlReader.Create method.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.ParseDoctypeDecl()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlDocument.Load(XmlReader reader)
于 2020-12-19T05:16:54.700 回答