Чтение хешей паролей любым пользователем и другие способы компрометации FreeIPA

от автора

Привет! Меня зовут Павел Козяев, я ведущий специалист по анализу киберугроз в BI.ZONE. Эта статья посвящена компрометации домена FreeIPA. Разберемся с событиями, которые полезны для мониторинга, и векторами компрометации домена, когда злоумышленник получает доступ к ключевым компонентам. Расскажу про привилегии, которые есть у группы admins и учетной записи admin, про уязвимость CVE-2024-3183 (FreeIPA Roasting), про возможности злоупотребления HBAC- и Sudo-правилами, а также риски, связанные с учетной записью Directory Manager. А еще увидим, как включение одного параметра при создании разрешения может открыть доступ ко всем пользовательским паролям. Бонус в конце статьи — набор правил детектирования для SOC.

Пара слов о FreeIPA

На всякий случай напомню, что FreeIPA — это решение для управления идентификацией, аутентификацией и авторизацией в Linux-окружении. Оно объединяет LDAP, Kerberos, DNS, управление сертификатами и политиками в единой системе. FreeIPA помогает централизованно управлять пользователями, группами и правами доступа, упрощая администрирование и повышая безопасность.

Компрометация домена FreeIPA дает злоумышленникам полный доступ к каталогу пользователей и их паролям, позволяет управлять Kerberos-билетами, контролировать правила Sudo и HBAC (доступ к хостам и привилегиям пользователей), а также может привести к компрометации других доменов (включая Windows).

Что мониторить

Мониторинг FreeIPA основывается на трех журналах:

  • /var/log/dirsrv/slapd-<$REALM>/access — события взаимодействия с каталогом LDAP;

  • /var/log/krb5kdc.log — события Kerberos (AS_REQ и TGS_REQ);

  • /var/log/httpd|apache2/error_log — события вызовов API FreeIPA.

Непосредственно LDAP-события разделяются на следующие типы:

  • Connection — cобытие подключения клиента к Directory Service, в котором содержатся номер соединения и IP-адрес клиента;

  • Bind — событие авторизации клиента на стороне сервера;

  • Request — тип LDAP-запроса (SRCH, MOD, DEL и т. д.);

  • Response — ответ сервера (Result, Entry).

Наибольший интерес для нас представляет журнал FreeIPA API Log, но он также является самым объемным.

FreeIPA предоставляет API, который управляет всем: от пользователей и групп до политик и хостов. Любое действие, которое выполняется через веб-интерфейс или CLI, в итоге идет через этот API. Все запросы сохраняются в журнале веб-сервера по пути /var/log/httpd|apache2/error_log. Однако в нем слишком много событий, относящихся к самому веб-серверу, поэтому необходимо четко определять собираемые события.

Доступно более 500 API-команд. С ними можно ознакомиться здесь или через веб-интерфейс в разделе «Навигатор API» вкладки IPA-Server.

Все названия API-команд можно разделить на две части: объект и действие с ним. Рассмотрим команду user_del — удалить пользователя, она разделяется на объект user и действие del:

admin@dc:~$ ipa user_del --help Usage: ipa [global-options] user-del LOGIN... [options]   Удалить пользователя.

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

Объект

Описание

group

Группа пользователей

user

Пользователь

host

Узел (сервер, рабочая станция)

hostgroup

Группа узлов

hbacrule

Правило HBAC (управляет доступом пользователей к узлам)

krbtpolicy

Политика билетов Kerberos (время жизни, параметры)

permission

Разрешение (минимальная единица контроля доступа)

privilege

Привилегия (набор разрешений)

role

Роль (набор привилегий, назначаемый пользователям)

sudocmd

Команда Sudo

sudocmdgroup

Группа команд Sudo

sudorule

Правило Sudo (кто, где и какие команды выполняет)

Мониторинг выполнения API-команд с этими объектами позволит выявлять double-meaning-активности (активности, которые может выполнить администратор или злоумышленник), мисконфигурации (слабые места в системе, позволяющие злоумышленникам скомпрометировать ее).

API позволяет выполнять множество действий с объектами, вот некоторые из них:

  • add — создание объекта;

  • del — удаление объекта;

  • find — поиск объекта;

  • mod — изменение объекта;

  • show — просмотр атрибутов объекта.

Также есть специфичные команды для некоторых конкретных объектов FreeIPA:

  • add_member/remove_member — добавление/удаление участника;

  • add_member_manager/remove_member_manager — добавление/удаление владельца группы;

  • enable/disable/unlock — включение/отключение/разблокировка объекта (пользователя или хоста);

  • add_host/remove_host — удаление/добавление целевого узла;

  • add_service/remove_service — добавление/удаление службы;

  • add_allow_command/add_deny_command — разрешающее/запрещающее правило для команды на хосте.

В данной статье остановимся только на отдельных примерах событий от API при разборе путей компрометации FreeIPA.

Компрометация домена FreeIPA

Для компрометации домена FreeIPA злоумышленнику необходимо соблюдение одного из следующих условий:

  • иметь root-права на сервере FreeIPA;

  • владеть паролем от учетной записи Directory Manager;

  • иметь возможность читать хеши паролей учетных записей в каталоге LDAP.

Становимся root на сервере FreeIPA

Возможностей получить привилегии root на сервере FreeIPA множество. Один из таких примеров компрометации домена FreeIPA привела команда SpecterOps. На векторе с поиском паролей в открытом виде и Kerberos-билетов на хосте в этой статье останавливаться не будем, как и на реализации CVE-2020-10747.

Из оставшихся путей получения административного (root) доступа к FreeIPA-серверу можно выделить несколько:

  • получение доступа к учетной записи из группы admins;

  • повышение привилегий при помощи изменения HBAC- и Sudo-правил;

  • эксплуатация какой-либо уязвимости.

Группа admins (aka Domain Admins) и пользователь admin

Во FreeIPA по умолчанию есть 4 группы пользователей.

Имя группы

Описание

admins

Account administrators group

editors

Limited admins who can edit other users

trust admins

Trusts administrators group

ipausers

Default group for all users

Группа admins во FreeIPA — особая встроенная группа, которая создается при установке. Ее права не зависят от членства в других группах или ролей — они заданы по умолчанию в системе FreeIPA. Пользователь admin — административный аккаунт, который также создается при установке (аналог Administrator в Active Directory).

В веб-интерфейсе или IPA CLI пользователь admin и все члены admins могут всё, но доступ к хостам и назначение привилегий управляются HBAC-/Sudo-правилами, о которых мы поговорим далее:

admin@dc:~$ ipa group_show admins --all --raw   dn: cn=admins,cn=groups,cn=accounts,dc=iparnd,dc=local   cn: admins   description: Account administrators group   gidnumber: 266200000   member: uid=admin,cn=users,cn=accounts,dc=iparnd,dc=local   member: uid=dima,cn=users,cn=accounts,dc=iparnd,dc=local   member: uid=demyan,cn=users,cn=accounts,dc=iparnd,dc=local   member: uid=yura,cn=users,cn=accounts,dc=iparnd,dc=local   member: uid=barbara,cn=users,cn=accounts,dc=iparnd,dc=local   ipaNTSecurityIdentifier: S-1-5-21-4221554819-882417855-2150854786-512   ipaUniqueID: 195797dc-f0da-11ee-8b0b-005056bd37bb   memberof: cn=Replication Administrators,cn=privileges,cn=pbac,dc=iparnd,dc=local   memberof: cn=Host Enrollment,cn=privileges,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Enroll a Host,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Add Configuration Sub-Entries,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Manage Host Principals,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Manage Host Keytab,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Modify DNA Range,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Read Replication Agreements,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Read DNA Range,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Modify Replication Agreements,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Remove Replication Agreements,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Manage Host Enrollment Password,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Add krbPrincipalName to a Host,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Write Replication Changelog Configuration,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Read LDBM Database Configuration,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Modify PassSync Managers Configuration,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Manage Host Certificates,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Read PassSync Managers Configuration,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Read Replication Changelog Configuration,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Add Replication Agreements,cn=permissions,cn=pbac,dc=iparnd,dc=local   objectClass: top   objectClass: groupofnames   objectClass: posixgroup   objectClass: ipausergroup   objectClass: ipaobject   objectClass: x-ald-audit-policy   objectClass: nestedGroup   objectClass: ipaNTGroupAttrs

Предположим, что атакующему каким-либо образом удалось получить доступ к учетной записи из группы admins и он может подключиться к серверу FreeIPA. При выполнении sudo -l он получает «User admin may run the following commands on dc: (ALL : ALL) NOPASSWD: ALL».

Какие следующие шаги для компрометации домена могут быть выполнены?

Известно, что на сервере FreeIPA работает Directory Server (LDAP-сервер, 389), который хранит всю информацию об объектах (пользователи, группы, политики и т. д.), а в их атрибутах хранится секретная информация:

  • ipaNTHash — атрибут, который содержит NT-хеш пароля пользователя для интеграции с AD;

  • userPassword — основной атрибут, в котором хранится хеш пароля пользователя, используемый для LDAP-аутентификации;

  • krbMKey — атрибут, содержащий главный ключ, которым зашифрованы ключи всех учетных записей в Kerberos;

  • krbPrincipalKey — атрибут, содержащий секретный ключ (или ключи) Kerberos principal (учетная запись), зашифрованный мастер-ключом krbMKey.

Компрометация домена происходит в результате получения доступа к двум файлам на LDAP-сервере:

  • /var/lib/dirsrv/slapd-<instance_name>/db/id2entry.db — основной файл базы данных LDAP, используется FreeIPA для хранения информации о пользователях, группах и других объектах. Он содержит информацию о каждом объекте в директории, включая атрибуты пользователей, групп и другие метаданные.

  • /etc/dirsrv/slapd-<instance_name>/dse.ldif — основной конфигурационный файл сервера базы данных LDAP, используется FreeIPA для хранения конфигурации и метаданных самого LDAP-сервера. В данном файле также содержится хеш пароля встроенной учетной записи Directory Manager.

Чтобы получить доступ к данным файла базы данных LDAP, можно воспользоваться установленным инструментом dbscan или другими самописными парсерами, так как файл бинарный и его нельзя читать напрямую:

dbscan -f /var/lib/dirsrv/slapd-<instance_name>/db/userRoot/id2entry.db >> /tmp/loot

 Получаем доступ к секретам каждого пользователя:

id 705         rdn: uid=dima         givenName: dima         sn: dima         uid: dima         cn: dima dima         displayName: dima dima         initials: dd         gecos: dima dima         krbPrincipalName: dima@IPARND.LOCAL         ...[redacted]...         loginShell: /bin/bash         homeDirectory: /home/dima         mail: dima@iparnd.local         ...[redacted]...         krbCanonicalName: dima@IPARND.LOCAL         userPassword:: e1BCS0RGMi1TSEE1MTJ9MTAwMDAkZDZrTWtueHBkdlE2N2E3eG5jTi8rR3IrSmw          1UWZWa1UkU2kzY0ZKZXBaRXJLN2xGR2ZGS3RXcmFsd1JzRXJCMFBCUXY3cTdiblRmT1MxZU5CWU1R          R1RZTjFENWdHOGZQTS9QSjVPLzBrZEZmTmRSUXErcVI0UXc9PQ==         creatorsName: uid=admin,cn=users,cn=accounts,dc=iparnd,dc=local         ...[redacted]...         parentid: 3         entryid: 705         krbPrincipalKey:: MIHeoAMCAQGhAwIBAaIDAgECowMCAQGkgccwgcQwaKAbMBmgAwIBBKESBBBR          byUsST8mVilYI1goIC4joUkwR6ADAgESoUAEPiAA/5SSvyP3BnoPO+oPCP8LmhJQQkRsaEoy5mFhi          AZ/sjrzeRHM23U1zveSc7K0EXVbLB8c6eX76Voj12jmMFigGzAZoAMCAQShEgQQRyk8KiYyNkc7YG          JGRV5RMaE5MDegAwIBEaEwBC4QAHUeeAxgqlYGPqX/s4M/3G3ZVha7t9/GkygCJlSneGrU4JJ0V+d          yZd4nETwL         ...[redacted]...         krbLastPwdChange: 20240806092223Z         krbExtraData:: AAJP67Fma2FkbWluZEBJUEFSTkQuTE9DQUwA         mepManagedEntry: cn=dima,cn=groups,cn=accounts,dc=iparnd,dc=local         ipaNTSecurityIdentifier: S-1-5-21-4221554819-882417855-2150854786-1016         memberOf: cn=admins,cn=groups,cn=accounts,dc=iparnd,dc=local         ...[redacted]...         krbTicketFlags: 128         krbLoginFailedCount: 1         krbPasswordExpiration: 20241104092223Z         ipaNTHash:: 3qwd8t2EU8bowS+LSVZRkQ==         passwordGraceUserTime: 0         krbLastFailedAuth: 20240807100542Z         dsEntryDN: uid=dima,cn=users,cn=accounts,dc=iparnd,dc=local

Важно отметить, что скомпрометированным будет и krbMKey, с помощью которого можно расшифровать krbPrincipalKey любого пользователя или сервиса.

Для компрометации домена FreeIPA также важно завладеть паролем учетной записи Directory Manager (о ней расскажем подробно ниже), хеш пароля хранится в атрибуте nsslapd-rootpw по пути /etc/dirsrv/slapd-IPARND-LOCAL/dse.ldif:

root@dc:/home/admin# cat /etc/dirsrv/slapd-IPARND-LOCAL/dse.ldif | grep -i "rootpw" nsslapd-rootpw: {PBKDF2-SHA512}10000$XeBA0KCCwA/SbqqmiNjL5P+2eRGkLVBs{redacted}

Let’s detect it

Важно мониторить подозрительные попытки чтения файла id2entry.db. Это можно делать при помощи BI.ZONE EDR или auditd.

Пример строчки для auditd:

-w /var/lib/dirsrv/slapd-$REALM/db/userRoot/id2entry.db -p rwa -k Access_id2entry

Lucene-запрос:

dev_os_type:linux AND event_type:FileOpenNix AND file_path:"id2entry.db" AND -proc_file_path:"/usr/sbin/ns-slapd"

Результат запроса:

Подозрительным также будет любое упоминание файла id2entry.db в командной строке выполняемого процесса:

dev_os_type:linux AND cmdline:"id2entry.db"

Находим, как атакующие забирают id2entry.db из контейнера на основной хост:

Или используют один из инструментов для получения учетных данных на Linux-хостах, например linikatz:

Что же касается файла dse.ldif, то также ищем подозрительные обращения к нему через командную строку:

dev_os_type:linux AND event_type:ProcessCreateNix AND ( proc_file_path:(     "cat" OR     "vi" OR     "nano" OR     "less" OR     "vim"  OR     "tail" OR     "more" OR     "head") OR     (proc_file_path:"grep" AND cmdline:"rootpw") ) AND cmdline:"dse.ldif"

И находим:

Представленные запросы имеют низкий FP-rate и могут легко использоваться как правила корреляции в SOC.

HBAC- и Sudo-правила

Теперь рассмотрим, как настроенные HBAC- и Sudo-правила могут помочь атакующему скомпрометировать домен FreeIPA.

HBAC (host-based access control) — набор правил для настройки доступа пользователей или групп пользователей к определенным хостам с использованием определенных сервисов. Например:

  • ограничение доступа по SSH к контроллеру домена определенной локации только для группы администраторов этой локации;

  • разрешение использовать только определенную службу для доступа определенным пользователям на определенных хостах.

При создании HBAC-правила определяются следующие параметры:

  • User — пользователи или группы, которые могут подключаться;

  • Host — узлы (хосты) или группы узлов, к которым можно подключиться;

  • Service — сервисы (например, sshd, login);

  • Source host — хосты-источники (откуда подключаются), опционально.

При установке FreeIPA создаются правила по умолчанию

  • allow_all — allow all users to access any host from any host.

  • allow_systemd-user — allow pam_systemd to run user@.service to create a system user session.

Разработчики рекомендуют отключать правило allow_all после настройки собственных HBAC-правил.

Sudo — набор правил, которые позволяют централизованно управлять тем, какие пользователи могут выполнять команды с привилегиями root (или других пользователей) на узлах.

FreeIPA позволяет настраивать правила разрешения и запрета на использование Sudo для пользователей и групп пользователей. В правилах могут задаваться:

  • User — пользователи/группы, которым разрешены привилегии;

  • Host — узлы или группы узлов, где это правило действует;

  • Command — команды (или группы команд), которые разрешены или запрещены;

  • RunAsUser — от имени какого пользователя можно запускать;

  • RunAsGroup — от имени какой группы можно запускать.

В клиентских системах FreeIPA Sudo-правила не хранятся локально в /etc/sudoers. Для проверки привилегий пользователя используется служба SSSD, которая обрабатывает информацию из LDAP-каталога сервера, кеширует в своей базе (/var/lib/sss/db/cache_<domain>.ldb) и возвращает список разрешенных Sudo-команд. HBAC-правила также кешируются службой SSSD из каталога LDAP и используются для разрешения пользователю доступа к узлу.

Рассмотрим, кто именно может управлять данными правилами.

Во FreeIPA существуют следующие разрешения, которые позволяют изменять HBAC- и Sudo-правила:

Данные разрешения входят в привилегии по умолчанию HBAC Administrator и Sudo Administrator, которые, в свою очередь, определены в роли IT Security Specialist. Отмечаем: если злоумышленник владеет учетной записью, к которой применяется роль IT Security Specialist, то он имеет возможность создать для себя разрешающие HBAC- и Sudo-правила для привилегированного доступа к серверу FreeIPA и скомпрометировать домен.

Пример такого пользователя:

admin@dc:~$ ipa user_show oleg --all --raw   dn: uid=oleg,cn=users,cn=accounts,dc=iparnd,dc=local   uid: oleg   givenname: oleg   sn: oleg   cn: oleg oleg   initials: oo   homedirectory: /home/oleg   gecos: oleg oleg   loginshell: /bin/bash   ...{redacted}...   memberof: cn=SuperRole,cn=roles,cn=accounts,dc=iparnd,dc=local   memberof: cn=IT Security Specialist,cn=roles,cn=accounts,dc=iparnd,dc=local   memberofindirect: cn=System: Add HBAC Rule,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Add Sudo rule,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Delete HBAC Rule,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Modify Netgroups,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Add Netgroups,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Add Sudo Command Group,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Sudo Administrator,cn=privileges,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=Netgroups Administrators,cn=privileges,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Manage HBAC Rule Membership,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Add HBAC Services,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Add Sudo Command,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Modify HBAC Rule,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Delete Sudo Command Group,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Manage HBAC Service Group Membership,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Delete HBAC Services,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Manage Sudo Command Group Membership,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Add HBAC Service Groups,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Remove Netgroups,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=HBAC Administrator,cn=privileges,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Delete Sudo Command,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Modify Netgroup Membership,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Modify Sudo Command Group,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Modify Sudo Command,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Modify Sudo rule,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Delete Sudo rule,cn=permissions,cn=pbac,dc=iparnd,dc=local   memberofindirect: cn=System: Delete HBAC Service Groups,cn=permissions,cn=pbac,dc=iparnd,dc=local   mepManagedEntry: cn=oleg,cn=groups,cn=accounts,dc=iparnd,dc=local   ...{redacted}...

Если у вас уже отключено HBAC-правило allow_all, то следует мониторить его включение, так как это может указывать не только на легитимные действия системного администратора, а на действия атакующего, направленные на расширение возможностей для горизонтального перемещения внутри организации, например для подключения по SSH к серверу FreeIPA или к другим критическим сегментам под непривилегированной учетной записью.

Пример события:

<190> May 30 15:14:55 dc [Fri May 30 15:14:55.457793 2025] [wsgi:error] [pid 28639] [remote 172.31.128.32:57661] ipa: INFO: admin@IPARND.LOCAL: batch: hbacrule_enable('allow_all'): SUCCESS

Let’s detect it

Ищем включение HBAC-правила allow_all:

dev_os_roles:"freeipa" AND event_id:"hbacrule_enable" AND obj_name:"allow_all"

Создание разрешающего Sudo-правила для запуска любых команд на любых узлах от имени root:

dev_os_roles:"freeipa" AND event_id:"sudorule_mod" AND prop_value_data_new:("usercategory='all'" AND "hostcategory='all'" AND "cmdcategory='all'" AND "ipasudorunasusercategory='all'")

Находим:

<190> Jun  2 11:28:12 dc [Mon Jun 02 11:28:12.237664 2025] [wsgi:error] [pid 32490] [remote 172.31.129.39:57009] ipa: INFO: [jsonserver_session] admin@IPARND.LOCAL: sudorule_mod('SUDO ALL ALLOW', usercategory='all', hostcategory='all', cmdcategory='all', ipasudorunasusercategory='all', ipasudorunasgroupcategory='all', rights=True, all=True, version='2.239'): SUCCESS

FreeIPA Roasting (CVE-2024-3183)

В июне 2024 года была опубликована информация об уязвимости CVE-2024-3183. Она позволяет атакующему с низкими привилегиями извлекать Kerberos-билеты (TGS) других пользователей и выполнять офлайн-брутфорс их паролей. Этот метод напоминает Kerberoasting, но применяется к пользовательским аккаунтам, а не к сервисным. В Kerberos запрос TGS-REQ шифруется сессионным ключом клиента, который уникален для каждой сессии. Однако сам билет (TGS) шифруется с использованием ключа целевого принципала (пользователя). Для пользовательских аккаунтов этот ключ формируется из пароля и уникальной соли.

Соль каждого пользователя можно узнать при попытке запросить TGT в режиме debug, так, в ответе KDC можно увидеть соответствующее значение соли:

Далее необходимо получить TGS для этого пользователя и выполнить брутфорс пароля.

Для эксплуатации уязвимости предлагается использовать модифицированные скрипты Impacket или встроенные команды IPA kinitkvno. Однако по следам данной CVE исследователь nu11z разработал дополнительную Python-библиотеку для взаимодействия с FreeIPA.

ipapocket — это Python-библиотека для взаимодействия с сетевыми протоколами FreeIPA. Она ориентирована на предоставление низкоуровневого программного доступа к протоколам через объектно ориентированный API. Библиотека позволяет взаимодействовать с Kerberos, в том числе создавать TGT, разбирать и анализировать пакеты из сырого сетевого трафика, взаимодействовать с компонентами FreeIPA без необходимости использовать готовые утилиты CLI. Также может использоваться для автоматизации процесса эксплуатации уязвимости CVE-2024-3183.

Ниже приведены интереcные утилиты из ipapocket:

  • ipp-cve-2024-3183.py — PoC для эксплуатации CVE-2024-3183 (FreeIPA Roasting). Позволяет извлекать TGS и формировать хеши для офлайн-брутфорса. Для хешей с шифрованием AES256-SHA1 (etype 18) используется форк hashcat с режимом -m 32900.

  • ipp-id2entry.py — разбор содержимого базы id2entry.db после выполнения dbscan -f. Позволяет дешифровать ключи пользователей (Kerberos principals), пригодные для создания тикетов (TGT/TGS вручную).

  • ipp-get-tgt.py — получение TGT (AS-REP) и сохранение его в CCACHE.

  • ipp-get-tgt-spake.py — получение TGT с использованием механизма SPAKE (Kerberos pre-auth hardening). Сохраняет TGT в CCACHE.

  • ipp-get-tgs.py — запрос TGS (служебный билет) по уже полученному TGT (т. е. из переменной окружения KRB5CCNAME). Сохраняет результат в CCACHE.

  • ipp-user-enum.py — перебор (энумерация) пользователей через Kerberos по поведению KDC (успешный/неуспешный ответ).

  • ipp-show-ccache.py — просмотр и расшифровка содержимого Kerberos CCACHE, отображает тикеты, сроки действия, типы шифрования и пр.

Let’s detect it

Если атакующий решит узнать соль нескольких пользователей, то можно определить такую активность по множеству неудачных AS_REQ-запросов для разных пользователей:

<190> Jun  3 16:52:17 dc июн 03 16:52:16 dc.iparnd.local krb5kdc[9014](info): AS_REQ (8 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19), DEPRECATED:des3-cbc-sha1(16), DEPRECATED:arcfour-hmac(23), camellia128-cts-cmac(25), camellia256-cts-cmac(26)}) 10.3.132.205: PREAUTH_FAILED: admin@IPARND.LOCAL for krbtgt/IPARND.LOCAL@IPARND.LOCAL, Preauthentication failed

Псевдокод правила корреляции:

dev_os_roles:"freeipa" AND event_id:" AS_REQ" AND event_result: "PREAUTH_FAILED"   event[5, ] with different usr_tgt_fullname timer 5m

Получается, что правило на password spraying по протоколу Kerberos может выявлять и подготовку к эксплуатации уязвимости CVE-2024-3183.

Попытка запроса TGS для admin с использованием команд IPA на хосте также будет являться аномалией:

dev_os_type:"linux" AND event_type:"ProcessCreateNix" AND cmdline:("kinit -S" OR "kvno") AND cmdline:("admin" OR "root")

Находим подозрительную активность:

Во FreeIPA не существует пользователя root, он является только псевдонимом для учетной записи admin.

Аналогично и попытка узнать значение соли из debug-режима запроса AS_REQ будет считаться подозрительной и аномальной для системы FreeIPA:

dev_os_type:"linux" AND cmdline:"kinit" AND cmdline:("admin" OR "root") AND cmdline:("grep salt" OR "KRB5_TRACE=/dev/stdout")

Находим подозрительную активность:

Также появление утилит ipapocket на хосте можно отслеживать следующим запросом:

dev_os_type:unix AND ( cmdline:("ipp-cve-2024-3183.py" "ipp-get-tgt.py" "ipp-user-enum.py" "ipp-get-tgs.py" "ipp-id2entry.py" "ipp-get-tgt-spake.py" "ipp-show-ccache.py" "ipapocket") OR proc_file_path:("ipp-cve-2024-3183.py" "ipp-get-tgt.py" "ipp-user-enum.py" "ipp-get-tgs.py" "ipp-id2entry.py" "ipp-get-tgt-spake.py" "ipp-show-ccache.py" "ipapocket") OR proc_p_file_path:("ipp-cve-2024-3183.py" "ipp-get-tgt.py" "ipp-user-enum.py" "ipp-get-tgs.py" "ipp-id2entry.py" "ipp-get-tgt-spake.py" "ipp-show-ccache.py" "ipapocket") )

В результате находим:

Directory Manager — контроль над LDAP

Ранее мы упоминали учетную запись Directory Manager. Это специальная системная учетная запись, которая используется для управления сервером FreeIPA и его компонентами. Она имеет полные права на все объекты в каталоге LDAP и является самой привилегированной учетной записью в системе FreeIPA. Для нее нельзя запросить билет Kerberos, а ее пароль задается при установке FreeIPA. Как ранее уже отмечали, ее хеш хранится по пути /etc/dirsrv/slapd-$REALM/dse.ldif.

Учетные данные пользователя Directory Manager злоумышленник может найти с помощью следующих методов:

  • поиск в содержимом скриптов автоматизации/интеграции;

  • поиск в истории вводимых команд (bash_history);

  • проверка на одинаковый пароль при установке для admin и Directory Manager;

  • брутфорс или password spraying через BIND LDAP.

Не рекомендуется использовать учетные данные Directory Manager в скриптах и при административных задачах, так как это может привести к компрометации всего домена FreeIPA.

Владея учетной записью Directory Manager, атакующий может выполнить удаленный дамп каталога LDAP в формате LDIF. Далее, используя, например, инструмент ldapsearch, он может получить доступ ко всем секретам объектов LDAP. Получается некий аналог атаки DCSync в AD:

ldapsearch -x -D "cn=Directory Manager" -w 'DontReadPassword!' -H ldap://dc.iparnd.local -b "dc=iparnd,dc=local" -LLL "objectclass=*" > freeipa_directory_dump.ldif

Для того чтобы отследить такие события, необходимо понимать, какие последовательности событий создают такое взаимодействие с LDAP-сервером. Все события в рамках одного взаимодействия объединяются по полю conn= (номер соединения):

<190> Jun  2 11:35:50 dc [02/Jun/2025:11:35:25.628772838 +0300] conn=1485349 fd=154 slot=154 connection from 10.3.132.205 to 10.3.132.207   <190> Jun  2 11:35:50 dc [02/Jun/2025:11:35:25.629183564 +0300] conn=1485349 op=0 BIND dn="cn=Directory Manager" method=128 version=3   <190> Jun  2 11:35:50 dc [02/Jun/2025:11:35:25.648517998 +0300] conn=1485349 op=1 SRCH base="dc=iparnd,dc=local" scope=2 filter="(objectClass=*)" attrs=ALL   <190> Jun  2 11:35:50 dc [02/Jun/2025:11:35:25.668187784 +0300] conn=1485349 op=1 RESULT err=0 tag=101 nentries=618 wtime=0.000131113 optime=0.019671069 etime=0.019796794 notes=U details="Partially Unindexed Filter"
  1. Из события connection определяем IP-адрес источника.

  2. Из события BIND определяем имя пользователя источника и тип аутентификации.

  3. Из события SRCH определяем тело запроса.

  4. Из события RESULT видим успешность запроса и количество возвращенных объектов.

Получаем доступ в текстовом виде ко всем секретам LDAP:

Let’s detect it

Для детектирования данной активности необходимо отслеживать следующие подозрительные события:

1. Подозрительное использование учетной записи Directory Manager. Так как использование данной учетной записи не рекомендовано для административных действий, то правило корреляции на любую попытку BIND-аутентификации по паролю (method=128) в каталоге LDAP FreeIPA с узла, не принадлежащему серверу FreeIPA, будет выявлять аномальную активность в инфраструктуре:

dev_os_roles:"freeipa" AND event_id:"BIND" AND usr_tgt_name:"Directory Manager" AND auth_type:"128"

Также в случае подбора пароля для учетной записи Directory Manager данное правило сработает в частном порядке.

2. LDAP-запрос, направленный на выгрузку большого количества объектов и их атрибутов, может быть аномальным в инфраструктуре и свидетельствовать о попытке дампа LDAP-структуры с целью изучения структуры домена:

dev_os_roles:"freeipa" AND event_id:"SRCH" AND ldap_dn.keyword:"^dc=.*" AND ldap_filter.keyword:"^.(object|user)\w+\=\S+" AND ldap_attrib_list:"ALL"

В событии BIND-аутентификации имя пользователя может быть пустым. Это связано с тем, что пользователем используется протокол Kerberos.

Если дамп LDAP выполняется не от имени учетной записи Directory Manager, а, например, от имени admin, то в выгрузке не будет содержаться чувствительная информация — такие атрибуты, как ipaNTHashuserPasswordkrbPrincipalKey и другие. Это связано с тем, что у Directory Manager больше привилегий в каталоге LDAP, чем у административной учетной записи admin по умолчанию. Таким образом, даже если LDAP-запрос выполнен успешно, по одному только факту его выполнения нельзя однозначно утверждать, какие именно атрибуты были получены. Если запрос выполнялся не от имени Directory Manager, высоковероятно, что хеши и ключи Kerberos пользователей не раскрыты. Это усложняет задачу атакующему: при корректной настройке и хранении секретов получить пароль от Directory Manager крайне сложно, что защищает домен от компрометации через прямой дамп LDAP.

А что, если, владея административными привилегиями в домене FreeIPA, иметь возможность создать разрешение для чтения хешей всех пользователей домена любому пользователю? Это позволит атакующему сохранить присутствие в системе и удаленно получить актуальную выгрузку LDAP-каталога с секретами пользователей, даже не владея учетной записью Directory Manager.

Создаем мисконфигурацию для чтения хешей паролей пользователей

Следует остановиться на том, как во FreeIPA происходит управление привилегиями пользователей. При рассмотрении HBAC- и Sudo-правил мы немного коснулись ролей, привилегий и разрешений.

Роль используется для точного делегирования прав доступа пользователям, группам, узлам или группе узлов. Разрешение дает право выполнять указанные низкоуровневые задачи (добавлять пользователей, изменять группы и так далее). Привилегия содержит одно или несколько разрешений, что дает полномочия более высокого уровня, например администратора пользователей (User Administrators). Имея привилегию User Administrators, можно добавлять, удалять и изменять записи пользователей. Привилегии назначаются ролям, а пользователи, группы, узлы и группы узлов могут быть участниками роли. Роли не могут содержать другие роли.

Пример взаимодействия:

  1. Разрешение дает доступ для чтения, записи, добавления, удаления, поиска или сравнения.

  2. Привилегия объединяет схожие разрешения (например, все разрешения, которые требуются для добавления пользователя).

  3. Роль дает набор привилегий пользователям, группам, узлам или группам узлов.

Любой пользователь из группы admins может создавать и изменять разрешения, привилегии и роли.

В целом для работы с разрешениями пользователю понадобятся следующие привилегии:

Однако разрешения на создание разрешения нет, ipa permission_find --right=add --type=permission ничего не находит. По результатам тестирования был сделан вывод, что именно создавать разрешение можно только членам группы admins. Это встроенная возможность.

Создадим отдельное разрешение для чтения атрибутов пользователей ipaNThash и userPassword прямо через веб-интерфейс:

Далее создадим привилегию с этим разрешением и роль:

И назначим нашу роль группе ipausers:

На примере обычного пользователя убедимся, что можем удаленно читать хеши любого пользователя:

Выполним LDAP-запрос от имени пользователя kate:

ldapsearch -x -D "uid=kate,cn=users,cn=accounts,dc=iparnd,dc=local" -w 'SuperPassword!' -H ldap://dc.iparnd.local -b "dc=iparnd,dc=local" -LLL "objectclass=person" krbCanonicalName uid cn userPassword ipaNTHash

Получаем удаленную выгрузку хешей всех пользователей:

Следует отметить, что созданное разрешение можно также добавлять в существующие привилегии и роли для большего сокрытия активности.

Найти такое разрешение можно командой ipa permission-find --attrs=ipaNTHash:

Let’s detect it

Отследим по событиям от FreeIPA API Call выполненные действия:

<190> Jun  2 15:49:46 dc [Mon Jun 02 15:49:45.970792 2025] [wsgi:error] [pid 32489] [remote 172.31.129.39:52564] ipa: INFO: [jsonserver_session] admin@IPARND.LOCAL: permission_add('wow_i_can_read_hashes', ipapermright='read', attrs=('ipanthash', 'userpassword'), ipapermbindruletype='permission', type='user', version='2.239'): SUCCESS   <190> Jun  2 15:51:34 dc [Mon Jun 02 15:51:34.061041 2025] [wsgi:error] [pid 32491] [remote 172.31.129.39:52593] ipa: INFO: [jsonserver_session] admin@IPARND.LOCAL: privilege_add_permission('Read_hash_priv', all=True, version='2.239', permission=('wow_i_can_read_hashes',)): SUCCESS   <190> Jun  2 15:52:00 dc [Mon Jun 02 15:51:59.484145 2025] [wsgi:error] [pid 32490] [remote 172.31.129.39:52593] ipa: INFO: [jsonserver_session] admin@IPARND.LOCAL: role_add_privilege('SuperRole', all=True, version='2.239', privilege=('Read_hash_priv',)): SUCCESS   <190> Jun  2 15:55:12 dc [Mon Jun 02 15:55:11.884416 2025] [wsgi:error] [pid 32491] [remote 172.31.129.39:52691] ipa: INFO: admin@IPARND.LOCAL: batch: role_add_member('SuperRole', group='ipausers'): SUCCESS

Данную активность можно выявлять на этапе создания или изменения разрешения:

dev_os_roles:"freeipa" AND event_id:("permission_add" OR "permission_mod") AND obj_properties:("read" OR "all") AND prop_value_data_new:("ipanthash" OR "userpassword")

Также LDAP-запросы с целью получения хешей паролей пользователя являются аномалией для инфраструктуры FreeIPA, так как по умолчанию читать секреты может только Directory Manager:

<190> Jun  2 16:05:21 dc [02/Jun/2025:16:05:12.261175207 +0300] conn=1487172 fd=154 slot=154 connection from 10.3.132.205 to 10.3.132.207   <190> Jun  2 16:05:21 dc [02/Jun/2025:16:05:12.261514748 +0300] conn=1487172 op=0 BIND dn="uid=kate,cn=users,cn=accounts,dc=iparnd,dc=local" method=128 version=3   <190> Jun  2 16:05:21 dc [02/Jun/2025:16:05:12.278897238 +0300] conn=1487172 op=1 SRCH base="dc=iparnd,dc=local" scope=2 filter="(objectClass=person)" attrs="krbCanonicalName uid cn userPassword ipaNTHash"

Получается аналогичный запрос:

dev_os_roles:"freeipa" AND event_id:"SRCH" AND ldap_dn.keyword:"^dc=.*" AND ldap_filter.keyword:"^.(object|user)\w+\=\S+" AND ldap_attrib_list:("userpassword" OR "ipanthash")

Резюмируем, что при наличии привилегий группы admins у пользователя может быть как минимум три вектора компрометации домена FreeIPA:

  1. Зайти на сервер FreeIPA, повыситься до root, забрать файлы /var/lib/dirsrv/slapd-<instance_name>/db/userRoot/id2entry.db и /etc/dirsrv/slapd-<instance_name>/dse.ldif.

  2. Выяснить учетные данные Directory Manager и выполнить удаленный дамп каталога LDAP.

  3. Создать разрешение для чтения хешей всех пользователей и назначить соответствующую роль пользователю, выполнить удаленный дамп.

Кратко о хешах

Хеши паролей хранятся в LDAP-каталоге. Каждый хранится в Base64-формате в атрибуте userPassword. Для совместимости с Windows-системами существует и второй атрибут ipaNTHash, который хранит NT-хеш пароля пользователя. По умолчанию параметр AllowNThash включен во FreeIPA. В атрибуте же userPassword хеш может храниться в различных форматах, таких как SSHA512, PBKDF2_SHA256, PBKDF2_SHA512. Давайте рассмотрим каждый из форматов и определим стойкость к офлайн-брутфорсу.

NT hash

Для преобразования хеша пароля атрибута ipaNTHash необходимо сперва сделать преобразование из Base64 и далее перекодировать как ASCII hex:

>>> import base64 >>> base64.b64decode('JZdFyxI6UqouaTqqzKLbUg==').hex() '259745cb123a52aa2e693aaacca2db52' >>> exit()

Далее ужe NT hash брутится с использованием John (--format=NT) или haschcat:

Если в вашей инфраструктуре отсутствует интеграция FreeIPA c Microsoft, то рекомендуем отключить поддержку NT-хешей, так злоумышленнику будет сложнее сбрутить пароли.

SSHA512

Декодировав из Base64 значение атрибута userPassword, мы можем встретить формат хеша SSHA512. Он является одним из распространенных форматов с префиксом {SSHA512}, как показано в примере ниже. Отличительная особенность — заголовок {SSHA512}. Брутится с использованием John или haschcat:

{SSHA512}SCMmLlStPIxVtJc8Y6REiGTMsgSEFF7xVQFoYZYg39H0nEeDuK/fWxxNZCdSYlRgJK3U3q0lYTka3Nre2CjXzeNUjbvHabYP

PBKDF2

В новых версиях FreeIPA используется более безопасный алгоритм PBKDF2 для хранения паролей. PBKDF2 — это функция, которая многократно (итеративно) применяет хеш-функцию (может быть SHA-256 или SHA-512), чтобы повысить устойчивость к брутфорсу. При декодировании userpasswordword вы получаете хеш следующего вида.

Формат:

{PBKDF2_SHA256}$<итерации>$<соль>$<хеш>
$pbkdf2-sha256$2048$5kvNtuFxh5jWDbOnq9vBeFPBEiUDrwb4w1DC4X5jJMAiObN71Y/2NUdsO.V4pAgAIWgdBQJXAy.SsbgAgxzDFA$06s.PFQqsFu88sx5PN05QBBHfd6j3VjAT1U77sCdH2DRXwRbGd.fQzU.S7jXqxGfdVI/YYMlv5wEhazXDWBZX5U9NZWRA9SEVrSCSqitBtTKNFsfUziQEiPXAF2OkFxM9HY8zszQJ7Ex3zJcIup8J5rgyij4mgdU2pPzwJoCdg6dawebgZZzft0KurRSM6Wtpaufb147SAN1AwrO8aC6A7RD/0HK9VOcqEqXUEoaRL/ZTehjgindga4hoRxgOy2pI8s1ySie1lw/wSVv2.QdfDWKImTstAEkWwg6ss7z8g7P7MIhurL9s9JGa.Zo9W6Pq6aNFFVLT2TjBLFFiltSbg

Есть особенность, что John не может обработать этот хеш. Причина в том, что PBKDF2-HMAC-SHA256 обычно имеет длину выходных данных 256 бит (32 байта), что соответствует размеру выхода алгоритма SHA-256. Но PBKDF2 позволяет указать произвольную длину выходного ключа, и разработчики 389-ds выбрали длину 256 байт, что превышает размер, поддерживаемый John. Из-за принципа работы PBKDF2 хеш формируется из нескольких блоков, которые вычисляются независимо. Это означает, что нам нужно атаковать только один блок, чтобы получить пароль.

Чтобы вручную не считать требуемое количество байтов, есть готовый скрипт, который преобразует хеши из атрибутов userPassword и ipaNTHash в подготовленный для John и hashcat формат. Однако все равно могут потребоваться дальнейшие преобразования хеша для обработки его инструментами для брутфорса:

Сценарии выявления подозрительной активности FreeIPA

В данном разделе приводим список рекомендуемых правил для мониторинга FreeIPA — от разведки до компрометации домена.

  1. Сбор информации о различных учетных записях в домене FreeIPA с одного узла и от одного пользователя.

  2. Сбор информации о различных объектах в домене FreeIPA с одного узла и от одного пользователя.

  3. Вероятная проверка учетных записей с использованием предварительной аутентификации Kerberos в домене FreeIPA.

  4. Подбор пароля к учетной записи через запросы BIND по протоколу LDAP во FreeIPA.

  5. Попытки подбора паролей для различных аккаунтов через запросы BIND по протоколу LDAP во FreeIPA.

  6. Подбор пароля к учетной записи в домене FreeIPA (LDAP).

  7. Подбор пароля к учетной записи в домене FreeIPA (Kerberos).

  8. Добавление пользователя в критическую/привилегированную группу FreeIPA.

  9. Удаление пользователя из критической/привилегированной группы FreeIPA.

  10. Внесение изменений в критическое Sudo-правило в домене FreeIPA.

  11. Попытка включения HBAC-правила allow_all в домене FreeIPA.

  12. Попытка внесения изменений в критическое HBAC-правило в домене FreeIPA.

  13. Попытка добавления критической привилегии для роли в домене FreeIPA.

  14. Назначение критической роли пользователю в домене FreeIPA.

  15. Добавление одинакового открытого ключа SSH нескольким пользователям от одного пользователя в домене FreeIPA.

  16. Обнаружение команд запуска утилит ipapocket.

  17. Попытка запроса TGS для admin.

  18. Предположительное раскрытие значения соли при использовании debug-режима для AS_REQ-запроса.

  19. Подозрительный доступ/действия с файлом базы данных id2entry.db на сервере FreeIPA.

  20. Получение доступа к критическому содержимому файла базы данных dse.ldif на сервере FreeIPA.

  21. Обнаружение LDAP-запроса, характерного для удаленного дампа домена в формате LDIF в домене FreeIPA.

  22. Использование учетной записи Directory Manager для BIND-аутентификации в каталоге LDAP FreeIPA.

  23. Создание разрешения на чтение паролей пользователей в домене FreeIPA.

  24. Обнаружение LDAP-запроса, характерного для выгрузки секретов объектов LDAP в домене FreeIPA.

С данными сценариями детектирования существенно повышается вероятность обнаружения активности атакующих на каждом этапе kill chain.

Заключение

Работа с FreeIPA показала, что безопасность этой системы пока еще слабо изучена. Первая значимая публикация по атакам на FreeIPA (серия статей Attacking FreeIPA (Part I–IV) от команды SpecterOps) появилась лишь в 2019 году. С тех пор интерес к теме медленно рос, однако в российском кибербез-комьюнити с 2022 года он значительно повысился. Причина — активный переход на опенсорс-решения в условиях санкционного давления и внедрение аналогов Active Directory. 

FreeIPA — один из наиболее популярных кандидатов на замену AD. Поэтому специалисты по кибербезопасности должны понимать поверхность атаки и разбираться в способах харденинга FreeIPA. В разделе «Создаем мисконфигурацию для чтения хешей паролей пользователей» я показал, как одна галочка при создании разрешения ведет к компрометации секретов всех пользователей в домене. Поэтому очень важно продолжать исследовать это решение. Оно скрывает в себе еще не одну мисконфигурацию и уязвимость. Рассмотренные в статье сценарии атак и правила детектирования помогут вовремя среагировать на попытку компрометации домена FreeIPA.


ссылка на оригинал статьи https://habr.com/ru/articles/922540/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *