Найти в Дзене
Инспектор Гаджет.

Path Injection - Типы и Методы Предотвращения

В этой статье мы рассмотрим такой тип уязвимостей в web-приложениях, как - XPath Injection.

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

Примечание: эта статья предназначена только для образовательных целей. Будьте частью конструктивного общества.

Веб-приложения хранят данные и получают доступ к ним различными способами и формами в зависимости от их вариантов использования. Исторически реляционные базы данных были популярным выбором среди других баз данных для хранения большого количества данных. Однако растет тенденция к использованию XML для хранения данных. При использовании XML данные хранятся во вложенной структуре в виде древа, а не столбцов и строк. У этого есть много недостатков, но его можно использовать для статических данных, таких как параметры конфигурации. Это связано с тем, что такие статические данные требуют меньше операций чтения/записи, что очень медленно происходит в базах данных XML.

При аудите веб-приложения можно легко упустить из виду определенные типы уязвимостей, если не проводить систематическую проверку каждого из них в отдельности. Инъекционные эксплойты хорошо известны, и действительно, они заняли первое место в рейтинге OWASP Top 10; однако в этой статье мы обсудим атаку, которая гораздо менее популярна, чем внедрение SQL, XPath и XQuery.

Что такое XPATH и XQuery?

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

Данные, хранящиеся в XML, можно запрашивать через XPath, который концептуально аналогичен SQL. Это также язык запросов, который используется для поиска определенных элементов в XML-документе. Разрешения на уровне доступа отсутствуют, и можно ссылаться практически на любую часть XML-документа, в отличие от SQL, который допускает ограничения для баз данных, таблиц или столбцов.

Это связано с тем, что XPath отличается от других языков баз данных, поскольку в нем отсутствуют элементы управления доступом или аутентификация пользователей.

XQuery - это расширенный набор языка XPath, который добавляет синтаксис, подобный SQL, а также некоторые полезные функции для запросов к документу.

Что такое XPath Injection?

Проблемы, которые могут возникнуть при хранении данных с использованием XML, также аналогичны проблемам, возникающим в SQL. Внедрение XPath - это тип атаки, при которой злонамеренный ввод может привести к несанкционированному доступу или раскрытию конфиденциальной информации, такой как структура и содержимое XML-документа. Это происходит, когда ввод пользователя используется при построении строки запроса. Большое количество методов, которые можно использовать в атаке с использованием SQL-инъекции, зависят от характеристик диалекта SQL, используемого целевой базой данных, тогда как атаки с использованием XPath-инъекции могут быть гораздо более адаптируемыми и повсеместными.

Принцип XPath-инъекции очень похож на SQL-инъекцию. Цель атаки тоже очень похожа. Единственная разница между этими атаками заключается в том, что внедрение XPath использует XML-файл для хранения данных вместо базы данных. Один из способов получить данные из XML-файла, должен использоваться XPath.

В некоторых случаях параметры в теле SOAP напрямую используются в качестве входных данных для запроса xpath. Если этот ввод пользователя не подтвержден, вероятно, злоумышленник может изменить запрос Xpath по своему желанию. В худшем случае злоумышленник сможет прочитать весь запрошенный XML-документ. 

  • SOAP - протокол обмена структурированными сообщениями в распределённой вычислительной среде. Первоначально SOAP предназначался в основном для реализации удалённого вызова процедур (RPC). Сейчас протокол используется для обмена произвольными сообщениями в формате XML, а не только для вызова процедур. Официальная спецификация последней версии 1.2 протокола никак не расшифровывает название SOAP. SOAP является расширением протокола XML-RPC

Подобно SQL Injection, атаки XPath Injection происходят, когда веб-сайт использует предоставленную пользователем информацию для построения запроса XPath для данных XML. Отправляя преднамеренно искаженную информацию на веб-сайт, злоумышленник может узнать, как структурированы данные XML, или получить доступ к данным, к которым у него обычно нет доступа. Они могут даже иметь возможность повысить свои привилегии на веб-сайте, если данные XML используются для аутентификации (например, файл пользователя на основе XML).

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

XPath - стандартный язык; его нотация / синтаксис всегда не зависит от реализации, что означает, что атака может быть автоматизирована. Нет разных диалектов, как это происходит в запросах к базам данных SQL.

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

Пример уязвимости XPath Injection

Мы будем использовать этот фрагмент XML для примеров:

<?xml version="1.0" encoding="utf-8"?>
<Employees>
<Employee ID="1">
<FirstName>Arnold</FirstName>
<LastName>Baker</LastName>
<UserName>ABaker</UserName>
<Password>SoSecret</Password>
<Type>Admin</Type>
</Employee>
<Employee ID="2">
<FirstName>Peter</FirstName>
<LastName>Pan</LastName>
<UserName>PPan</UserName>
<Password>NotTelling</Password>
<Type>User</Type>
</Employee>
</Employees>

Предположим, у нас есть система аутентификации пользователей на веб-странице, которая использует такой файл данных для входа пользователей. После ввода имени пользователя и пароля программа может использовать XPath для поиска пользователя:

VB:
Dim FindUserXPath as String
FindUserXPath = "//Employee[UserName/text()='" & Request("Username") & "' And
Password/text()='" & Request("Password") & "']"

C#:
String FindUserXPath;
FindUserXPath = "//Employee[UserName/text()='" + Request("Username") + "' And
Password/text()='" + Request("Password") + "']";

С обычным именем пользователя и паролем этот XPath будет работать, но злоумышленник может отправить неверное имя пользователя и пароль и выбрать узел XML, не зная имени пользователя или пароля, например:

Username: blah' or 1=1 or 'a'='a
Password: blah

FindUserXPath becomes //Employee[UserName/text()='blah' or 1=1 or
'a'='a' And Password/text()='blah']

Logically this is equivalent to:
//Employee[(UserName/text()='blah' or 1=1) or
('a'='a' And Password/text()='blah')]

В этом случае истинной должна быть только первая часть XPath. Часть пароля становится неактуальной, а часть UserName будет соответствовать ВСЕМ сотрудникам из-за части «1 = 1».

Рассмотрим следующее хранилище данных XML:

<addressBook>
<address>
<firstName>William</firstName>
<surname>Gates</surname>
<password>MSRocks!</password>
<email>billyg@microsoft.com</email>
<ccard>5130 8190 3282 3515</ccard>
</address>
<address>
<firstName>Chris</firstName>
<surname>Dawes</surname>
<password>secret</password>
<email>cdawes@craftnet.de</email>
<ccard>3981 2491 3242 3121</ccard>
</address>
<address>
<firstName>James</firstName>
<surname>Hunter</surname>
<password>letmein</password>
<email>james.hunter@pookmail.com</email>
<ccard>8113 5320 8014 3313</ccard>
</address>
</addressBook>

Запрос XPath для получения всех адресов электронной почты из этого хранилища данных будет выглядеть следующим образом:

//address/email/text()

Запрос на возврат всех сведений о пользователе Dawes будет выглядеть так: 

//address[surname/text()=’Dawes’]

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

Давайте посмотрим, как мы можем выполнить инъекцию на этом примере. Этот код поступает из веб-приложения, которое предоставляет информацию о кредитной карте пользователям, вошедшим в него. Запрос XPath, который эффективно проверяет предоставленные пользователем учетные данные и извлекает номер соответствующей кредитной карты пользователя, может быть:

//address[surname/text()=’Dawes’ and password/text()=’secret’]/ccard/text()

Так же, как и в случае внедрения SQL-кода, злоумышленник может перехватить запрос приложения, предоставив пароль со следующим значением:

‘ or ‘a’=’a

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

//address[surname/text()=’Dawes’ and password/text()=’’ or ‘a’=’a’]/ccard/text()

Помните, что в отличие от запросов SQL, ключевые слова в запросах XPath чувствительны к регистру, как и имена элементов в самом документе XML.

Чтобы продолжить, можно использовать недостатки внедрения XPath для извлечения произвольной информации из целевого XML-документа. Один из широко используемых способов сделать это, используя ту же технику, что мы видели при внедрении SQL, заставляя приложение реагировать по-разному, в зависимости от условия, указанного злоумышленником.

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

‘ or 1=1 and ‘a’=’a
‘ or 1=2 and ‘a’=’a

Это различие в поведении может быть использовано для проверки истинности любого указанного условия и, следовательно, для извлечения произвольной информации по одному байту за раз. Как и в случае с SQL, язык XPath содержит функцию подстроки, которую можно использовать для проверки значения строки по одному символу за раз. Например, предоставив следующий оператор:

‘ or //address[surname/text()=’Thomas’ and substring(password/text(),1,1)=‘S’] and ‘a’=’a

Это приводит к следующему запросу:

//address[surname/text()=’Mel’ and password/text()=’’ or //address[surname/text()=’Thomas’ and substring(password/text(),1,1)= ‘S’] and ‘a’=’a ‘]/ccard/text()

Который возвращает результаты, если первым символом пароля пользователя Thomas является S. Путем циклического перебора каждой позиции символа и проверки каждого возможного значения мы можем извлечь полное значение пароля Thomas.

Поиск уязвимостей XPath Injection

Допустим, разработчик хранит данные аутентификации в XML-файле со следующей структурой:

...
<user>
<name>UserName</UserName>
<password>Password</password>
</user>
...

При аутентификации разработчик строит выражение Xpath следующим образом:

string//user[name/text()='"txtUserName.Text"' and password/text()='" txtPassword.Text"'])

Переменные txtUserName и txtPassword являются стандартными текстовыми полями ASPX. Когда злоумышленник вставляет выражение с кавычкой (') в одно из текстовых полей, он завершает строку и может написать свое собственное выражение XPath. Как я и говорил выше, сценарий похож на SQL-инъекцию.

Первый известный мне метод обнаружения подобного рода уязвимости, омнова на ручном вводе, пробуем подставлять следующие данные: 

  • 'whatever – basic test
  • DROP
  • Something

Во все поля ввода / параметры URL / и что угодно. Если вы видите какую-либо ошибку, связанную с классами, которые обеспечивают манипуляции с XML в ASP.NET, вы, вероятно, обнаружили угрозу иньекции XPath.

Второй способ - поиск уязвимостей в коде. Вы можете искать следующие строки: 

  • Xpath - многие классы, которые работают с XPath, имеют в своем имени строку 'xpath'
  • SelectSingleNode () и SelectNodes () - методы, используемые для получения данных из файлов XML через XPath.

Практический пример XPath Injection

-2

Исходный код формы выглядит так:

$xml = simplexml_load_file("passwords/heroes.xml");
$result = $xml->xpath("/heroes/hero[login='" . $login . "' and password='" . $password . "']");

Используем следующую полезную нагрузку:

blah' or id='2

За ID берём условный порядковый номер пользователя в системе и подставляем в форму логина и пароля:

-3

Пробуем перебирать ID чтобы получать новые логины и пароли пользователей.

Следующий пример - это форма поиска:

-4

Подставив кавычку в запрос в URL мы можем вызвать ошибку, которая намекает нам на дальнейшие действия:

http://192.168.0.115/bWAPP/xmli_2.php?genre=action%27&action=search

-5

Используем следующую полезную нагрузку для получения паролей пользователей:

http://192.168.0.115/bWAPP/xmli_2.php?genre=horror%27)]/password%20|%20a[contains(a,%27&action=search

-6

Защита от XPath Injection

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

В следующем примере одинарные кавычки (‘) используются для завершения параметров имени пользователя и пароля. Итак, нам нужно заменить все символы ‘ в этом вводе версией этого символа в кодировке XML, то есть « ’». 

VB:
Dim FindUserXPath as String
FindUserXPath = "//Employee[UserName/text()='" & Request("Username").Replace("'", "'") & "' And
Password/text()='" & Request("Password").Replace("'", "'") & "']"

C#:
String FindUserXPath;
FindUserXPath = "//Employee[UserName/text()='" + Request("Username").Replace("'", "'") + "' And
Password/text()='" + Request("Password").Replace("'", "'") + "']";

  • Использование предварительно скомпилированного запроса XPath1. Предварительно скомпилированные запросы XPath уже задаются до выполнения программы, а не создаются на лету после того, как пользовательский ввод был добавлен в строку. Это лучший способ, потому что вам не нужно беспокоиться об отсутствии символа, который нужно было экранировать.
  • Пользовательский ввод можно отфильтровать, например, цитату (‘) можно заменить на «' ». Проверка должна быть добавлена как на стороне клиента, так и на стороне сервера.
  • Использование параметризованных запросов (например, подготовленные операторы в SQL), в которых запросы предварительно скомпилированы, а пользовательский ввод передается как параметры, а не выражения.

"//users[LoginID/text()= $LoginID and passwd/text()= $password]”

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