C# xml 文档异常中禁止 DTD

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13854068/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:59:01  来源:igfitidea点击:

DTD prohibited in xml document exception

c#xml-parsingxmlreader

提问by ConnorU

I'm getting this error when trying to parse through an XML document in a C# application:

尝试解析 C# 应用程序中的 XML 文档时出现此错误:

"For security reasons DTD is prohibited in this XML document. To enable DTD processing set the ProhibitDtd property on XmlReaderSettings to false and pass the settings into XmlReader.Create method."

“出于安全原因,此 XML 文档中禁止使用 DTD。要启用 DTD 处理,请将 XmlReaderSettings 上的 ProhibitDtd 属性设置为 false,并将设置传递给 XmlReader.Create 方法。”

For reference, the exception occurred at the second line of the following code:

作为参考,异常发生在以下代码的第二行:

using (XmlReader reader = XmlReader.Create(uri))
{
    reader.MoveToContent(); //here

    while (reader.Read()) //(code to parse xml doc follows).

My knowledge of Xml is pretty limited and I have no idea what DTD processing is nor how to do what the error message suggests. Any help as to what may be causing this and how to fix it? thanks...

我对 Xml 的了解非常有限,我不知道 DTD 处理是什么,也不知道如何按照错误消息的建议进行操作。有关可能导致此问题的原因以及如何解决此问题的任何帮助?谢谢...

采纳答案by Dr. Aaron Dishno

Note that settings.ProhibitDtd is now obsolete, use DtdProcessing instead: (new options of Ignore, Parse, or Prohibit)

请注意 settings.ProhibitDtd 现在已过时,请改用 DtdProcessing:(忽略、解析或禁止的新选项)

XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;

and as stated in this post: How does the billion laughs XML DoS attack work?

正如这篇文章所述: 十亿笑声 XML DoS 攻击是如何工作的?

you should add a limit to the number of characters to avoid DoS attacks:

您应该对字符数添加限制以避免 DoS 攻击:

XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.MaxCharactersFromEntities = 1024;

回答by C. M. Sperberg-McQueen

First, some background.

首先,一些背景。

What is a DTD?

什么是 DTD?

The document you are trying to parse contains a document type declaration; if you look at the document, you will find near the beginning a sequence of characters beginning with <!DOCTYPEand ending with the corresponding >. Such a declaration allows an XML processor to validate the document against a set of declarations which specify a set of elements and attributes and constrain what values or contents they can have.

您尝试解析的文档包含文档类型声明;如果您查看文档,您会在开头附近找到一系列<!DOCTYPE以相应的>.开头和结尾的字符。这样的声明允许 XML 处理器根据一组声明来验证文档,这些声明指定了一组元素和属性,并限制了它们可以具有的值或内容。

Since entities are also declared in DTDs, a DTD allows a processor to know how to expand references to entities. (The entity pubdatemight be defined to contain the publication date of a document, like "15 December 2012", and referred to several times in the document as &pubdate;-- since the actual date is given only once, in the entity declaration, this usage makes it easier to keep the various references to publication date in the document consistent with each other.)

由于实体也在 DTD 中声明,因此 DTD 允许处理器知道如何扩展对实体的引用。(实体pubdate可能被定义为包含文档的发布日期,例如“2012 年 12 月 15 日”,并在文档中多次引用为&pubdate;-- 由于实际日期仅给出一次,因此在实体声明中,这种用法使得更容易使文档中对发布日期的各种引用保持一致。)

What does a DTD mean?

DTD 是什么意思?

The document type declaration has a purely declarative meaning: a schema for this document type, in the syntax defined in the XML spec, can be found at such and such a location.

文档类型声明具有纯粹的声明意义:在 XML 规范中定义的语法中,此文档类型的模式可以在某个位置找到。

Some software written by people with a weak grasp of XML fundamentals suffers from an elementary confusion about the meaning of the declaration; it assumes that the meaning of the document type declaration is not declarative(a schema is over there) but imperative(please validate this document). The parser you are using appears to be such a parser; it assumes that by handing it an XML document that has a document type declaration, you have requested a certain kind of processing. Its authors might benefit from a remedial course on how to accept run-time parameters from the user. (You see how hard it is for some people to understand declarative semantics: even the creators of some XML parsers sometimes fail to understand them and slip into imperative thinking instead. Sigh.)

一些由对 XML 基础知识掌握较弱的人编写的软件对声明的含义存在基本的混淆;它假定文档类型声明的含义不是声明性的(架构在那里)而是命令性的(请验证此文档)。您使用的解析器似乎就是这样的解析器;它假定通过将具有文档类型声明的 XML 文档交给它,您已请求某种处理。它的作者可能会从关于如何接受用户的运行时参数的补习课程中受益。(您会看到有些人理解声明式语义是多么困难:即使是某些 XML 解析器的创建者有时也无法理解它们,而是陷入命令式思维。叹气。)

What are these 'security reasons' they are talking about?

他们谈论的这些“安全原因”是什么?

Some security-minded people have decided that DTD processing (validation, or entity expansion without validation) constitutes a security risk. Using entity expansion, it's easy to make a very small XML data stream which expands, when all entities are fully expanded, into a very large document. Search for information on what is called the "billion laughs attack" if you want to read more.

一些有安全意识的人认为 DTD 处理(验证,或没有验证的实体扩展)构成了安全风险。使用实体扩展,很容易制作一个非常小的 XML 数据流,当所有实体完全扩展时,它会扩展为一个非常大的文档。如果您想阅读更多内容,请搜索有关所谓的“十亿笑声攻击”的信息。

One obvious way to protect against the billion laughs attack is for those who invoke a parser on user-supplied or untrusted data to invoke the parser in an environment which limits the amount of memory or time the parsing process is allowed to consume. Such resource limits have been standard parts of operating systems since the mid-1960s. For reasons that remain obscure to me, however, some security-minded people believe that the correct answer is to run parsers on untrusted input without resource limits, in the apparent belief that this is safe as long as you make it impossible to validate the input against an agreed schema.

防止十亿笑声攻击的一种明显方法是让那些对用户提供的或不受信任的数据调用解析器的人在限制解析过程消耗的内存量或时间的环境中调用解析器。自 1960 年代中期以来,此类资源限制一直是操作系统的标准部分。然而,出于对我来说仍然模糊的原因,一些具有安全意识的人认为正确的答案是在不受资源限制的不受信任的输入上运行解析器,显然相信只要您无法验证输入,这就是安全的反对一个商定的模式。

This is why your system is telling you that your data has a security issue.

这就是为什么您的系统会告诉您您的数据存在安全问题。

To some people, the idea that DTDs are a security risk sounds more like paranoia than good sense, but I don't believe they are correct. Remember (a) that a healthy paranoia is what security experts need in life, and (b) that anyone really interested in security would insist on the resource limits in any case -- in the presence of resource limits on the parsing process, DTDs are harmless. The banning of DTDs is not paranoia but fetishism.

对某些人来说,DTD 是一种安全风险的想法听起来更像是偏执而不是明智,但我认为它们是不正确的。请记住 (a) 健康的偏执狂是安全专家在生活中所需要的,以及 (b) 任何真正对安全感兴趣的人在任何情况下都会坚持资源限制——在解析过程中存在资源限制的情况下,DTD 是无害。禁止 DTD 不是偏执,而是拜物教。



Now, with that background out of the way ...

现在,有了这个背景......

How do you fix the problem?

你如何解决这个问题?

The best solution is to complain bitterly to your vendor that they have been suckered by an old wive's tale about XML security, and tell them that if they care about security they should do a rational security analysis instead of prohibiting DTDs.

最好的解决方案是向您的供应商抱怨他们被老太婆关于 XML 安全的故事所迷惑,并告诉他们如果他们关心安全,他们应该进行合理的安全分析而不是禁止 DTD。

Meanwhile, as the message suggests, you can "set the ProhibitDtd property on XmlReaderSettings to false and pass the settings into XmlReader.Create method." If the input is in fact untrusted, you might also look into ways of giving the process appropriate resource limits.

同时,正如消息所暗示的那样,您可以“将 XmlReaderSettings 上的 ProhibitDtd 属性设置为 false,并将设置传递给 XmlReader.Create 方法”。如果输入实际上是不受信任的,您还可以研究为流程提供适当资源限制的方法。

And as a fallback (I do not recommend this) you can comment out the document type declaration in your input.

作为后备(我不推荐这样做),您可以在输入中注释掉文档类型声明。

回答by ConnorU

As far as fixing this, with a bit of looking around I found it was as simple as adding:

至于解决这个问题,稍微环顾四周,我发现它就像添加一样简单:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;

and passing these settings into the create method.

并将这些设置传递给 create 方法。

[UPDATE 3/9/2017]

[更新 3/9/2017]

As some have pointed out, .ProhibitDTDT is now deprecated. Dr. Aaron Dishno's answer, below, shows the superseding solution

正如一些人指出的那样,.ProhibitDTDT 现在已被弃用。下面的Aaron Dishno 博士的回答显示了替代解决方案

回答by aalesund

After trying all of the above answers without success I changing the service user from [email protected] to [email protected]and now the app works correctly while running in azure.

在尝试了上述所有答案但没有成功后,我将服务用户从 [email protected] 更改为[email protected],现在该应用程序在 azure 中运行时可以正常工作。

Alternatively if you run into this problem in an environment you have more control over; you can paste the following into your hosts file:

或者,如果您在环境中遇到此问题,您可以更好地控制;您可以将以下内容粘贴到您的主机文件中:

127.0.0.1 msoid.onmicrosoft.com
127.0.0.1 msoid.mydomain.com
127.0.0.1 msoid.mydomain.onmicrosoft.com
127.0.0.1 msoid.*.onmicrosoft.com