RCE via PHP with WAF bypass
@cherepawwkaВсем привет!
Сегодня мы решим таск средней сложности "Обходной путь" с платформы CodeBy Games, получив RCE из уязвимого PHP скрипта, осуществляющего некоторую проверку входных данных.

Описание задания приведено ниже на скриншоте:

Что же, приступим!
Поиск уязвимости
Перейдем по предложенному URL (http://62.173.140.174:16019/):

Нас встречает форма ввода, где сразу же показан пример рабочей нагрузки. При вводе строки echo 'hello'; на экране появится слово "hello":

Вероятнее всего, перед нами PHP (echo, точка с запятой после команды). Следовательно, нужно попытаться эксплуатировать это знание. Из описания и тэга title мы понимаем, что приложение реализует какие-то методы защиты (скорее всего "кастомный WAF", фильтрующий некоторые входные данные). Зная, что в PHP могут быть отключены некоторые функции (об этом я писал в своей прошлой статье), тут может использоваться схожий механизм защиты. В первую очередь попробуем собрать информацию и вручную пофаззить приложение, чтобы понять, что именно и как фильтруется.
Для начала на дурака попробуем исполнить какой-нибудь код. Гуглим, получаем информацию о том, как это возможно сделать:

Пробуем:


Не прокатило. Оно и неудивительно, иначе бы всё было слишком просто.
В PHP есть замечательная функция phpinfo(), позволяющая получить максимум информации о конфигурации PHP на сервере. Попробуем внедрить её:


Отлично! В первую очередь узнаем имя скрипта:

и также посмотрим информацию в поле disable_functions:

Отлично, здесь опасные функции не отключены, следовательно, они фильтруются. Раз мы знаем имя скрипта, попробуем получить его содержимое. Сделать это можно следующим образом:

Попробуем осуществить этот запрос:


Посмотрим его в Burp Proxy:


Бинго! Теперь мы знаем, как именно фильтруется вводимое нами содержимое. Мы видим, что запрещённый контент перечислен в массиве $bad_words:
$bad_words = array('system', 'exec', 'passthru', 'shell_exec', 'ls', 'wget', 'nc', 'passwd');
Вводимый же код исполняется благодаря функции eval():
<?php if (isset($code)) echo eval($code); ?>
Обладая этими знаниями, начнем байпассить фильтры, чтобы получить RCE!
Эксплуатация
Да, конечно, фильтруется немало полезных слов и функций. Однако, это далеко не полный список, и у нас остаётся козырь в кармане. Ранее в своих статьях я уже говорил о способах исполнения команд ОС из скриптов. Один из таких методов — использование символов `.
Так, запрос echo `whoami`; должен вернуть нам имя пользователя, под которым работает веб-приложение. Попробуем внедрить код таким образом:


Отлично, мы обошли обнаруженные фильтры и исполнили код на стороне сервера. Осталось лишь погулять по файловой системе и получить флаг. Но команда ls нам недоступна, так как она фильтруется. Казалось бы, придётся снова фаззить... Но нет, есть способ обойти это ограничение. Фильтруется именно вхождение символов ls, но это обходится благодаря добавлению слэша — l\s:
Возьмем прошлый запрос с whoami из истории Burp Proxy, поместим его в Repeater и начнем инжектить код:

Мы получили содержимое каталога, но флага тут нет. Поищем дальше. Вспомним, что таск называется "Обходной путь", следовательно, попробуем погулять по директориям:

Находим интересный файл .secret, доступный на чтение всем пользователям. Прочитаем его содержимое (можно двумя способами: echo `cat ../.secret`; и readfile('../.secret');). Я покажу оба.
Запрос через функцию readfile():


Запрос через command injection:

Получаем заветный флаг и 350 очков в копилку!
CODEBY{3val_f1lt3rs_bypa$s3d}
На этом разбор подошёл к концу. Уверен, что это не единственный способ обхода фильтров и решения задания, так что любое другое решение только приветствуется.
До новых встреч!
