---
# System prepended metadata

title: Модуль №8
tags: [MOE]

---

## Описание сути уязвимости XXE

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

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

![](https://hackmd.io/_uploads/S1SrogJsh.png)


### Детали XML и DTD, являющиеся причиной для возникновения уязвимости

XML это формат файла, описывается описывается вот [этой](https://www.w3.org/TR/xml/) спецификацией. 

Формат изнутри выглядит как html:

```
<!DOCTYPE foo [ <!ENTITY myentity "my entity value" > ]>
```

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

Основой формирования докуметна с заданными характеристиками является DTD механизм.


По сути это просто набор объявлений, которые предоставляют возможность включать в документ указанные данные. Это может быть картинка, другой xml документ или любое значение - сторока или число.

Особенной частью механима является то, что механизм DTD может работать с:

- объектами внутри xml
- объектами внутри файловой системы ОС
- объектами, которые располагаются в сетевом хранилище (FTP, HTTP, SMB потоколы)

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

:::danger
Стоить помнить, что XML это формат, который используется не только в сыром виде, он так же может быть частью других сложных форматов:

- SOAP конвертов
- DOCX файлов
- SVG картинок
- ...

Нужно иметь в виду, что эти форматы могут так же использовать DTD.
:::

### Условия возникновения уязвимости

Уязвимость появляется при выполнении 2х условий:

1. Данные от пользователя получаются в виде json, а потом перегоняются в XML
2. Данные получаются в XML формате
3. В библиотеке для разбора формата файлов включено использование DTD

:::info
В Java и С# нужно явно указывать, что парсер не имеет возможности работать с DTD, иначе значение по-умолчанию может его включить.
:::

### Последствия эксплуатации

Обычно, при помощи уязвимости можно открывать локально сохраненные в файловой системе файлы, отправлять их содержимое через http и ftp протокол.

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

### Примеры

Чтение файла из файловой системы ОС:
```=
<?xml version="1.0"?>
<!DOCTYPE data [
<!ELEMENT data (#ANY)>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<data>&file;</data>
```

Чтение файлай из файловой системы через SOAP:
```=
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>
```

SSRF:

```=
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "http://internal.service/secret_pass.txt" >
]>
<foo>&xxe;</foo>
```


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


```C#=
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;

namespace XXEExamples.Tests
{
    [TestFixture]
    public class XmlReader_Tests
    {
        [Test]
        public void XMLReader_WithDTDProcessingParseAndXmlResolverSet_NotSafe()
        {
            AssertXXE.IsXMLParserSafe((string xml) =>
            {
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.DtdProcessing = DtdProcessing.Parse;
                settings.XmlResolver = new XmlUrlResolver();
                settings.MaxCharactersFromEntities = 6000;

                using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
                {
                    XmlReader reader = XmlReader.Create(stream, settings);

                    var xmlDocument = new XmlDocument();
                    xmlDocument.XmlResolver = new XmlUrlResolver();
                    xmlDocument.Load(reader);
                    return xmlDocument.InnerText;
                }
            }, false);
        }

        [Test]
        public void XMLReader_WithDTDProcessingIgnored_Safe()
        {
            var exception = Assert.Throws<XmlException>(() =>
            {
                AssertXXE.IsXMLParserSafe((string xml) =>
                {
                    XmlReaderSettings settings = new XmlReaderSettings();
                    settings.DtdProcessing = DtdProcessing.Ignore;
                    settings.MaxCharactersFromEntities = 6000;

                    using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
                    {
                        XmlReader reader = XmlReader.Create(stream, settings);

                        var xmlDocument = new XmlDocument();
                        xmlDocument.XmlResolver = new XmlUrlResolver();
                        xmlDocument.Load(reader);
                        return xmlDocument.InnerText;
                    }
                }, true);
            });

            Assert.IsTrue(exception.Message.StartsWith("Reference to undeclared entity 'xxe'."));
        }

        [Test]
        public void XMLReader_WithDTDProcessingProhibited_Safe()
        {
            var exception = Assert.Throws<XmlException>(() =>
            {
                AssertXXE.IsXMLParserSafe((string xml) =>
                {
                    XmlReaderSettings settings = new XmlReaderSettings();
                    settings.DtdProcessing = DtdProcessing.Prohibit;
                    settings.MaxCharactersFromEntities = 6000;

                    using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
                    {
                        XmlReader reader = XmlReader.Create(stream, settings);

                        var xmlDocument = new XmlDocument();
                        xmlDocument.XmlResolver = new XmlUrlResolver();
                        xmlDocument.Load(reader);
                        return xmlDocument.InnerText;
                    }
                }, true);
            });

            Assert.IsTrue(exception.Message.StartsWith("For security reasons DTD is prohibited in this XML document."));
        }
    }
}
```

```C#=
using Microsoft.AspNetCore.Mvc;
using System;
using System.Xml;

namespace WebFox.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class XxeTest1 : ControllerBase
    {

        [HttpGet("{xmlString}")]
        public void DoXxe(String xmlString)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xmlString);
        }
    }
}
```

### Способы защиты

- Проверка версий окружения, языка программирования, по-умолчанию могут быть разные значения флагов для включения DTD
- полное отключение DTD и XInclude


## Практика

- https://portswigger.net/web-security/all-labs
- https://ringzer0ctf.com/challenges/85
- https://www.root-me.org/en/Challenges/Web-Server/XML-External-Entity
