XXE-атака – тип атаки на приложение, основанный на обработке внешних данных небезопасно сконфигурированным XML-парсером. Уязвимость приложения к данному дефекту безопасности может привести к раскрытию конфиденциальных данных со скомпрометированного устройства.
Примечание. В данном документе описывается XXE-атака. XEE-атака, также известная как 'billion laughs'-атака, атака с использованием XML-бомб, описана здесь.
Стандарт 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-файла. Кроме того, следствием атаки может стать подделка запросов на стороне сервера (SSRF).
Предположим, что есть приложение, которое принимает запросы в виде 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 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
};
Стоит также отметить, что дефолтные настройки некоторых XML-парсеров могут изменяться в разных версиях библиотек. Например, Microsoft поменяли настройки некоторых XML-парсеров между .NET Framework 4.5.1 и .NET Framework 4.5.2, сделав их более безопасными по умолчанию.
Рассмотрим следующий фрагмент кода:
static void XmlDocumentTest(String pathToXml)
{
var xml = File.ReadAllText(pathToXml);
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
Console.WriteLine(doc.InnerText);
}
В версиях .NET Framework 4.5.1 и более старых данный код уязвим к XXE-атакам, так как по умолчанию XmlResolver не равен null и обрабатывает внешние сущности.
Однако этот же код является устойчивым к XXE-атакам в .NET Framework 4.5.2 и более новых версиях, так как свойство XmlResolver по умолчанию имеет значение null. Как следствие, внешние сущности не будут обработаны.
0