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

jun*_*omo 29 .net c# xml asp.net xml-parsing

我们对代码进行了安全审核,他们提到我们的代码容易受到外部实体(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);
Run Code Online (Sandbox Code Playgroud)

在审计报告中,他们说它失败了,因为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);
Run Code Online (Sandbox Code Playgroud)

但我可以在这里看到,读者没有任何值加载到xmlDoc(XmlDocument).任何人都可以帮我错过的地方吗?任何帮助表示赞赏!

Adr*_*tti 40

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

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null;
xmlDoc.LoadXml(OurOutputXMLString);
Run Code Online (Sandbox Code Playgroud)

如果要过滤这些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; 
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个IsUnsafeHost()是自定义函数,用于检查是否允许给定主机.有关一些想法,请参阅此处的帖子.只是返回nullResolveUri()保存从这种攻击代码.如果允许URI,您只需返回默认XmlUrlResolver.ResolveUri()实现.

要使用它:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = new CustomUrlResolver();
xmlDoc.LoadXml(OurOutputXMLString);
Run Code Online (Sandbox Code Playgroud)

有关如何解析XML外部资源的更多详细信息,请阅读解决 MS Docs上的外部资源.如果你的代码是比这个例子更复杂,那么你一定要读备注部分用于XmlDocument.XmlResolver财产.


小智 6

所以最好使用

new XmlDocument { XmlResolver = null };
Run Code Online (Sandbox Code Playgroud)

有趣的是,从 .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(); 
Run Code Online (Sandbox Code Playgroud)