В последнее время в различных отчетах об атаках и результатах пентестов часто фигурирует FreeIPA — система централизованного управления хостами и группами пользователей, ориентированная на Linux-инфраструктуру. Можно сказать, что это опенсорс-альтернатива для MS Active Directory. Хотя FreeIPA не является ключевым компонентом инфраструктуры, из-за особенностей конфигурирования, она может стать для злоумышленника кратчайшим путем к компрометации организации. Поэтому мы — Ильназ Гатауллин, технический руководитель RED Security SOC и Сергей Орляк, руководитель третьей линии RED Security SOC — решили рассказать о схемах атак на FreeIPA, основных методах их детектирования и расследования.
Мы хотим разобрать целый ряд атак: показать их механику, поделиться правилами корреляции, которые вы сможете использовать для самостоятельного выявления таких инцидентов, и советами по расследованию. Поскольку в итоге получился очень обширный tutorial, мы разделим его на две публикации. Во второй части посмотрим на весь Kill Chain атак на FreeIPA и покажем, как приведенные правила позволят выявлять злоумышленника на любом из этапов.
Состав системы FreeIPA
Как же выглядит FreeIPA глазами внешнего атакующего? Она состоит из нескольких компонентов:
Apache httpd,
MIT Kerberos,
LDAP 389,
Kadmin
Сервер синтезификации DogTag на Tomcat
DNS-сервер Bind.

Оказавшись на сервере или на рядовом хосте, атакующий может скомпрометировать находящиеся на них keytab-файлы для аутентификации. Злоумышленник, вероятно, попытается извлечь билеты Kerberos (сетевой протокол аутентификации для безопасной передачи данных), либо хеши паролей. Оказавшись на сервере FreeIPA, он может атаковать базу LDAP-каталога для полной компрометации всех хешей пользователей и Kerberos-ключей.
Вот что видит злоумышленник после получения доступа на хост:
Ключи в виде keytab-файлов
1. На сервере FreeIPA и на членах домена:
/etc/krb5.keytab
2. На сервере FreeIPA:
/etc/pki/pki-tomcat/dogtag.keytab
/etc/dirsrv/ds.keytab
/etc/named.keytab
/etc/ipa/dnssec/ipa-dnskeysyncd.keytab
/var/lib/ipa/gssproxy/http.keytab
Хранилище хешей и ключей
1. На сервере FreeIPA и на членах домена:
/var/lib/sss/db/*.ldb
/var/lib/sss/secrets/secrets.ldb
2. На сервере FreeIPA:
/var/lib/dirsrv/slapd-%REALM%/db/userRoot/id2entry.db
/etc/dirsrv/slapd-%REALM%/dse.ldif
/var/lib/ipa/backup/
/tmp/
Можно привести некоторую аналогию с Microsoft Windows:
FreeIPA (sssd) = Windows (lsass)
FreeIPA (id2entry.db)= Windows (ntds.dit)
FreeIPA (secrets.ldb) = Windows (SAM)
Настройки журналирования FreeIPA
Для эффективного выявления, локализации и расследования инцидентов ИБ нужно произвести настройку журналирования событий. Ниже предоставлены конкретные рекомендации.
MIT Kerberos:
В конфигурационный файл /etc/krb5.conf необходимо внести записи:
[logging]
kdc = FILE:/var/log/krb5kdc.logЖурнал с событиями будет находиться по адресу: /var/log/krb5kdc.log
Apache httpd:
В конфигурационный файл: /etc/httpd/conf/httpd.conf необходимо внести записи:
ErrorLog "logs/error_log"
CustomLog "logs/access_log"Журналы с событиями будут находиться по адресу:
/var/log/httpd/error_log
/var/log/httpd/access_log
LDAP 389 (access-логи):
Настройки логирования хранятся в ldap. По умолчанию журналирование настроено на уровень 256 (Logging for connections, operations, and results)
Проверить уровень можно командой:
ldapsearch -x -D "cn=Directory Manager" -b cn=config -W -h [ipa_server_IP] -p 389 nsslapd-accesslog-level | grep nsslapd-accesslog-levelЖурналы с событиями будет находиться по адресам:
/var/log/dirsrv/slapd-%REALM%/errors
/var/log/dirsrv/slapd-%REALM%/access
Заметим, что для анализа LDAP-запросов нужно произвести дополнительную настройку событий audit для LDAP 389, который предоставлен так же ниже:
LDAP 389 (audit-логи):
Дополнительно к событиям по умолчанию рекомендуем включить журналирование изменения записей LDAP (audit-логи). Для этого на сервере со службой 389 выполните команду:
ldapmodify -D "cn=Directory Manager" -W << EOF
dn: cn=config
changetype: modify
replace: nsslapd-auditlog-logging-enabled
nsslapd-auditlog-logging-enabled: on
replace:nsslapd-auditlog
nsslapd-auditlog: /var/log/dirsrv/slapd-%REALM%/audit
replace:nsslapd-auditlog-mode
nsslapd-auditlog-mode: 600
replace:nsslapd-auditlog-maxlogsize
nsslapd-auditlog-maxlogsize: 100
replace:nsslapd-auditlog-logrotationtime
nsslapd-auditlog-logrotationtime: 1
replace:nsslapd-auditlog-logrotationtimeunit
nsslapd-auditlog-logrotationtimeunit: day
EOF
Журнал с событиями будет находиться по адресу: /var/log/dirsrv/slapd-%REALM%/audit
Дополнительных настроек журналирования событий для MIT Kerberos, Access-логов, LDAP 389 и Apache httpd не требуется — для расследований достаточно настроек по умолчанию.
Также не стоит забывать про остальные демоны — kadmin, tomcat, bind, sssd, samba и другие. Если вам будет интересно погрузиться в них, напишите в комментариях, сделаем отдельные статьи.
Логика выявления и расследования шагов при атаках на FreeIPA
Анонимная LDAP-аутентификация (Anonymous BIND, TA0007)
Если у злоумышленника нет учетных записей доменов FreeIPA, он может произвести анонимную LDAP-аутентификацию, которая разрешена по умолчанию. Таким образом легко получить данные об объектах LDAP-каталога.
Ниже представлено правило корреляции для детектирования анонимной LDAP-аутентификации. Здесь и далее мы будем приводить их в универсальном и немного сокращенном Sigma-формате: чтобы вы могли применить их для своей SIEM-системы:
logsource:
product: ldap 389
files: /var/log/dirsrv/slapd-*/access
detection:
selection:
ldap_action: 'BIND‘
ldap_ method: '128‘
dn : ''
condition: selection
А вот пример команды, которую может выполнить атакующий:
ldapsearch -x -H ldap://11.62.10.236:389 -b "cn=users,cn=accounts,dc=stand,dc=local" uid
Результат ее выполнения представлен на скриншоте:

Разберем расследование этого инцидента на примере. Полужирным мы выделили поля, которые помогают принять правильное решение.
Итак, вот такие данные мы получаем при срабатывании правила корреляции:
[11/Oct/2024:17:11:58.263667442 +0300] conn=418 op=0 BIND dn=""
method=128 version=3
Для реагирования нужно обогатить инцидент дополнительной информацией. Чтобы определить, с какого хоста был выполнен запрос, ищем событие установки соединения по номеру LDAP-сессии:
[11/Oct/2024:17:11:58.263167039 +0300] conn=418 fd=232 slot=232
connection from 11.62.10.144 to 11.62.10.236
Теперь применим фильтр по номеру этой LDAP-сессии, чтобы увидеть всю активность, которая была выполнена в ее рамках:
[11/Oct/2024:17:11:58.263970095 +0300] conn=418 op=1 SRCH base="cn=users,cn=accounts,dc=stand,dc=local" scope=2 filter="(objectClass=*)" attrs="uid"
Также важно учитывать, что отдельных запросов с IP-адреса атакующего в LDAP может быть несколько.
Simple LDAP-аутентификация (Simple BIND, T1078)
Если у атакующего есть учетная запись, он может выполнить Simple LDAP-аутентификацию. В норме таких событий в домене достаточно мало, соответственно, можно выстроить профиль подключений, отследить нелегитимные и в дальнейшем их расследовать.
Правило корреляции:
logsource:
product: ldap 389
files: /var/log/dirsrv/slapd-*/access
detection:
selection:
ldap_action: 'BIND'
ldap_method: '128'
filter:
dn: ''
condition: selection AND NOT filter
Пример активности атакующего:
ldapsearch -x -D
"uid=user2,cn=users,cn=accounts,dc=stand,dc=
local" -w "P@ssw0rd" -H ldap://11.62.10.236:389
-b "cn=users,cn=accounts,dc=stand,dc=local" uid
Результат выполнения команды:

При расследовании срабатывания данного правила корреляции мы сразу видим имя пользователя, который пытался использовать Simple-аутентификацию.
Аналогично предыдущему примеру по номеру LDAP-сессии получаем IP-адрес хоста, откуда была произведена активность, и смотрим все запросы к LDAP-каталогу в рамках данной сессии. И опять-таки, важно проверить, были ли другие запросы с IP-адреса атакующего.
[11/Oct/2024:17:21:38.604067273 +0300] conn=423 op=0 BIND dn="uid=user2,cn=users,cn=accounts,dc=stand,dc=local" method=128 version=3
По номеру LDAP-сессии мы можем посмотреть IP-адрес хоста, откуда было произведено подключение, и все запросы к LDAP-каталогу в рамках данной активности.
Хост, с которого был произведен запрос:
[11/Oct/2024:17:21:38.603544084 +0300] conn=423 fd=232 slot=232
connection from 11.62.10.144 to 11.62.10.236
Активность на LDAP-каталоге, выполненная в рамках данной сессии:
[11/Oct/2024:17:21:38.606253739 +0300] conn=423 op=1 SRCH base=”cn=users,cn=accounts,dc=stand,dc=local” scope=2 filter=”(objectClass=*)” attrs=”uid”
Неуспешные попытки аутентификации под различными учетными записями по протоколу Kerberos (PassSpray Kerberos, T1087)
Многим уже известны атаки User Enumeration и Password Spraying — FreeIPA, в том числе, подвержена и этим видам атак, так что необходимо отслеживать активности в журналах MIT Kerberos и проводить расследование в случае подбора учетных записей или Password Spraying.
Правило корреляции:
logsource:
product: MIT Kerberos
files: /var/log/krb5kdc.log
detection:
selection:
krb5_event: 'AS_REQ'
filter:
action:
- 'ISSUE‘
- 'NEEDED_PREAUTH‘
condition: selection AND NOT filter
correlation:
group-by:
- 'SourceAddress'
uniq: 'UserName‘
timespan: 5m
condition: gte 10
Пример активности атакующего:
kerbrute_linux_amd64 passwordspray --dc 11.62.10.236 -d stand.local user_dict.txt "P@ssw0rd"
kerbrute_linux_amd64 userenum --dc 11.62.10.236 -d stand.local user_dict.txt
Результат исполнения команды:

Добавим, что значение политики блокировки по умолчанию: 6 неверных попыток и 10 минут до сброса счетчика.
Расследование такого инцидента эффективнее производить на выборке большого количества однотипных событий. Поэтому для данного правила корреляции мы выбираем все события попыток аутентификации Kerberos с фильтрацией по IP-адресу предполагаемого злоумышленника. Так можно построить таймлайн, который дополнительно покажет аномалию и время старта атаки.
Данные при начале расследования:
2024 Oct 11 18:04:30 oracle-test.stand.local krb5kdc[2961](info): AS_REQ (3 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), DEPRECATED:arcfour-hmac(23)}) 11.62.10.144: CLIENT_NOT_FOUND: User13@STAND.LOCAL for krbtgt/STAND.LOCAL@STAND.LOCAL, Client not found in Kerberos database
Здесь мы видим IP атакующего. Используя его как фильтр, можно посмотреть запросы к событиям запроса билетов Kerberos, оценивая их количество и распределение по времени. При правильном выборе полей агрегации мы сразу видим таймлайн атаки и ее интенсивность. И самое главное, отфильтровав события по успешности операции, мы выявим скомпрометированные в ходе атаки учетные записи пользователей:

Перебор пароля для учетной записи (УЗ) по протоколу Kerberos (Bruteforce Kerberos, T1110)
FreeIPA также подвержена атакам путем подбора пароля. Как мы говорили выше, в системе есть ограничения по умолчанию — настройка политик, которая не позволяет подбирать пароли и блокирует учётную запись после определённого количества неудачных попыток аутентификации. Однако администраторы могут отключить эту функцию и тем самым позволить злоумышленнику беспрепятственно проводить атаку подбора пароля.
Правило корреляции:
logsource:
product: MIT Kerberos
files: /var/log/krb5kdc.log
detection:
selection:
krb5_event: 'AS_REQ'
filter:
action:
- 'ISSUE‘
- 'NEEDED_PREAUTH‘
condition: selection AND NOT filter
correlation:
group-by:
- 'SourceAddress'
- 'UserName‘
timespan: 5m
condition: gte 20
Пример активности атакующего:
kerbrute_linux_amd64 bruteuser --safe --dc 11.62.10.236 -d stand.local pass_dict.txt user2
Результат исполнения команды:

Расследование этого инцидента производится аналогично обращению к множеству событий с их последующей агрегацией, то есть так же, как и в кейсе PassSpray Kerberos.
Данные при начале расследования:
2024 Oct 11 18:44:16 oracle-test.stand.local krb5kdc[2961](info): AS_REQ (3 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), DEPRECATED:arcfour-hmac(23)}) 11.62.10.144: PREAUTH_FAILED: user2@STAND.LOCAL for krbtgt/STAND.LOCAL@STAND.LOCAL, Preauthentication failed
После попытки подбора пароля учетная запись может заблокироваться. Таким образом, следует отслеживать два базовых события — неудачную аутентификации под учетной записью и ее блокировку.

Блокировка критичной УЗ (User LockedOut, T1531)
На таких событиях можно строить разные стратегии по выявлению атакующего. Это могут быть:
Множественная блокировка одной УЗ в результате некорректного выполнения атаки BruteForce;
Блокировка различных УЗ с одного IP-адреса, когда параметры для атаки Password Spraying были выбраны некорректно;
Единичная блокировка критичных УЗ.
Рассмотрим последний вариант. В FreeIPA критичной УЗ, создаваемой по умолчанию, является admin. Но в процессе работы администраторы системы иногда добавляют других пользователей, полномочия которых могут быть критичными для FreeIPA или для бизнес-систем, которые с ней интегрированы.
В этом случае помогут такие правила корреляции:
name: ‘User_Unsuccess’
logsource:
product: MIT Kerberos
files: /var/log/krb5kdc.log
detection:
selection:
krb5_event: 'AS_REQ'
filter:
action:
- 'ISSUE‘
- 'LOCKED_OUT‘
- 'NEEDED_PREAUTH‘
condition: selection AND NOT filter
name: ‘User_Locked’
logsource:
product: MIT Kerberos
files: /var/log/krb5kdc.log
detection:
selection:
krb5_event: 'AS_REQ‘
action: 'LOCKED_OUT‘
user: ‘admin‘
condition: selection
correlation:
rules:
- ‘User_Unsuccess’
- ‘User_Locked’
group-by:
- 'SourceAddress'
- 'UserName‘
timespan: 1m
Расследование подозрений на инциденты по срабатываниям данного правила корреляции аналогично уже рассмотренным правилам выявления атак типа BruteForce и Password Spraying.
Подходы злоумышленников к охоте за ключами в базе LDAP
Ранее мы говорили, что каталог LDAP в системе FreeIPA содержит большой объем информации. Нам нужно понять, чем же может попытаться завладеть злоумышленник. Прежде всего, с большой долей вероятности он попробует получить хеши паролей пользователей или ключи Kerberos.
Для совместимости с Microsoft хеши могут быть вида IPA-NTHash, который имеет низкую сложность вычислений и более подвержен брутфорсу. Может также использоваться user password — для авторизации на LDAP. Kerberos-ключи, находящиеся в LDAP, зашифрованы мастер-ключом, который также находится в LDAP-контейнере.
Стоит еще сказать про пользователя Directory Manager. Это системный пользователь, он находится в отдельном файле конфигурации экземпляра LDAP-каталога. Особенность этого пользователя в том, что он обладает расширенными правами, достаточными, чтобы запросить все хеши и ключи Kerberos.
В каких полях хранятся ключи (файл «id2entry.db»):
ipaNTHash — NT Hash (в base64),
userPassword — хеш пароля пользователя (в base64),
krbMKey — мастер‑ключ для шифрования ключей krbPrincipalKey,
krbPrincipalKey — зашифрованный ключ Kerberos.
Хеш пароля от учетной записи Directory Manager хранится в файле /etc/dirsrv/slapd-[domain name]/dse.ldif в атрибуте «nsslapd-rootpw».
Пример активности атакующего:
ldapsearch -D "cn=Directory Manager" -x -w "P@ssw0rd" -H ldap://11.62.10.236 "(|(userPassword=*)(ipaNTHash=*)(krbPrincipalKey=*)(krbMKey=*))" krbCanonicalName uid cn userPassword ipaNTHash krbPrincipalKey krbMKey
Результат выполнения команды:

Мы определились, за какими ключами может охотиться злоумышленник, но как же он до них доберется? Есть два основных подхода: удаленная попытка получения и локальная из файлов базы данных LDAP-каталога. Первый вариант можно осуществить с помощью УЗ с достаточными правами, например, все той же Directory Manager.
Локально можно собрать все эти ключи, получив доступ непосредственно на сервер FreeIPA. Вне зависимости от способа сбора этих данных, расшифровку Kerberos-ключей для аутентификации можно выполнить с помощью пакета IPA-Pocket, а затем пересобрать их в keytab-файлы, используя стандартную утилиту ktutil. А хеши уже можно перебирать для получения паролей в открытом виде.
Пример действий злоумышленника — команды для получения и расшифровки ключей из артефактов работы ldapsearch (удаленно):
ldapsearch -D "cn=Directory Manager" -x -w "P@ssw0rd" -H ldap://11.62.10.236 "(|(userPassword=*)(ipaNTHash=*)(krbPrincipalKey=*)(krbMKey=*))" krbCanonicalName uid cn userPassword ipaNTHash krbPrincipalKey krbMKey
python3.12 ipp-id2entry-ldiff.py
Результат выполнения команды:

Пример команды и расшифровки ключей из артефактов работы dbscan локально на хосте:
dbscan -f /var/lib/dirsrv/slapd-%REALM%/db/userRoot/id2entry.db > dbscan_id2entry_dump.txt
python3.12 ipp-id2entry.py -d dbscan_id2entry_dump.txt
Результат исполнения команды:

Далее злоумышленник превращает полученные ключи в keytab-фалы с помощью утилиты ktutil и получает TGT-билет, выполняя PassTheTicket:
kinit -V -k -t admin_ticket.keytab -f admin@STAND.LOCAL
Перебор пароля критичной УЗ по LDAP (LDAP BruteForce Crit, T1110)
Итак, злоумышленнику интереснее всего будет получить учетную запись Directory Manager, которая даст ему наивысший набор привилегий. При этом у системы FreeIPA есть одна особенность — по умолчанию Directory Manager при подборе паролей по протоколу LDAP не блокируется. Это и позволяет злоумышленнику производить атаку, при этом не получая блокировку УЗ.
Но часто ли мы будем подключаться по протоколу LDAP под критичными УЗ? Если администраторы неиспользуют в повседневной работе Directory Manager или admin, такая активность должна быть настоящей редкостью — значит, ее можно спрофилировать. Тем самым по двум базовым событиям — User Connect и Bind — мы выявим аномальные события, организуем профиль подключений и будем дальше выявлять аномалии.
Можно выделить два подхода к детектированию вредоносной активности:
Выявление перебора паролей для критичной УЗ;
Выявление единичных попыток подключения под критичными УЗ (успешных или нет), отличающихся от стандартного профиля. Поиск аномалий позволит нам выявить действия нарушителя, даже если порог активности не будет превышать значений для правила BruteForce.
Правило детектирования перебора пароля:
name: 'User_Connect'
logsource:
product: ldap.389
files: /var/log/djrsrv/slapd-*/access
detection:
selection:
ldap_action:
- 'connection':
- 'SSL connection':
condition: selection
name: 'User_BIND'
logsource:
product: ldap.389
files: /var/log/djrsrv/slapd-*/access
detection:
selection:
ldap_action: 'BIND'
useristarbutt:
- 'cn=Directory Manager',
- 'cn=uid=admin'
condition: selection
correlation:
rules:
- 'User_Connect'
- 'User_BIND'
group-by:
- 'SourceAddress',
- 'UserName',
- 'ldap_389_HostName',
- 'ldap_389_HostAddress'.
timespan: 1m
condition: gte 10
Правило корреляции выявления подключения под критичной учетной записью:
name: 'User_Connect'
logsource:
product: ldap 389
files: /var/log/dirsrv/slapd-*/access
detection:
selection:
ldap_action:
- 'connection':
- 'SSL connection':
condition: selection
name: 'User_BIND'
logsource:
product: ldap 389
files: /var/log/dirsrv/slapd-*/access
detection:
selection:
ldap_action: 'BIND'
user/startwith:
- 'CR=Directory Manager':
- 'CR=uid=admin'
condition: selection
correlation:
rules:
- 'User_Connect'
- 'User_BIND'
Пример активности атакующего:
hydra -l "cn=Directory Manager" -P /usr/share/wordlists/rockyou.txt -S -I ldap3://11.62.10.236
Результат выполнения команды:

Данные при начале расследования:
[13/Oct/2024:23:24:38.956563355 +0300] conn=15541 fd=243 slot=243 SSL connection from 11.62.10.144 to 11.62.10.236
[13/Oct/2024:23:26:40.954419391 +0300] conn=15541 op=496 BIND dn="cn=Directory Manager" method=128 version=3
Расследование данного инцидента удобно проводить с помощью запросов с агрегацией. При правильном выборе полей агрегации мы можем сразу определить начало атаки, ее интенсивность и успешность:

При срабатывании этого правила корреляции мы сразу получаем имя критичной УЗ и IP-адрес хоста, откуда было выполнено подключение. Обладая информацией о скоупе IP-адресов, с которых происходит легитимное подключение, можно сразу определить, нужно ли в данном случае реагирование.
Данные при начале расследования:
[13/Oct/2024:21:58:43.609751461 +0300] conn=15522 fd=231 slot=231 connection from 11.62.10.144 to 11.62.10.236
[13/Oct/2024:21:58:43.610350915 +0300] conn=15522 op=0 BIND dn="cn=Directory Manager" method=128 version=3
Но интересно же узнать и цели подключения. Для этого можно использовать LDAP SRCH, чтобы посмотреть тело выполненного запроса. Если в ходе расследования мы видим подобный запрос, то понятно, что от этой активности ничего хорошего ждать не следует:
[13/Oct/2024:21:58:43.610968482 +0300] conn=15522 op=1 SRCH base="dc=stand,dc=local" scope=2 filter="(|(userPassword=*)(ipaNTHash=*)(krbPrincipalKey=*)(krbMKey=*))" attrs="krbCanonicalName uid cn userPassword ipaNTHash krbPrincipalKey krbMKey"
Таким образом, контроль использования критичных учеток всегда будет первоочередной задачей. Программаминимум — детектировать явные атаки на них. Но можно сделать больше и составить профили стандартного использования критичных УЗ. Во-первых, это позволит проаудировать и при необходимости скорректировать подходы к их применению, а во-вторых, даст нам инструментарий для выявления более сложных атак.
На этом мы заканчиваем первую часть. В следующей статье расскажем о том, может ли злоумышленник применять Bruteforce или User Enumeration незаметно для команды защитников, поговорим о том, как профилировать запросы к LDAP-каталогу и наконец дадим полную схему Kill Chain атак на FreeIPA c правилами выявления вредоносной активности.