На прошлых выходных хотел по-быстрому решить задачку по информационной безопасности web-серверов и написать статью. Но не тут-то было. Задачка с портала root-me.org, называется "PHP - Remote Xdebug". За решение задачки дают 25 баллов, средний уровень.
С этой задачей я застрял на целую неделю, только вчера успешно завершил. Самое интересное, с самого начала было понятно где находится уязвимость, однако, добраться до неё оказалось не просто. Люблю такие задачи, когда узнаёшь что-то новое.
Читаем текст:
- Remote Xdebug
- remote_connect_back
Xdebug — расширение PHP для профилирования и отладки PHP-скриптов. Работает по протоколу DBGp.
Эта полезная утилита помогает разработчикам PHP упростить отладку PHP-скриптов с помощью точек останова, пошагового выполнения и отслеживания выражений. А ещё лучше делать это удалённо, из дома. Собственно, об удалённой работе нам сообщает подсказка "remote_connect_back".
А требуется нам добраться до содержимого некоторого файла, в котором и будет флаг.
Ссылки
Решение
Посмотрим на страницу задания:
У нас имеется простой сайт, который отображает IP адрес посетителя, т.е. наш внешний IP адрес.
Из описания к заданию мы можем сделать вывод, что разработчик данного сайта занимается отладкой кода удалённо, используя Xdebug. Краткая схема взаимодействия:
- На удалённом сайте устанавливается и настраивается Xdebug — расширение для PHP.
- Разработчик запускает свою любимую IDE, конфигурирует, ставит необходимые плагины, в том числе для браузера.
- Разработчик открывает в браузере сайт, включает дебаг, и сервер сам коннектится по указанному в настройках порту на домашний IP адрес разработчика.
- Разработчик дебажит код.
Разработчик может из дома удалённо подключаться к сайту и дебажить код во все брек-поинты. Для работы ему нужен прямой IP адрес, потому как Xdebug сам соединяется с клиентом. Если IP адрес разработчика плавающий, или отладкой кода занимаются несколько программистов, то в настройках Xdebug может присутствовать небезопасная опция:
xdebug.discover_client_host = true
И если она есть, то мы можем временно стать разработчиками PHP и сами отдебажить проект. Прямой IP адрес у меня есть. Нам нужно будет установить IDE, настроить её и включить дебаг. В качестве редактора кода я буду использовать Visual Studio Code.
Visual Studio Code — кроссплатформенный открытый редактор кода, разработанный компанией Microsoft. Бесплатный.
И вот тут я застрял, не нашлось нормальных инструкций по настройке Remote Xdebug для Visual Studio Code, пришлось разобраться и написать всё самому.
Visual Studio Code — remote Xdebug
Устанавливаем Visual Studio Code.
Находим расширение PHP Debug и устанавливаем.
Создаю для проекта папку C:\CTF, открываю её в VSCode.
Тыкаем слева в иконку с жуком.
Нажимаю на ссылку для создания файла launch.json.
В проекте создаётся файл launch.json с примером настроек. в элементе JSON массива с параметром "name": "Listen for Xdebug" находим параметр "port" и меняем его значение на 9000. Почему 9000? Последняя версия Xdebug работает с портом 9003, однако, когда создавали задачку CTF, использовали более старую версию Xdebug, которая работает с портом 9000. Можно, конечно, весь диапазон портов на свой комп пробросить, потом посмотреть куда будет ломиться Xdebug, но мне сразу повезло с портом TCP 9000.
Слева вверху в блоке RUN AND DEBUG выбираем из списка "Listen for Xdebug" и нажимаем зелёный треугольник для запуска.
Открывается оповещение безопасности. Ставим галки. Разрешить доступ.
VSCode начинает слушать порт TCP 9000. Останавливаем дебаг. Нажимаем красный квадрат (Stop).
Для того чтобы сервер достучался до порта 9000 на моём компе (а сегодня я за разработчика PHP), нужно на роутере пробросить порт 9000 с внешнего прямого IP адреса на порт 9000 локального компьютера.
ipconfig
Локальный IP у меня 192.168.1.105.
Пробрасываю на него порт 9000 с внешнего IP.
Работать будем в браузере Edge.
Устанавливаем расширение Xdebug helper.
Заходим на наш сайт задания, На иконке расширения выбираем зелёного жука Debug.
Редактируем launch.json.
{
"version": "0.2.0",
"configurations": [
{
"name": "remote XDebug",
"type": "php",
"request": "launch",
"hostname": "0.0.0.0",
"port": 9000,
"log": true,
"stopOnEntry": true,
"pathMappings": {
"C:\\ctf": "${workspaceFolder}"
}
}
]
}
Разворачиваем вкладку BREAKPOINTS слева внизу и ставим галки на всех типах точек останова. Слева вверху в блоке RUN AND DEBUG выбираем из списка "remote XDebug" и нажимаем зелёный треугольник для запуска. Или F5.
Обновляем окно браузера.
Опа, мы попали на точку останова. Скажем что-нибудь в консоли по PHP-шному:
phpinfo();
Команда выполнилась. Посмотрим в браузер.
Мы не только попали на точку останова, но и смогли удалённо выполнить команду PHP. Осталось выполнить наше задание.
Отключаю вывод лога, чтобы не засорять экран, заново включаю дебаг, попадаю на точку останова. Выполним другую команду, выведем список файлов в текущей директории:
scandir(".");
Видим в директории интересный файл c491a08d66309dc3e4dd1e040c178022.txt. Заглянем внутрь:
file_get_contents("./c491a08d66309dc3e4dd1e040c178022.txt");
И получаем наш флаг. Валидируем.
Получаем 25 очков.
Безопасность
Xdebug — полезная утилита, которая помогает разработчикам PHP упростить отладку PHP-скриптов с помощью точек останова, пошагового выполнения и отслеживания выражений. Однако, оставлять на продуктовой среде включённый Xdebug — это совсем нехорошо, особенно с опцией "xdebug.discover_client_host = true". Если уж так хочется дебажить удалённо: не используйте эту опцию, указывайте конкретный IP адрес разработчика.
В крайнем случае всегда можно настроить Firewall на исходящие соединения на порт дебага. Указать там статический список адресов разработчиков.
Если у PHP разработчика нет прямого IP адреса, то можно сделать SSH-туннель к удалённому серверу.
ssh -R 9000:localhost:9000 <username>@<host> -p <port>
Но лучше всё-таки не использовать дебаг на боевом проекте.