Weak Pass Detector – запрет на использование утекших паролей в контроллере домена
Всем привет! Меня зовут Иван Нагорнов, я руководитель направления в Лаборатории кибербезопасности Сбербанка. В данной статье будет сделан обзор и предложение к использованию одной из наших разработок, которая направлена на минимизацию использования утекших паролей из открытых источников в контроллере домена. Мы уверены, что данная идея и ее реализация будут полезны для ИБ сообщества.
Прежде чем перейти к теме публикации, добавлю несколько слов о нашем подразделении. Лаборатория кибербезопасности Сбербанка — исследовательский коллектив экспертов, инженеров и ученых-исследователей в области информационной безопасности, объединенных общей целью — защитить людей и компании от широкого спектра новых и появляющихся киберугроз. Наша команда постоянно отслеживает и анализирует тенденции кибербезопасности и изменения в технологическом ландшафте, обнаруживая и прогнозируя новые угрозы. Мы разрабатываем методы нейтрализации или смягчения этих угроз. Наши исследователи и инженеры стремятся создать технологические решения проблем на самых ранних стадиях, прежде чем они станут масштабными и затронут многих.
Наблюдая за тенденцией развития различных средств обнаружения и противодействия злоумышленникам, с 2018 года и по текущий момент мы видим существенный рост количества решений по мониторингу и защите корпоративного ландшафта на основе Active Directory (далее - AD). Например, появление таких продуктов, как «Bloodhound Enterprise», «Tenable.ad», «Azure Password Protection» и других коммерческих решений свидетельствует о том, что интерес и потребность со стороны организаций в этом направлении неуклонно растёт. Растёт и внимание злоумышленников вместе с количеством обнаруженных уязвимостей, ведь AD является центральной системой, объединяющей различные объекты сети. Практически каждый год не обходится без раскрытия серьезных уязвимостей или нового вектора расширения привилегий до уровня администратора домена в компонентах службы каталогов или смежных системах.
Исходя из своего личного опыта, я могу сказать, что такое внимание связано не только с повышением уровня рисков вокруг AD, но и c повышением уровня зрелости самих функций ИБ. На текущий момент кроме мониторинга важных объектов ИТ инфраструктуры и реагирования (SOC) необходим еще и более глубокий, специфический мониторинг критичных систем, таких как MS AD, систем автоматизации процессов и учета SAP/1С, производственных систем ICS.
Также необходима реализация превентивных (автоматизированных) контролей безопасности там, где это возможно. Это позволяет быстро и надежно защитить ту или иную область системы. Однако, с течением времени нужно регулярно убеждаться в том, что контроль остается эффективным, и доступных вариантов обхода не появилось. Примерами реализации таких превентивных контролей может выступать настройка требований парольной политики, запрет (блокировка) на использование учетных записей сотрудников, находящихся в длительном отпуске (например, в декретном), запрет на интерактивный вход на компьютер/сервер под локальными учетными записями. Можно перечислить и многие другие методы, и приемы, но все они будут направленны на компенсирование или существенное снижение уровня риска ИБ при использовании той или иной системы.
Одним из таких контролей и будет являться наша разработка с рабочим названием «Weak Pass Detector» (далее – WPD), о которой и будет данная статья.
Предпосылки для реализации и появление идеи
Для понимания проблематики и необходимости реализации решения я предлагаю рассмотреть следующие примеры техник из реальных проектов по тестированию защищенности корпоративной инфраструктуры с точки зрения злоумышленника, который уже находится внутри сети. Для простоты восприятия будем изъясняться в техниках матрицы MITRE ATT&CK Enterprise.
Пример 1. При реализации проектов по тестированию защищенности одной из целей является компрометация контроллера домена, захват которого будет означать получение контроля над значительной частью ИТ инфраструктуры. На начальных этапах после выгрузки всех пользователей можно использовать атаку типа «Password Spraying». Данная техника входит в раздел «Credential Access» матрицы MITRE ATT&CK Enterprise и реализуется путем подбора ученой записи к простому паролю, который обычно соответствует парольной политике, например «QAZwsx123!» или «Winter2021!». Целью атаки является получение одной или нескольких валидных учетных записей для продвижения внутрь домена.
Пример 2. В рамках продвижения внутри домена, после компрометации какого-либо хоста, необходимо получить пароль учетной записи из хеша в текстовом виде (после реализации «OS Credential Dumping»), так как механизм «Pass the Hash» не применим для аутентификации в большинстве сторонних приложений. Для быстроты подбора пароля наряду со специализированным ПО и аппаратными устройствами (GPU) используются собранные или специально модифицированные словари паролей, и ни для кого не секрет что в этой комбинации (GPU + Словарь) большая часть успеха будет зависеть от словаря.
При анализе подобранных паролей и учетных записей частично реализуется другая техника «Credential Stuffing»- только злоумышленник не пытается сразу проверить утекшие пароли на каком-либо сервисе, пароли просто используются как база для эффективного подбора. Основу широко используемых словарей, например, «weakpass» или «Probable-Wordlists» составляют как раз утекшие и подобранные пароли, которые отсортированы по популярности.
Подводя итог возможных атак на контроллер домена или на пользовательские учетные записи, можно определить, что успешность сценариев напрямую зависит от сложности используемого пароля или от его присутствия в публичных утечках, содержимое которых рано или поздно попадет в обновленный словарь. Такой недостаток, как «Password Reuse» по-прежнему остается весомой проблемой безопасности, для борьбы с которой существует не так уж много инструментов ввиду приватности паролей и невозможности их легального извлечения из множества сервисов для последующих проверок. Значимая часть пользователей до сих пор держат в уме свои «любимые» и как им кажется безопасные пароли, которые используются ими как на внешних ресурсах, так и внутри корпоративной инфраструктуры. В подтверждение этих данных могу привести ссылку на исследование «Empirical Analysis of User Passwords across Online Services» Политехнического университета Виргинии, согласно которому более 70% пользователей по-прежнему продолжают использовать утекшие пароли в других сервисах в течение одного года. К тому же, более 40% этих пользователей используют пароли, которые утекли более трех лет назад. Таким образом эта угроза существует постоянно и стойкость пароля может являться последним рубежом безопасности всей системы. Конечно, реализация двухфакторной аутентификации позволит снизить этот риск, однако, много ли вам встречалось компаний, у которых реализовано два и более факторов для пользовательского сегмента корпоративной сети?
На мой взгляд иллюстрация ниже демонстрирует сложность задачи по контролю за повторным использованием паролей.
Хотелось бы также рассказать о появлении идеи c проверкой паролей на внешнем сервисе. В большей степени это связано с использованием возможности расширения процесса смены пароля. Опять же в хорошо знакомой вам матрице MITRE ATT&CK Enterprise есть интересная техника «Modify Authentication Process: Password Filter DLL» при реализации которой злоумышленник может получить пароли пользователей в открытом виде, то есть без необходимости подбора пароля к хешу. Эта техника выполняется после компрометации контроллера домена с помощью модификации процесса аутентификации через активацию динамически подключаемой библиотеки Password Filter. Если говорить точнее, то это изменение или расширение процесса смены пароля, однако, в матрице эта техника находится в разделе модификации процесса аутентификации. По факту происходит следующее: при изменении пароля учетной записи новый пароль попадает на контроллер домена для проверки требованиям парольной политики и в случае успешной смены новый пароль будет сохранен локально (на контроллере домена), например, записан в текстовый файл. Функционал Password Filter DLL является стандартным расширением функции фильтрации пароля от Microsoft, который и будет использован как ключевой элемент при реализации нашей идеи. Для понимания — это не какой-то новый инструмент и не «rocket science», это то, что присутствует в стандартной функциональности контроллера домена уже много лет. В открытом доступе также есть ряд разработок, дающих возможность проверки пароля по словарю, но мы не нашли ни одной разработки, которая бы использовала внешнюю базу данных (далее – БД) или реализовала бы достойную отказоустойчивость сервиса в целом.
Исходя из вышеизложенного можно сказать, что реализация WPD обусловлена необходимостью контроля за паролями, которые устанавливают пользователи и разрешением установки только тех паролей, которые отсутствуют в словаре запрещенных. Контроль обеспечивается в превентивной мере, а именно – анализ пароля происходит при его установке в дополнение к корпоративным требованиям парольной политики. Внедрение и использование данного решения позволяет за определенный срок (цикл смены пароля у всех пользователей) избавиться от «слабых» паролей». Под «слабыми паролями» подразумеваются те, которые удовлетворяют парольной политике, но являются скомпрометированными в результате утечек из сторонних сервисов.
Описание решения
На текущий момент решение представляет собой 3 компонента:
OpenPasswordFilter.dll – библиотека фильтрации паролей для расширения процесса lsass.exe и перехвата вызовов при смене пароля.
OPFService.exe – сервис для осуществления POST-запроса на REST API сервера БД.
Apache Ignite DBMS – БД с таблицей запрещенных паролей и REST API сервисом для приема запросов.
Согласно статье Microsoft, процесс смены пароля представляет собой следующий порядок действий:
Local Security Authority (LSA) инициирует вызов фильтров, зарегистрированных в системе.
Каждый фильтр паролей вызывается дважды: сначала проверяется новый пароль, а затем после проверки фильтрами нового пароля, чтобы уведомить о смене пароля.
Уведомление о смене пароля используется для синхронизации изменений паролей с БД внешней учетной записи.
Если пароль проходит внешний фильтр (на контроллере домена), то изменения вносятся в локальное хранилище (SAM).
Внедряя расширение для фильтрации паролей, мы добавляем несколько шагов в процесс, а именно:
Перехват пароля на контроллере домена.
Вызов во внешний сервис (БД) для проверки наличия пароля в режиме реального времени.
Таким образом итоговый процесс смены пароля после внедрения разработки выглядит следующим образом:
Технически на стороне контроллера домена это выглядит следующим образом. Активированная в реестре библиотека OpenPasswordFilter.dll передает устанавливаемый пароль на локальный сетевой интерфейс контроллера домена, прослушиваемый сервисом OPFService (C#). Сервис после получения пароля формирует запрос на REST API БД. Затем БД проверяет данный пароль на его наличие в таблице скомпрометированных паролей и возвращает положительный ответ, в случае если пароль найден, или отрицательный ответ в обратном случае. Сервис обрабатывает ответ от БД и передает результат в библиотеку для продолжения процесса смены пароля, если пароль не найден, и завершения процесса, если пароль присутствует в БД. В случае присутствия пароля в БД пользователь получит стандартное сообщение ОС Windows об недопустимости использования пароля по причине неудовлетворения требованиям парольной политики так как библиотека является расширением парольной политики сложности (complexity).
Использование БД Apache Ignite не является обязательным в этой схеме и может быть заменено на любую другую БД, однако, мы приняли решение использовать именно эту БД из-за ее типа «In-Memory», и как следствие возможности осуществлять проверку пароля практически мгновенно.
В текущей версии WPD реализована работа в так называемом «режиме аудита». Существует 2 варианта работы – журналирование (логирование) событий и блокировка.
Вариант 1 реализован для журналирования событий с попытками установки пароля из черного списка. В таком случае DLL не будет блокировать попытку установки, а администратор сможет убедиться, что все работает корректно.
Вариант 2 – для блокировки установки паролей при их наличии в БД. Переключать режимы работы можно с помощью параметров при активации DLL в реестре.
Мы старались реализовать WPD по принципу «Secure by Design». К предпринятым мерам безопасности и отказоустойчивости в архитектуре решения можно отнести следующее:
Отправка только POST запроса на API БД, которая исключает возможность попадания тела запроса в стандартный лог, как это происходит, например с запросом GET.
Шифрование запросов с помощью TLS.
Передача в запросе только пароля без идентификации УЗ, которой меняется пароль. Таким образом имя УЗ не покидает контроллер и неизвестно внешнему хосту с БД.
В DLL и сервисе заложены условия отказоустойчивости, которые позволяют в случае отказа какого-либо из трех компонентов (DLL, сервиса или БД) беспрепятственно установить пароль, который при этом проходит все остальные требования парольных политик. Для конечного пользователя этот процесс будет незаметным, однако, администратору не помешает иногда заглядывать в журнал событий или организовать регулярный «health check».
Журналирование событий по смене пароля в стандартный справочник «event log».
К дополнительным ограничениям, которые также можно реализовать:
Сетевое ограничение - настройка «жестких» маршрутов для доступа к БД для ее администрирования.
Сетевое ограничение - доступ к REST API БД только для сервисов с хостов, на которых расположены контроллеры домена.
Хеширование передаваемого пароля каким-нибудь легким алгоритмом (однако, это может увеличить нагрузку на сам контроллер и БД, так как в БД придется хранить уже хеш-сумму пароля, а это потребует большего объема оперативной памяти, так как хеш-сумма обычно длиннее, чем сам пароль).
Добавление аутентификационного токена в запрос к REST API (например, JWT).
Основные шаги в настройке
Для работы «In-Memory» БД Ignite необходима Oracle JDK или Open JDK версии 11, или выше. Windows Server2012+ / Linux – базовые версии ОС. Исходники WPD вы найдете в репозитории по ссылке. Исходный код распространяется под лицензией GNU GPL v.2.0.
Установка БД Apache Ignite:
Загрузите последнюю стабильную версию установочного архива, совместимую с вашей ОС.
Произведите установку приемлемым для вас способом согласно инструкции разработчика ПО, доступной по ссылке.
Для активации REST API Ignite, скопируйте папку «ignite-rest-http» из «/libs/optional» в «/libs». Как было описано ранее - OPFService.exe работает с БД Apache Ignite по REST API. Такая архитектура выбрана в том числе, чтобы избежать необходимости устанавливать JDK на контроллер домена, который необходим в случае использования клиента Ignite.
Запустите скрипт «bin/ignite.sh» для Unix, или «bin/ignite.bat» для Windows.
Вы должны увидеть в консоли что-то подобное:
[02:49:12] Ignite node started OK (id=ab5d18a6)<o:p></o:p>
[02:49:12] Topology snapshot [ver=1, nodes=1, CPUs=8, heap=1.0GB]<o:p></o:p>
По умолчанию, скрипт «ignite.sh/ignite.bat» запускает ноду БД с дефолтными настройками из конфигурационного файла «config/default-config.xml».
Возможно, вам может понадобиться изменить максимальный размер кеша для региона. Для этого, в файле конфигурации нужно изменить значение настройки «maxSize» в разделе «dataStorageConfiguration». По нашим примерным оценкам 100 миллионов строк паролей занимают ~10gb RAM в БД.
<!-- Memory configuration. -->
<property name="dataStorageConfiguration">
<bean class="org.apache.ignite.configuration.DataStorageConfiguration">
<property name="defaultDataRegionConfiguration">
<bean class="org.apache.ignite.configuration.DataRegionConfiguration">
<property name="name" value="Default_Region"/>
<property name="maxSize" value="#{15L * 1024 * 1024 * 1024}"/>
</bean>
</property>
</bean>
</property>
По умолчанию, REST API Apache Ignite работает без использования TLS. Для включения TLS, воспользуйтесь инструкцией Jetty.
Необходимо добавить сертификаты в keystore.
Внести изменения в файл конфигурации «/config/jetty-config.xml».
В БД Ignite пароли хранятся в виде словаря <Ключ, Значение>. Пример программы на C# для импорта паролей в БД:
private void ImportPass(Dictionary<string, string> passwords)
{
var cfg = new IgniteClientConfiguration
{
Endpoints = new[] { "127.0.0.1:10800" }
};
using (var ignite = Ignition.StartClient(cfg))
{
var cache = ignite.GetOrCreateCache<string, string>("my-cache");
cache.PutAll(passwords);
}
}
Пример вызова функции «ImportPass();» для импорта словаря:
Dictonary<string, string> passwords = new Dictonary<string, string>();
passwords.Add("p@ssw0rd", "p@ssw0rd");
ImportPass(passwords);
В БД Apache Ignite поиск осуществляется по ключу (в ключ сохранено значение пароля), в случае если БД находит такой ключ, то возвращает его значение (порядковый номер) и БД интерпретирует результат такого запроса как «True». В обратном случае – «False».
Документация по «In-Memory» БД Apache Ignite, которая также может быть полезна представлена в разделе «Ссылки» ниже.
Установка CSLab Password Filter на контроллерах домена:
Скопируйте файл «OpenPasswordFilter.dll» в «%WINDIR%\System32».
Зарегистрируйте библиотеку в реестре, для чего нужно изменить (или добавить, если не существует) ключ «Notification Packages» в разделе «HKLM\SYSTEM\CurrentControlSet\Control\Lsa», добавив в него название библиотеки без расширения.
После этого можно просто запустить бинарный файл «OPFService.exe», но лучше зарегистрировать его в системе как сервис с помощью следующей команды:
sc create OPF binPath="<полный путь к файлу></span>OPFService.exe"
После запуска сервиса будет создан новый журнал в разделе «EventLog\Applicatons and Services Logs\CSLab Password Filter», в котором по умолчанию будут регистрироваться только системные события фильтра.
Для изменения уровня логирования, режима работы и адреса сервера базы данных (если это необходимо), нужно создать новый раздел в реестре «HKLM\SOFTWARE\CSLab\PassFilter».
Возможные настройки:
В режиме аудита пропускаются все пароли, которые есть в базе данных, но в журнале будет создано событие о том, что пользователь поменял пароль на запрещенный (который есть в БД).
Нужно создать DWORD (32-bit) запись с именем «AuditMode», значения:
0 – режим аудита выключен, пароли из БД отклоняются (значение по умолчанию).
1 – режим аудита включен, пароли из БД пропускаются.
Для изменения уровня логирования нужно создать DWORD (32-bit) запись с именем LogLevel, значения:
0 – регистрируются только системные события (значение по умолчанию).
1 – регистрируются успешные и неуспешные попытки смены пароля «Event ID 9001 – Audit Success(если включен режим аудита) / Audit Failure».
2 – регистрируются успешные и неуспешные попытки смены пароля «Event ID 9001 – Audit Success (если включен режим аудита) / Audit Failure» в сообщение добавляется пароль, который пытались использовать.
Для изменения адреса сервера БД, нужно создать строковую запись с именем «DBAddress» и значением «<ServerAddress>:<Port>». Например, как представлено на снимке экрана ниже.
Важным моментом является подпись кода библиотеки DLL от Microsoft. Она необходима для работы с включенным механизмом «LSA Protection» на контроллерах домена. Соответственно, если механизм не используется, то и библиотека без подписи будет работать.
В случае если у вас происходит смена пароля аномально долго (12 секунд и более), то вероятно проблема в стандартных значениях политики и долгом разрешении имени (резолве) хоста с БД при использовании недоверенного сертификата. Попробуйте изучить данную статью.
Показатели тестирования
Тестирование WPD было произведено в синтетической среде, состоящей из одного контроллера домена (характеристики: Windows Server 2016/4 core/16gb RAM), одного хоста (характеристики: Windows 10/4 core/8gbRAM) с которого были осуществлены многочисленные смены пароля и БД Apache Ignite со словарем запрещенных паролей.
Для нагрузочного тестирования был разработан инструмент на С# с поддержкой параллельных потоков смены пароля, который позволял управлять количеством учетных записей для смены паролей и отображал временные показатели. Также было создано около десяти миллионов (10 мл.) пользователей в контроллере домена. Размер БД запрещенных паролей Apache Ignite в рамках тестирования был ограничен объемом в два миллиарда (2 млрд.) слов, что в свою очередь заняло порядка ~200gb RAM.
Для себя мы также определили, что приемлемое время смены пароля учетной записи для обычного пользователя контроллера домена не должно превышать трех секунд. В рамках тестирования мы использовали пароли, которые удовлетворяют парольной политике, но при этом отсутствуют (для успешной смены пароля) и присутствуют (для отказа в смене пароля) в базе данных запрещенных паролей. Таким образом мы избежали проведения нагрузочного теста для парольной политики.
Статистические показатели по результатам тестирования представлены в таблице ниже:
Как видно из таблицы, было реализовано четыре сценария. Первые два сценария – только с парольной политикой и отключенным фильтром, последние два сценария – с активированным фильтром в дополнение к политике. Как видно из показаний тестирования, смены пароля происходят быстрее с активированным фильтром! Невероятно, но это факт. Снимки с показателями последнего этапа тестирования из реальной системы прикрепляю ниже:
Заключение
Важнейшей частью всей разработки, которая напрямую будет влиять на эффективность, является правильно собранный словарь запрещенных паролей. Мы рекомендуем начать с известных словарей вроде «weakpass» и «hashes.org». Также будет уместным расширение словаря с помощью известных русских слов на английской раскладке, предварительно сгенерированных комбинаций, специфических для вашей организации – это может быть наименование, адрес, бренд и прочее. Сборку словаря следует производить с учетом актуальной парольной политики, чтобы не импортировать слова, которые будут отклонены по количеству символов или сложности. При попытке смены пароля они будут отбрасываться фильтром парольной политики, а место хранения в «In-Memory» БД должно использоваться максимально эффективно. Хорошей идеей также будет реорганизация хранилища запрещенных паролей по отдельным таблицам на основании первых символов пароля. Это позволит сделать процесс проверки и процесс импорта быстрее, так как исключит необходимость проверки импортируемого пароля по всему множеству в БД.
Согласно рекомендации Microsoft о том, что сценарий, при котором пароли покидают контур контроллера домена, является не очень позитивным, мы рекомендуем также рассмотреть возможность жестких сетевых ограничений для сервера с БД Apache Ignite.
Предоставленный в статье подход и исходный код стоит рассматривать в качестве прототипа, то есть без опыта использования на промышленной инфраструктуре. Пожалуйста, не забывайте про процесс внесения изменений и обязательно тестируйте итоговую конфигурацию, в случае если у вас появится желание адаптировать эту разработку в свой ландшафт. Помните, что только вы несете ответственность за ваши действия.
Стоит отметить, что данное решение не избавит ландшафт от всех возможных утекших паролей, так как это в принципе не представляется возможным. Ландшафт не сводится к одному лишь контроллеру домена и службам AD. Однако, по нашим оценкам, объем в миллиарды и десятки миллиардов слов позволяет создать надежный механизм проверки пароля при его установке и существенно продлевает время подбора пароля злоумышленником, в случае получения хеша. Как отмечалось ранее, эффективность решения будет напрямую связана с качеством словаря утекших паролей. Но нельзя заниматься бездумной генерацией всех возможных комбинаций символов и слов, всегда нужно помнить об ограниченном пространстве хранения. При наполнении словаря запрещенных паролей необходимо балансировать между количеством допустимых паролей и временем проверки. К тому же, после импорта слов необходимо регулярно убеждаться в том, что процесс смены пароля остается приемлемым для конечных пользователей.