Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top

Вебинар: Использование статических анализаторов кода при разработке безопасного ПО - 19.12

>
>
>
V5614. OWASP. Potential XXE vulnerabili…
menu mobile close menu
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Микрооптимизации (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C++)
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

V5614. OWASP. Potential XXE vulnerability. Insecure XML parser is used to process potentially tainted data.

01 Окт 2021

Анализатор обнаружил использование небезопасно сконфигурированного XML-парсера, который обрабатывает данные, полученные из внешнего источника. Это может сделать приложение уязвимым к XXE-атаке.

XXE-атаки выделены в отдельную категорию рисков в OWASP Top 10 Application Security Risks 2017: A4:2017 – XML External Entities (XXE) и включены в категорию A05:2021 – Security Misconfiguration OWASP Top 10 2021.

Суть XXE-атаки

Стандарт XML предусматривает использование DTD (document type definition). DTD даёт возможность определять и использовать XML-сущности. Сущности могут быть как полностью определены внутри документа (например, представлять собой какую-то строку), так и ссылаться на какой-то внешний ресурс. Отсюда и происходит название XXE-атаки: XML eXternal Entities.

Внешние сущности могут быть определены через URI, вследствие чего XML-парсер может обработать этот URI и подставить полученное содержимое в XML-документ.

Пример XML-документа, в котором определена внешняя сущность:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file://D:/XXETarget.txt">
]>
<foo>&xxe;</foo>

Здесь определена сущность '&xxe;'. При обработке этого XML парсер подставит вместо '&xxe;' содержимое файла 'D:\XXETarget.txt'.

Таким образом, атака возможна, если:

  • злоумышленник может передать приложению XML-файл с внешними сущностями, и приложение выполнит парсинг этого файла;
  • XML-парсер имеет небезопасную конфигурацию;
  • данные парсинга (значения сущностей) могут попасть обратно к злоумышленнику.

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

Примеры уязвимого кода

PVS-Studio выдаст предупреждение, если обнаружит в коде небезопасно сконфигурированный XML-парсер, который обрабатывает данные, которые могут быть получены из внешнего источника.

Рассмотрим простой пример. Есть приложение, которое принимает запросы в виде XML-файлов и обрабатывает товары с соответствующим идентификатором. Если идентификатор задан неверно, приложение сообщает об этом.

Формат XML-файла, с которым работает приложение:

<?xml version="1.0" encoding="utf-8" ?>
<shop>
  <itemID>62</itemID>
</shop>

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

static void ProcessItemWithID(String pathToXmlFile)
{
  XmlReaderSettings settings = new XmlReaderSettings()
  {
    XmlResolver = new XmlUrlResolver(),
    DtdProcessing = DtdProcessing.Parse
  };

  using (var fileReader = File.OpenRead(pathToXmlFile))
  {
    using (var reader = XmlReader.Create(fileReader, settings))
    {
      while (reader.Read())
      {
        if (reader.Name == "itemID")
        {
          var itemIDStr = reader.ReadElementContentAsString();
          if (long.TryParse(itemIDStr, out var itemIDValue))
          {
            // Process item with the 'itemIDValue' value
            Console.WriteLine(
              $"An item with the '{itemIDValue}' ID was processed.");
          }
          else
          {
            Console.WriteLine($"{itemIDStr} is not valid 'itemID' value.");
          }
        }
      }
     }
  }
}

Для приведённого выше XML-файла приложение распечатает следующую строку:

An item with the '62' ID was processed.

Если вместо номера в ID будет записано что-то другое (например, строка "Hello world"), приложение сообщит об ошибке:

"Hello world" is not valid 'itemID' value.

Несмотря на то, что код делает то, что от него ожидается, он уязвим к XXE-атакам за счёт соблюдения всех перечисленных ранее факторов:

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

Ниже представлен XML-файл, через который можно скомпрометировать данный код:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file://D:/MySecrets.txt">
]>
<shop>
  <itemID>&xxe;</itemID>
</shop>

В этом файле объявляется внешняя сущность 'xxe', которая будет обработана парсером. Вследствие этого содержимое файла 'D:/MySecrets.txt' (например, такое: 'This is an XXE attack target.'), находящегося на машине, где запущено приложение, будет выдано пользователю:

This is an XXE attack target. is not valid 'itemID' value.

Для того, чтобы обезопаситься от подобной атаки, можно запретить обработку внешних сущностей (присвоить свойству 'XmlResolver' значение 'null'), а также запретить или игнорировать обработку DTD (записать в свойство 'DtdProcessing' значение 'Prohibit' или 'Ignore' соответственно).

Пример безопасных настроек:

XmlReaderSettings settings = new XmlReaderSettings()
{
  XmlResolver = null,
  DtdProcessing = DtdProcessing.Prohibit
};

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

static void ProcessXML(String pathToXmlFile)
{
  XmlDocument xmlDoc = new XmlDocument();
  xmlDoc.XmlResolver = new XmlUrlResolver();

  using (var xmlStream = File.OpenRead(pathToXmlFile))
  {
    xmlDoc.Load(xmlStream);
    Console.WriteLine(xmlDoc.InnerText);
  }
}

Здесь загрузка XML происходит через экземпляр типа 'XmlDocument'. При этом для 'XmlResolver' явно выставлено опасное значение, а обработка DTD включена неявно. Чтобы запретить обработку внешних сущностей, достаточно записать в свойство 'XmlResolver' значение 'null'.

Анализатор также учитывает и межпроцедурные вызовы. Рассмотрим пример:

static FileStream GetXmlFileStream(String pathToXmlFile)
{
  return File.OpenRead(pathToXmlFile);
}

static XmlDocument GetXmlDocument()
{
  XmlDocument xmlDoc = new XmlDocument()
  {
    XmlResolver = new XmlUrlResolver()
  };

  return xmlDoc;
}

static void LoadXmlInternal(XmlDocument xmlDoc, Stream input)
{
  xmlDoc.Load(input);
  Console.WriteLine(xmlDoc.InnerText);
}

static void XmlDocumentTest(String pathToXmlFile)
{
  using (var xmlStream = GetXmlFileStream(pathToXmlFile))
  {
    var xmlDoc = GetXmlDocument();
    LoadXmlInternal(xmlDoc, xmlStream);
  }
}

В данном случае анализатор выдаст предупреждение на вызов метода 'LoadXmlInternal', так как отследит, что:

  • парсер, полученный из метода 'GetXmlDocument', может обрабатывать внешние сущности;
  • поток, полученный из метода 'GetXmlStream', содержит данные, полученные из внешнего источника (прочитанные из файла);
  • парсер и 'заражённые' данные передаются в метод 'LoadXmlInternal', где выполняется обработка XML-файла.

Стоит отметить, что анализатор также считает источниками небезопасных данных параметры методов, доступных из других сборок. Более подробно эта тема раскрыта в заметке "Почему важно проверять значения параметров общедоступных методов".

Например, на следующий код будет выдано предупреждение низкого уровня достоверности, так как источник небезопасных данных – параметр публично-доступного метода:

public static void XmlDocumentTest(Stream xmlStream)
{
  XmlDocument doc = new XmlDocument()
  {
    XmlResolver = new XmlUrlResolver()
  };

  doc.Load(xmlStream);
  Console.WriteLine(doc.InnerText);
}

Обратите внимание, что настройки некоторых XML-парсеров менялись в разных версиях .NET Framework.

Рассмотрим следующий фрагмент кода:

static void XmlDocumentTest(String pathToXml)
{
  var xml = File.ReadAllText(pathToXml);
  XmlDocument doc = new XmlDocument();

  doc.LoadXml(xml);
  Console.WriteLine(doc.InnerText);
}

Данный код является устойчивым к XXE-атакам в .NET Framework 4.5.2 и более новых версиях, так как свойство 'XmlResolver' по умолчанию имеет значение 'null'. Как следствие, внешние сущности не будут обработаны.

В версиях .NET Framework 4.5.1 и более старых данный код уязвим к XXE-атакам, так как по умолчанию 'XmlResolver' не равен 'null' и обрабатывает внешние сущности.

PVS-Studio также учитывает дефолтные настройки парсеров в зависимости от того, какая версия .NET Framework / .NET используется в анализируемом проекте.

Общая рекомендация по защите от XXE-атак – следить за тем, чтобы обработка DTD была отключена; обработка внешних сущностей – запрещена. В разных XML-парсерах настройки могут немного отличаться, но, как правило, за это отвечают свойства 'DtdProcessing' ('ProhibitDtd' в более старых версиях .NET Framework) и 'XmlResolver'.

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.).

Данная диагностика классифицируется как:

close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам