Поделиться через


Безопасность LINQ to XML

В этом разделе обсуждаются проблемы безопасности, связанные с LINQ to XML. Кроме того, в нем приводятся рекомендации по снижению рисков нарушения безопасности.

Общие сведения о безопасности LINQ to XML

Технология LINQ to XML разрабатывалась в большей степени для повышения удобства программирования, чем для серверных приложений с жесткими требованиями к безопасности. Большинство XML-сценариев состоит из обработки доверенных XML-документов, а не тех XML-документов, не заслуживающих доверия, которые передаются на сервер. Технология LINQ to XML оптимизирована для таких сценариев.

Если нужно обработать не заслуживающие доверия данные из неизвестного источника, рекомендуется использовать экземпляр класса XmlReader, настроенного на предотвращение путем фильтрации известных атак XML типа «отказ в обслуживании».

Если объект XmlReader сконфигурирован для снижения риска атак типа «отказ в обслуживании», его можно использовать для заполнения дерева LINQ to XML и одновременно воспользоваться преимуществами повышения продуктивности программиста, связанными с LINQ to XML. Многие приемы снижения рисков включают создание агентов чтения, настроенных на решение проблем безопасности, а затем создание экземпляра XML-дерева с помощью такого настроенного агента чтения.

XML по своей природе уязвим для атак типа «отказ в обслуживании» из-за того, что XML-документы не ограничены по размеру, глубине, длине имен элементов и так далее. Независимо от компонента, с помощью которого обрабатывается XML, следует всегда быть готовым к очистке домена приложения, если он потребляет излишне много ресурсов.

Предотвращение атак XML, XSD, XPath и XSLT

Технология LINQ to XML построена на основе объектов XmlReader и XmlWriter. LINQ to XML поддерживает XSD и XPath через методы расширения в пространствах имен System.Xml.Schema и System.Xml.XPath. Используя классы XmlReader, XPathNavigator и XmlWriter совместно с LINQ to XML, можно вызывать XSLT для преобразования XML-деревьев.

При работе в менее защищенной среде возникает несколько проблем безопасности, связанных с XML и использованием классов в System.Xml, System.Xml.Schema, System.Xml.XPath и System.Xml.Xsl. Эти проблемы включают следующие, но не ограничиваются ими.

  • Языки XSD, XPath и XSLT основаны на использовании строк, поэтому в них могут быть определены операции, которые занимают много времени и требуют большого объема памяти. Разработчики приложений, принимающих строки XSD, XPath и XSLT из источников, не заслуживающих доверия, отвечают за то, чтобы осуществлялась проверка этих строк на отсутствие вредоносного кода и чтобы она не приводила к чрезмерному потреблению системных ресурсов.

  • XSD-схемы (включая встроенные схемы) по своей природе уязвимы для атак типа «отказ в обслуживании», поэтому не следует принимать схемы из источников, не заслуживающих доверия.

  • XSD и XSLT могут включать ссылки на другие файлы, что может привести к возникновению атак, охватывающих несколько зон и доменов.

  • Внешние сущности в DTD могут привести к атакам, распространяющимся на несколько зон и доменов.

  • DTD уязвимы для атак типа «отказ в обслуживании».

  • Подверженными атакам типа «отказ в обслуживании» становятся XML-документы с чрезмерно глубокой структурой, поэтому следует ограничивать глубину вложенности элементов в XML-документах.

  • Поддерживающие компоненты, такие как объекты NameTable, XmlNamespaceManager и XmlResolver, не следует принимать из сборок, не заслуживающих доверия.

  • С целью снижения угрозы атак, которые могут быть связаны с обработкой больших документов, рекомендуется считывать данные в виде фрагментов.

  • Предпосылкой возникновения многих атак может стать применение блоков скриптов в таблице стилей XSLT.

  • Перед конструированием динамических выражений XPath следует выполнять тщательную проверку.

Дополнительные сведения об этих атаках и их предотвращении см. в разделе NIB: безопасность и приложения System.Xml.

Вопросы безопасности LINQ to XML

Вопросы безопасности в этом разделе не представлены в каком-либо определенном порядке. Важны все вопросы, поэтому их необходимо решать должным образом.

Успешная атака с целью повышения прав доступа предоставляет вредоносной сборке более полный контроль над средой. Успешная атака с целью повышения прав доступа может привести к раскрытию данных, отказу в обслуживании и так далее.

В приложениях не следует раскрывать данные перед пользователями, не имеющими прав на просмотр этих данных.

Проведение атаки типа «отказ в обслуживании» приводит к тому, что синтаксический анализатор XML или средства LINQ to XML начинают потреблять чрезмерный объем памяти или ресурсов ЦП. Атаки типа «отказ в обслуживании» считаются менее серьезными, чем атаки с целью повышения прав доступа или атаки, направленные на раскрытие данных. Однако и с ними следует считаться в той ситуации, когда сервер должен обрабатывать XML-документы из источников, не заслуживающих доверия.

Исключения и сообщения об ошибках могут привести к раскрытию данных

В описании ошибки раскрываются такие сведения, как преобразуемые данные, имена файлов или подробности реализации. Доступ к сообщениям об ошибках не следует предоставлять вызывающим объектам, не заслуживающим доверия. Необходимо перехватывать все ошибки и создавать собственные сообщения об ошибках.

Отказ от вызова CodeAccessPermissions.Assert в обработчике события

Сборка может иметь меньшее или большее количество разрешений. Сборка с большими разрешениями имеет более полный контроль над компьютером и средой.

Если в коде сборки с большими разрешениями вызывается метод CodeAccessPermission.Assert в обработчике события, а затем полученное XML-дерево передается вредоносной сборке, имеющей меньшие разрешения, то в последней сборке может быть активизировано событие. При этом в обработчике этого события будет выполняться код из сборки с большими разрешениями, поэтому появится возможность применять вредоносную сборку с повышенными правами доступа.

Корпорация Майкрософт рекомендует ни в коем случае не вызывать метод CodeAccessPermission.Assert в обработчике события.

Небезопасные определения DTD

Сущности в DTD изначально являются небезопасными. Применение XML-документа, содержащего DTD, с недобрыми намерениями может привести к тому, что синтаксический анализатор захватит всю память и ресурсы ЦП, создав предпосылки атаки типа «отказ в обслуживании». Поэтому в LINQ to XML обработка DTD отключена по умолчанию. Не следует принимать определения DTD из ненадежных источников.

Примером использования DTD из ненадежных источников служит веб-приложение, позволяющее пользователям Интернета передавать XML-файл, ссылающийся на определение DTD и DTD-файл. При проверке этого файла на наличие вредоносного определения DTD может произойти атака типа «отказ в обслуживании» на сервер. Другим примером приема DTD из ненадежных источников является применение ссылки на DTD в общем сетевом ресурсе, также разрешающем анонимный FTP-доступ.

Отказ от выделения чрезмерного объема буферной памяти

Разработчики приложений должны учитывать, что применение слишком крупных источников данных может привести к исчерпанию ресурсов и возникновению атаки типа «отказ в обслуживании».

Если злонамеренный пользователь предоставляет или передает очень большой XML-документ, это может стать причиной чрезмерного потребления системных ресурсов LINQ to XML. Это равнозначно атаке типа «отказ в обслуживании». Чтобы избежать этого, можно задать значение свойства XmlReaderSettings.MaxCharactersInDocument и создать модуль чтения, который в дальнейшем будет ограничивать размер загружаемого документа. Затем с помощью средства чтения создается XML-дерево.

Например, если известно, что максимальный ожидаемый размер XML-документов из не заслуживающего доверия источника меньше 50 КБ, присвойте свойству XmlReaderSettings.MaxCharactersInDocument значение 100 000. При этом обработка XML-документов не будет нарушена, но уменьшится риск атаки типа «отказ в обслуживании», при которой могут передаваться документы, требующие большого объема памяти.

Предотвращение чрезмерного раскрытия сущности

Одна из известных атак типа «отказ в обслуживании» при использовании DTD основана на документе, вызывающем чрезмерное раскрытие сущности. Чтобы избежать этого, можно задать значение свойства XmlReaderSettings.MaxCharactersFromEntities и создать модуль чтения, который в дальнейшем будет ограничивать число символов, являющихся результатом раскрытия сущности. Затем с помощью средства чтения создается XML-дерево.

Ограничение глубины XML-иерархии

Одной из возможных атак типа «отказ в обслуживании» является предоставление документа с избыточной глубиной иерархии. Чтобы избежать этого, можно заключить XmlReader в собственный класс, который подсчитывает глубину вложенности элементов. Если эта глубина превышает заранее определенную приемлемую величину, можно завершить обработку вредоносного документа.

Защита от не заслуживающих доверия реализаций XmlReader и XmlWriter

Администраторы должны убедиться, что все внешние реализации XmlReader и XmlWriter имеют строгие имена и зарегистрированы в конфигурации компьютера. Это позволяет предотвратить загрузку злонамеренного кода под видом модуля чтения или записи.

Периодическое освобождение объектов, ссылающихся на XName

Чтобы защититься от атак определенных типов, разработчики приложений должны регулярно освобождать все объекты, имеющие ссылку на объект XName в домене приложения.

Защита от случайно сформированных XML-имен

Приложениям, принимающим данные из источников, не заслуживающих доверия, следует заключать модули XmlReader в пользовательский код для проверки на наличие случайно сформированных XML-имен и пространств имен. При обнаружении таких случайно сформированных XML-имен или пространств имен приложение может завершить обработку вредоносного документа.

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

Доступ к заметкам для компонентов программного обеспечения, имеющих совместный доступ к дереву LINQ to XML

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

Определенный уровень безопасности предоставляется средой CLR. Например, компонент, не содержащий закрытый класс, не может получить доступ к заметкам, которые обозначены ключами с помощью этого класса. Однако заметки могут быть удалены компонентами, не имеющими возможность их читать. Это может использоваться в качестве атаки для злонамеренного изменения данных.

См. также

Основные понятия

Руководство по программированию (LINQ to XML)

Другие ресурсы

NIB: безопасность и приложения System.Xml