Как мы нашли самодельный веб-сервис, давший дорогу внутрь сети

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Как‑то раз мы проводили разведку по пулу из ~9000 IP-адресов крупной российской IT-компании и нашли заброшенный домен и работающий на нем сервис. Он оказался уязвимым, и вскоре мы смогли захватить веб‑сервер и проникнуть во внутреннюю сеть предприятия. Как это было сделано, я расскажу в этой статье.

Для поиска старых и забытых ресурсов мы использовали технику Passive DNS. Данные мы взяли из VirusTotal: написали небольшой скрипт, который отправлял запросы к API с IP-адресами из нашего пула. Это позволило собрать множество интересных доменов, большинство из которых входили в наш скоуп. Так и нашелся тот самый «забытый» веб‑сервис, который впоследствии оказался уязвимым.

Домен был непростой, что‑то вроде web1.smth.smth.companyname.com. Там был развернут самописный сервис мониторинга веб‑приложений, на который, судя по логам, последний раз заходили около месяца назад. Доступ к нему мы получили с помощью дефолтных учетных данных (admin:admin), создали отдельную учетку администратора для дальнейшего тестирования и, конечно же, как настоящие этичные хакеры, оповестили отдел ИБ заказчика об уязвимости.

На следующий день ИБ‑отдел закрыл ресурс, хотя мы просили дать возможность продолжать тестирование. Ребята из отдела ИБ объяснили решение тем, что «там нет ничего интересного».

Однако я опустил один момент: перед тем как сообщать об уязвимости, мы спарсили все учетные данные пользователей (для проектных целей и дальнейшего тестирования), которые хранились в открытом виде прямо в разметке HTML. Естественно, среди них были и учетки администраторов.
Кусочек списка пользователей



Пароль


оль
Полученные учетки мы применили на других ресурсах компании, половина пользователей действительно существовала, но пароли давным‑давно сменены.

Спустя две недели работы над остальным скоупом я параллельно занимался разведкой и работой с вебом. В какой‑то момент я взял наш прошлый хост — *.smth.smth.companyname.com, закинул на перебор в gobuster и... вуаля! Нашелся тот же самый ресурс, но уже с другим алиасом — пусть он будет называться vulnerable.smth.smth.companyname.com.

Здесь уже не было дефолтных учетных данных админа, как раньше, поэтому нам и пригодилась учетка администратора из дампа ресурса web1.smth.smth.companyname.com.

Получаем доступ, ковыряем приложение и находим возможности для самых разных SQL-инъекций. Нам удалось реализовать error-based SQLi, blind (time-based) SQLi, а также мы могли читать локальные файлы с помощью встроенной функции MS SQL — OpenRowset (она позволяет обращаться к локальным файлам).
image3.png



image4.png



image5.png



Это было вечером, а к поздней ночи я докрутил инъекцию в MS SQL до Out-of-Band.
Полезная нагрузка для эксплуатации OOB



В принципе, ничего сверхъестественного: в одну строчку назначаем произвольную переменную, присваиваем переменной hostname удаленного сервера, с помощью функции exec отправляем на исполнение. Пришлось немного пошаманить с hostname, скорее всего, WAF блокировал запросы к **.oastify.com. Но с помощью нехитрых манипуляций — разделения FQDN на части и конкатенации строк — мне удалось получить отстук на удаленный сервер.
image7.png



Но из‑за этого возникло несколько проблем:
  • нужно было каким‑то образом дать права на использование функции xp_cmdshell (RCE by design);
  • весь TCP-трафик урезался, и приходили только DNS-запросы, которые, соответственно, используют UDP.
В целом с первым вопросом мы разобрались довольно быстро: с помощью БД master перенастроили использование xp_cmdshell (насколько помню, у нас была сервисная учетка sa, у которой по дефолту есть права для использования БД master):
Код: Скопировать в буфер обмена
use master; sp_configure 'xp_cmdshell', '1'; RECONFIGURE
image8.png




image9.png



Реконфиг прошел успешно, теперь мы можем удаленно исполнять код.
image10.png



image11.png

1

Теперь осталось решить вопрос с получением сессии и закреплением. Динамический реверс‑шелл, к сожалению, получить не удалось из‑за отсутствия обратной связи по TCP. Поэтому мы обратились за помощью к нашему небезызвестному коллеге и товарищу s0i37. Очень пригодилась его статья про способы передачи файлов через DNS, а также сами клиент и сервер для DNS-шелла.

Осталось понять, каким образом мы можем передать VBS-клиент на веб‑сервер. Поразмыслив, мы нашли только один вариант — закодировать скрипт в Base64 и построчно передать в файл через Burp Intruder, а потом с помощью certutil декодировать файл и получить рабочий DNS-клиент.
Построчная передача файла



Декодируем клиент DNS на сервере



Фрагмент декодированного клиента



Мы получили сессию с помощью DNS-шелла и по наводке наших инфраструктурщиков проверили сетевой доступ со скомпрометированной машины до дата‑центра. Взаимодействие по SMB открыто.
image15.png


Дело за малым — осталось локально повысить привилегии и передать машину коллегам — специалистам по тестированию внутренней инфраструктуры.

В локальном повышении нам поможет включенная SeImpersonatePrivilege. Берем эксплоит из семейства «картошек» или PrintSpoofer, повышаем привилегии и передаем машинку коллегам.
image16.png



Полная схема пробива веб-приложения


Выводы​

Вот как в итоге выглядит цепочка уязвимостей:
  1. Использование словарных паролей.
  2. Небезопасное хранение паролей.
  3. Error-based SQL-инъекция.
  4. Включенная привилегия SeImpersonatePrivilege у сервисной учетной записи.
Заказчику мы выдали следующие рекомендации:
  • Настроить парольную политику. Например, использовать сгенерированные случайным образом пароли, состоящие из 12 или более символов и содержащие цифры, буквы разных регистров и спецсимволы.
  • Отказаться от хранения паролей сотрудников в разметке HTML, использовать менеджеры паролей.
  • Использовать параметризованные запросы к СУБД и экранировать пользовательский ввод данных.
  • Отключить привилегию SeImpersonatePrivilege у сервисных учетных записей.
Автор @cucurucuq
 
Сверху Снизу