ss0xffff
14.02.2024, 17:03
В этом посте хотел бы рассмотреть необычное решение, которое я нашел в процессе выполнения CTF таска "Соленый огурец" из веба на платформе Antichat.
https://forum.antichat.xyz/attachments/29110284/img_788b92d1dc.png
1. Открываем указанный iport в браузере и перед нами открывается простое веб приложение для создания заметок.
https://forum.antichat.xyz/attachments/29110284/1707910167614.png
2. В самом начале на странице с заданием можно было скачать исходники к этому приложению. После того как архив скачался, заглянем в app.py: видно что это приложение на фласке; стоит обратить внимание на маршрут "/add_none" - интересным моментом является то, что введенная заметка сериализируется (метод dumps) с помощью модуля pickle, затем кодировка base64 и потом сохраняется в куки с названием "notes". Для вывода заметки производятся обратные действия: из куки декодировка base64 и затем десериализация (метод loads).
https://forum.antichat.xyz/attachments/29110284/img_b1a46e8695.png
3. Таким образом можно предположить, что если "завернуть" нужные нам команды с помощью pickles, закодировав полученный результат с помощью base64, и передать их в кукис, то можно добиться удаленного выполенния кода. Далее пришлось полазить по Интернету в поисках каких-либо подсказок насчет данной ситуации. Во всех случаях, которые мне попались, люди переопределяли метод __reduce__() внутри какого-либо класса, вызывая выполнение системных команд. Справедливо было бы спросить почему именно этот метод. Почитав докуметацию к pickles, надеюсь, я правильно понял, что метод __reduce__() является частью протокола сериализации Python, который позволяет объектам определить специальную логику для их сериализации и десериализации; когда объект передается функции pickle.dump() или pickle.dumps(), модуль pickle проверяет, есть ли у объекта метод __reduce__(). Если такой метод определен, то вызывается __reduce__(), который должен вернуть кортеж из функции, класса или строки и аргументов, которые будут использоваться для создания объекта при его десериализации. В нашем случае, когда переопределяется метод __reduce__(), вызывается команда из терминала.
Для проверки я сделал тестовую программу которая сериализует класс Inject c методом __reduce__() (внутри c помощью subprocess.check_output, которая сохраняет stdout, попробуем вывести текущего пользователя):
https://forum.antichat.xyz/attachments/29110284/1707913014602.png
Запустим данный скрипт и получим закодированный в base64 сериализованный объект: "gASVLwAAAAAAAACMCnN1YnB......"
Скопируем вывод и всавим его прямо в кукис notes и обновим страницу:
https://forum.antichat.xyz/attachments/29110284/1707913226412.png
Получим такой вывод - похоже на посимаолный вывод ascii кодов в десятеричной с.к. Воспользовавшись таблицой ascii, можно легко сопоставить 114 - 'r', 111 - 'o', 116 - 't', 10 - это управляющий символ. То есть мы под root'ом. Таким образом мы достигли PoC. Можно двигаться дальше. Для удобства сделаем программу на python котороая будет переводить ascii коды в привычные нам символы:
https://forum.antichat.xyz/attachments/29110284/1707913553766.png
4. Теперь попробуем вывести все доступные файлы в текущей директории:
https://forum.antichat.xyz/attachments/29110284/1707913704020.png
Получаем наш новый кукис и вставляем его в Cookie Editor:
https://forum.antichat.xyz/attachments/29110284/1707913835613.png
Скопируем эти коды и декодируем их с помощью написанной ранее программы:
https://forum.antichat.xyz/attachments/29110284/1707913928951.png
Отлично, теперь аналогичным образом прочитаем файл с флагом:
https://forum.antichat.xyz/attachments/29110284/1707914009150.png
Результат:
https://forum.antichat.xyz/attachments/29110284/1707914453774.png
Декодируем:
https://forum.antichat.xyz/attachments/29110284/1707914591436.png
Готово, флаг найден.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Я сказал вначале, что решение необычное, потому что насколько я знаю это задание нужно было решать через реверс шелл (в интернете все передавли как пейлоад именно netcat reverse shell):
https://forum.antichat.xyz/attachments/29110284/1707914870292.png
Но если я правильно понимаю, для реверс шелла нужен белый ip (если мы не в одной локальной сети, конечно): ведь по сути это машина жертвы должна инициировать соединение, а атакующий - открыть определенный порт и слушать.
То есть самое главное, что я хотел спросить, что обычно делается если нужно начать реверс шелл: покупается в vps, проброс портов на роутере или может есть какие-то сервисы, чтобы разово принять такое соединение?
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Благодарю за внимание. Надеюсь получить ответ на вопрос выше. В ctf играх я недавно поэтому, если где что не так сказал - не судите строго.
https://forum.antichat.xyz/attachments/29110284/img_788b92d1dc.png
1. Открываем указанный iport в браузере и перед нами открывается простое веб приложение для создания заметок.
https://forum.antichat.xyz/attachments/29110284/1707910167614.png
2. В самом начале на странице с заданием можно было скачать исходники к этому приложению. После того как архив скачался, заглянем в app.py: видно что это приложение на фласке; стоит обратить внимание на маршрут "/add_none" - интересным моментом является то, что введенная заметка сериализируется (метод dumps) с помощью модуля pickle, затем кодировка base64 и потом сохраняется в куки с названием "notes". Для вывода заметки производятся обратные действия: из куки декодировка base64 и затем десериализация (метод loads).
https://forum.antichat.xyz/attachments/29110284/img_b1a46e8695.png
3. Таким образом можно предположить, что если "завернуть" нужные нам команды с помощью pickles, закодировав полученный результат с помощью base64, и передать их в кукис, то можно добиться удаленного выполенния кода. Далее пришлось полазить по Интернету в поисках каких-либо подсказок насчет данной ситуации. Во всех случаях, которые мне попались, люди переопределяли метод __reduce__() внутри какого-либо класса, вызывая выполнение системных команд. Справедливо было бы спросить почему именно этот метод. Почитав докуметацию к pickles, надеюсь, я правильно понял, что метод __reduce__() является частью протокола сериализации Python, который позволяет объектам определить специальную логику для их сериализации и десериализации; когда объект передается функции pickle.dump() или pickle.dumps(), модуль pickle проверяет, есть ли у объекта метод __reduce__(). Если такой метод определен, то вызывается __reduce__(), который должен вернуть кортеж из функции, класса или строки и аргументов, которые будут использоваться для создания объекта при его десериализации. В нашем случае, когда переопределяется метод __reduce__(), вызывается команда из терминала.
Для проверки я сделал тестовую программу которая сериализует класс Inject c методом __reduce__() (внутри c помощью subprocess.check_output, которая сохраняет stdout, попробуем вывести текущего пользователя):
https://forum.antichat.xyz/attachments/29110284/1707913014602.png
Запустим данный скрипт и получим закодированный в base64 сериализованный объект: "gASVLwAAAAAAAACMCnN1YnB......"
Скопируем вывод и всавим его прямо в кукис notes и обновим страницу:
https://forum.antichat.xyz/attachments/29110284/1707913226412.png
Получим такой вывод - похоже на посимаолный вывод ascii кодов в десятеричной с.к. Воспользовавшись таблицой ascii, можно легко сопоставить 114 - 'r', 111 - 'o', 116 - 't', 10 - это управляющий символ. То есть мы под root'ом. Таким образом мы достигли PoC. Можно двигаться дальше. Для удобства сделаем программу на python котороая будет переводить ascii коды в привычные нам символы:
https://forum.antichat.xyz/attachments/29110284/1707913553766.png
4. Теперь попробуем вывести все доступные файлы в текущей директории:
https://forum.antichat.xyz/attachments/29110284/1707913704020.png
Получаем наш новый кукис и вставляем его в Cookie Editor:
https://forum.antichat.xyz/attachments/29110284/1707913835613.png
Скопируем эти коды и декодируем их с помощью написанной ранее программы:
https://forum.antichat.xyz/attachments/29110284/1707913928951.png
Отлично, теперь аналогичным образом прочитаем файл с флагом:
https://forum.antichat.xyz/attachments/29110284/1707914009150.png
Результат:
https://forum.antichat.xyz/attachments/29110284/1707914453774.png
Декодируем:
https://forum.antichat.xyz/attachments/29110284/1707914591436.png
Готово, флаг найден.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Я сказал вначале, что решение необычное, потому что насколько я знаю это задание нужно было решать через реверс шелл (в интернете все передавли как пейлоад именно netcat reverse shell):
https://forum.antichat.xyz/attachments/29110284/1707914870292.png
Но если я правильно понимаю, для реверс шелла нужен белый ip (если мы не в одной локальной сети, конечно): ведь по сути это машина жертвы должна инициировать соединение, а атакующий - открыть определенный порт и слушать.
То есть самое главное, что я хотел спросить, что обычно делается если нужно начать реверс шелл: покупается в vps, проброс портов на роутере или может есть какие-то сервисы, чтобы разово принять такое соединение?
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Благодарю за внимание. Надеюсь получить ответ на вопрос выше. В ctf играх я недавно поэтому, если где что не так сказал - не судите строго.