История одного веб-сервиса: как забытые ресурсы могут стать дверью во внутреннюю сеть

Недавно мы рассказывали об успешном участии экспертов УЦСБ в премии для специалистов по тестированию на проникновение Pentest Award и обещали вернуться с детальным описанием интересных кейсов, с которыми участвовали наши пентестеры.

В этой статье поделимся, как у одного из наших заказчиков пентестеры вовремя обнаружили уязвимость, которую потенциальные злоумышленники могли использовать для закрепления во внутренней корпоративной сети.

На примере этого кейса вы сможете узнать о новых векторах атак, оценить риски для своей инфраструктуры и найти советы, как устранить подобные уязвимости и повысить уровень защищенности.

Разведка

В одном из наших проектов мы проводили разведку по скоупу в несколько тысяч IP-адресов.

Одной из задач разведки был сбор старых или забытых доменных имен с помощью техники Passive DNS.

Passive DNS — набор записей, содержащих результаты разрешения DNS для доменов в соответствующие IP-адреса.

Одним из сервисов, предоставляющих доступ к данным Passive DNS, является VirusTotal. Написав небольшой скрипт, который отправляет запросы к API VirusTotal, мы собрали довольно много интересных доменных имен.

Именно в результате сбора доменов с помощью Passive DNS и нашелся тот самый забытый веб-сервис, который впоследствии оказался уязвимым. Доменное имя этого сервиса было в прямом смысле пятиэтажным, условно назовем его так: web1.smth.smth.companyname.com.

Это был самописный сервис мониторинга некоторых других сервисов, на который, судя по логам, последний раз заходили около месяца назад. Доступ к нему мы получили с помощью учетных данных по умолчанию, создали отдельную учетную запись администратора для дальнейшего тестирования и, конечно же, оповестили отдел ИБ заказчика об обнаружении уязвимости.

На следующий день отдел ИБ закрыл уязвимый ресурс, хотя от заказчика в то же время был запрос на продолжение тестирования этого веб-приложения. Что ж, не беда — продолжаем изучать бескрайний внешний периметр.

Теперь один важный момент: перед тем как отдел ИБ отключил уязвимый сервис, мы спарсили все учетные данные пользователей, которые хранились в открытом виде прямо в разметке HTML. Естественно, среди них были и учетные записи администраторов.

Вот, например, как выглядел кусочек списка пользователей:

ce7033e76b1cdb39f4f5ebf6f3d37b7e.png

А вот как хранился пароль:

ee0ce080ec9294e1abc2fe578a5d2a71.png

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

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

Алиас — дополнительное имя, которое предоставляет пользователю доступ к контенту с основного домена без переадресации.

Поиск уязвимостей и недостатков

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

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

Функция OpenRowset в MS SQL может считывать данные из файла без их загрузки в целевую таблицу.

183f06120ff7341b76592d2cc6cff864.png8e879a5b994cb59cbe98733a2042f15c.png

Путь к RCE

Вечером того же дня  докрутили инъекцию до Out-Of-Band с помощью следующей полезной нагрузки:

a7855a92a1e56e4bf8301a61cb0712f1.png

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

ec535ced4b10a4f17bf5734a3abfcd0b.png

Для дальнейшего развития атаки было нужно решить две задачи:

—         получить права на использование функции xp_cmdshell,

—         обойти сетевые ограничения: весь TCP трафик отбрасывался, проходили только DNS запросы, использующие UDP.

С первым вопросом мы разобрались довольно быстро. С помощью базы данных master сконфигурировали использование xp_cmdshell, так как в нашем распоряжении была сервисная учетная запись sa, у которой по умолчанию есть права на запись в базу данных master. Получилось это с помощью классической полезной нагрузки: use master; sp_configure 'xp_cmdshell', '1'; RECONFIGURE.

871bac62294e07f122532ef40e4151e6.pngaac81b111fdd8e86a6693224465d0efe.png

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

2e8b6f1144e4b14c0eeff1048fe157a0.pngd63f010f93d35aaa23c5d0b9b3e0ccdd.png

Закрепление

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

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

Примерно так выглядела построчная передача файла:

a20a2b7d6f1796e77c854e9feb143000.png

А вот так мы декодируем файл DNS-клиента на стороне сервера:

2bbe38acd3c35ca078aaba4626be0537.pngd8b7bf7a63b5adafb732fe7ad06185c7.png

Сессия с помощью DNS shell получена. По совету наших инфраструктурщиков мы проверили сетевой доступ со скомпрометированной машины до DC и обнаружили, что взаимодействие по SMB разрешено:

80d9474614ab8b5ac21827d68cc78606.png

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

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

3464797ddf10bfcfbf12ed603a18b474.png

Заключение

Список уязвимостей в цепочке:

1.     Использование словарных паролей

2.     Небезопасное хранение паролей

3.     Error-based SQL-инъекция

4.     Включенная привилегия SeImpersonatePriveleges у сервисной учетной записи

Так выглядит полная схема «пробива» периметра:

953e7ebf156263d585527216c9e861d1.png

Какие уроки можно извлечь из этого кейса?

Прежде всего, нельзя допускать использования словарных паролей, поэтому нужно не только внедрять парольные политики, но и контролировать их соблюдение.

Также очевидно, что хранить пароли в незашифрованном виде, а тем более в разметке страницы — плохая идея. Кроме того, стоит помнить о необходимости использования параметризованных запросов во избежание возникновения возможностей для SQL-инъекций.

Наконец, последние звенья цепочки показывают, как важно отключать привилегии учетных записей, если они не являются необходимыми — в частности, такие привилегии, как SeImpersonate Privilege.

Автор: Семён Тумашев, специалист по анализу защищённости УЦСБ.

© Habrahabr.ru