Подтвердить что ты не робот

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

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

"Из соображений безопасности 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 и как делать то, что предлагает сообщение об ошибке. Любая помощь в отношении того, что может быть причиной этого и как его исправить? спасибо...

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

Что такое DTD?

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

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

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

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

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

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

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

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

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

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


Теперь, с учетом этого фона...

Как вы устраните проблему?

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

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

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

Ответ 3

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

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

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

[ДОПОЛНЕНО 3/9/2017]

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