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

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

XXE\-атаки выделены в отдельную категорию рисков в OWASP Top 10 Application Security Risks 2017: [A4:2017 – XML External Entities \(XXE\)](https://owasp.org/www-project-top-ten/2017/A4_2017-XML_External_Entities_(XXE).html) и включены в категорию [A05:2021 – Security Misconfiguration](https://owasp.org/Top10/A05_2021-Security_Misconfiguration/) OWASP Top 10 2021\.

## Суть XXE\-атаки

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

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

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

```cpp
<?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\-файла, с которым работает приложение:

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

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

```cpp
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\-файла приложение распечатает следующую строку:

```cpp
An item with the '62' ID was processed.
```

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

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

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

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

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

```cpp
<?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\.'\), находящегося на машине, где запущено приложение, будет выдано пользователю:

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

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

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

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

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

```cpp
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'\.

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

```cpp
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\-файла\.

Стоит отметить, что анализатор также считает источниками небезопасных данных параметры методов, доступных из других сборок\. Более подробно эта тема раскрыта в заметке "[Почему важно проверять значения параметров общедоступных методов](https://pvs-studio.ru/ru/blog/posts/csharp/0835/)"\.

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

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

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

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

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

```cpp
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'\.