DTD запрещен в исключении xml-документа

Я получаю эту ошибку при попытке проанализировать XML-документ в приложении c#:

" по соображениям безопасности DTD запрещен в этом XML-документе. Чтобы включить обработку DTD, задайте для свойства ProhibitDtd в XmlReaderSettings значение false и передайте параметры в XmlReader.метод Create."

Для справки, исключение произошло во второй строке следующий код:

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

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

мои знания Xml довольно ограничены и я понятия не имею, что такое обработка DTD и как сделать то, что предлагает сообщение об ошибке. Любой справку о том, что может быть причиной этого и как это исправить? спасибо...

3 ответов


обратите внимание, что настройки.ProhibitDtd теперь устарел, вместо этого используйте DtdProcessing: (новые опции игнорировать, анализировать или запрещать)

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

и как указано в этом посте: как работает миллиард смеется XML DoS атаки?

вы должны добавить ограничение на количество символов, чтобы избежать DoS-атак:

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

во-первых, некоторый фон.

что такое DTD?

документ, который вы пытаетесь проанализировать, содержит объявление типа документа; если вы посмотрите на документ, вы найдете в начале последовательность символов, начинающуюся с <!DOCTYPE и заканчивая тегом >. Такое объявление позволяет процессору XML проверять документ на соответствие набору объявлений, которые задают набор элементов и атрибутов и ограничивают значения или содержимое они могут.

поскольку сущности также объявлены в DTDs, DTD позволяет процессору знать, как развернуть ссылки на сущности. (Сущность pubdate может быть определен как содержащий дату публикации документа, например "15 декабря 2012 года", и несколько раз упоминается в документе как &pubdate; -- поскольку фактическая дата указана только один раз в объявлении сущности, это использование упрощает сохранение различных ссылок на дату публикации в документе в соответствии с друг с другом.)

что означает DTD?

объявление типа документа имеет чисто декларативное значение: схему для этого типа документа в синтаксисе, определенном в спецификации XML, можно найти в таком-то и таком-то месте.

некоторое программное обеспечение, написанное людьми со слабым пониманием основ XML, страдает от элементарной путаницы в отношении значения декларации; предполагается, что значение объявления типа документа не декларативный (схема есть), но важно (пожалуйста, проверьте этот документ). Парсер, который вы используете, кажется таким парсером; он предполагает, что, передав ему XML-документ с объявлением типа документа, вы запросили определенный вид обработки. Его авторы могут извлечь выгоду из курса исправления о том, как принимать параметры времени выполнения от пользователя. (Вы видите, как трудно некоторым людям понять декларативную семантику: даже создатели некоторых синтаксических анализаторов XML иногда не понимают их и вместо этого переходят к императивному мышлению. Вздох.)

что это за "причины безопасности", о которых они говорят?

некоторые люди, думающие о безопасности, решили, что обработка DTD (проверка или расширение сущности без проверки) представляет угрозу безопасности. Используя расширение сущностей, легко создать очень маленький поток данных XML, который расширяется, когда все сущности полностью развернуты, в очень большой документ. Поиск информации о том, что называется "миллиардная атака смеется", Если вы хотите прочитать больше.

один очевидный способ защиты от атаки миллиарда смеется для тех, кто вызывает парсер на поставляемых пользователем или ненадежных данных, чтобы вызвать парсер в среде, которая ограничивает объем памяти или время процесса синтаксического анализа разрешено потреблять. Такие ограничения ресурсов были стандартными частями операционных систем С середины 1960-х годов. По причинам, которые остаются неясно для меня, однако, некоторые люди, думающие о безопасности, считают, что правильный ответ-запустить Парсеры на ненадежном входе без ограничения ресурсов, в явном убеждении, что это безопасно, пока вы не сделаете невозможным проверить ввод по согласованной схеме.

вот почему ваша система говорит вам, что ваши данные имеют проблему безопасности.

для некоторых людей идея о том, что DTDs являются риском для безопасности, больше похожа на паранойю, чем на здравый смысл, но я не верю, что они правильные. Помните (а), что здоровая паранойя-это то, что нужно экспертам по безопасности в жизни, и (Б) что любой, кто действительно заинтересован в безопасности, будет настаивать на ограничениях ресурсов в любом случае-при наличии ограничений ресурсов в процессе анализа DTDs безвредны. Запрет DTDs - это не паранойя, а фетишизм.


теперь, с этим фоном в сторону ...

как вы решаете проблему?

лучшее решение это горько жаловаться вашему поставщику, что они были обмануты старой сказкой wive о безопасности XML, и сказать им, что если они заботятся о безопасности, они должны сделать рациональный анализ безопасности вместо запрещения DTDs.

между тем, как следует из сообщения, Вы можете "установить свойство ProhibitDtd на XmlReaderSettings в false и передать настройки в XmlReader.метод Create."Если вход на самом деле ненадежен, вы также можете изучить способы предоставления процесса соответствующие ограничения ресурсов.

и в качестве запасного варианта(я не рекомендую это) вы можете прокомментировать объявление типа документа в своем вводе.


что касается исправления этого, с немного оглядываясь вокруг, я обнаружил, что это было так же просто, как добавить:

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

и передача этих параметров в метод create.

[обновление 3/9/2017]

как указывали некоторые,.ProhibitDTDT теперь устарел. Д-Р Аарон Dishnoответ, ниже, показывает заменяющее решение