Study of attacks and defense strategies
Considering law about the transition to domestic software at critical information infrastructure facilities by 2025, this topic is becoming relevant for many companies. Along with the active transition to FreeIPA, users began to have questions about attack mechanisms and defense strategies against them. In this article, we will consider some examples of attacks on the FreeIPA infrastructure and offer options for detecting them using a SIEM system.
FreeIPA device
FreeIPA – is a set of components for centralized management of accounts, groups and security policies. The system includes a web interface and command-line administration tools. FreeIPA provides centralized authentication, authorization and account information, storing data on users, groups, hosts and other objects necessary for managing the security aspects of a local network. This solution is built on the Red Hat Identity Management (IdM) platform from well-known open source components and standard protocols, with a strong emphasis on ease of management and automation of installation and configuration tasks.
To better understand the possible attacks on the FreeIPA infrastructure, let's get acquainted with its components and technologies.
FreeIPA Components
FreeIPA (and its derivatives such as ALD Pro from Astra Linux) includes several key components:
Web server:
used to configure policies and manage accounts;
implemented on the basis of Apache HTTP Server.
Directory Server 389:
provides centralized storage of data about users and resources;
uses LDAP (Lightweight Directory Access Protocol).
MIT Kerberos:
is responsible for authentication and management of access tickets (standard ones, like in AD, TGT and TGS are used, and the CCHACHE file is used to store the ticket locally);
Allows you to securely authenticate users and services on the network.
NTP (Network Time Protocol):
synchronizes time between all system components;
provides accurate time, which is critical for authentication and security.
DNS:
manages domain names and their resolution into IP addresses;
Includes support for SRV records for Kerberos and LDAP.
Dogtag Certification System:
manages digital certificates for encryption and authentication;
provides a public key infrastructure (PKI).
These components are integrated to provide secure and centralized management of identity, authentication, and authorization across the domain infrastructure. You can read more about the architecture in documentation.
Event logging
FreeIPA provides the following logs for logging:
/var/log/httpd/error_log
: FreeIPA API call logs (and Apache errors) – analyzes calls to the FreeIPA API and errors of the Apache server on which the FreeIPA web is running;/var/log/krb5kdc.log
: FreeIPA KDC utilization – logs FreeIPA KDC actions;/var/log/dirsrv/slapd-$REALM/access
: Directory Server utilization – logs requests via LDAP protocol;/var/log/dirsrv/slapd-$REALM/errors
: Directory Server errors (including mentioned replication errors) – is responsible for errors that occur in the system during its operation.
We will look at some of the logs in more detail during the event analysis when analyzing attacks.
Attacks on FreeIPA
In our attack analysis we will rely on the matrix MITRE ATT&CK.
First, let's look at what methods an attacker might use to obtain credentials (tactics Credential Access). One of the possible options is an attempt to steal TGT and TGS tickets (we talked about them in more detail in one of our previous articles) and then reuse them.
Stealing Kerberos Tickets
Let's consider a situation where tickets are configured to be saved as a file on disk. In this case, we can perform an attack like Steal or Forge Kerberos Tickets (T1558). The standard format for storing tickets is the CCACHE file. CCACHE (Credential Cache) is a file that contains user data and tickets, which allows you to avoid re-authentication when accessing services. These files are usually stored in /tmp
have a resolution of 600 and a format krb5cc_<uid>
From the attacker's point of view, this is important for the following reasons:
valid tickets can be used for authentication without the need to know the user's password in clear text;
CCACHE tickets are portable. They can be downloaded and uploaded to another host without the need to update or validate the ticket
klist
.
This will display information about the active Kerberos ticket, and in the field Ticket cache
the path to it will be indicated. The figure shows that the CCHACHE file itself is located in the folder /tmp
.
Now let's look at the events that are generated when these tickets are accessed.
To monitor file access events, we will use the most common Linux audit daemon – AuditdTo generate such events, we need the following configuration rule for Auditd:
-w /tmp -p rwa -k ticket_ccache_file_read
After adding the rule, when accessing the CCHACHE file, an Object Access event is generated:
In the Object Access event we are interested in:
The executable file that initiated the activity (
exe=
), in our case/usr/bin/cat
.The file that was accessed (
name=
) in the above event/tmp/krb5cc_1472000008
After normalization, this field is calledfilePath
. If the CCACHE file is accessed from/tmp
the path will be specified in the fieldcwd=
(after normalization this fieldobjPath
).Syscol number (
syscall=
). In our case, the number257
which meansopenat
– opening a file. After normalization, this field is calledcs4
.The rights with which the appeal was made (
a2=
), are equal0
which means opening the file for reading. After normalization, this field is calledfilePermission
.
Based on the above activity, we can conclude that it is necessary to monitor the file opening (syscall =openat
), which contains the substring krb5cc_
in the name and is located on the path /tmp
with read permissions r
.
The figure below shows an example of such a rule in R-Vision SIEM:
The rule code is written in the R-Object plugin, which we recently published an article about.
The full code can be seen under the spoiler:
Reading Ticket CCACHE file
id: ce9ec896-9549-42ae-a855-9010a5ea41e2
name: Чтение Ticket CCACHE файла
type: correlation_rule
severity: medium
version: 1.0.1
status: stable
date: 2024-05-02
author: Ilya Efimov, R-Vision
description: Когда билеты настроены на сохранение в виде файла на диске,
стандартным форматом и типом является файл CCACHE. Это простой
двоичный формат файла для хранения учетных данных Kerberos. Эти
файлы обычно хранятся в /tmp и имеют разрешения 600. С точки зрения
атакующего это важно по следующим причинам - 1)Действительные билеты могут
быть использованы для аутентификации без необходимости знать пароль
пользователя в открытом тексте. 2) Билеты CCACHE очень портативны.
Их можно скачать и загрузить на другой хост без необходимости обновления
или проверки билета. Таким образом доступ к билетам CCACHE является критичным
событием ИБ и может означать действия злоумышленника по разведке учетных записей
и доступу к действительным билетам Kerberos.
В случае возникновения активности необходимо опросить владельца учетной записи инициатора активности
на предмет совершенных действий.
reference:
- https://posts.specterops.io/attacking-freeipa-part-i-authentication-77e73d837d6a
- https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-active-directory
known_false_positives:
- Действия пользователя по изучению своих билетов
data_source:
- Linux
- auditd
- R-Point
- credential-access
tags:
- Credential Access
- attack.T1558
filter: !vrl |
.dvendor == "Linux" &&
downcase(to_string(.cs4) ?? "") == "openat" &&
contains(to_string(.filePath) ?? "", "krb5cc_") &&
(downcase(to_string(.objPath) ?? "") == "/tmp" || contains(to_string(.filePath) ?? "", "/tmp")) &&
downcase(to_string(.filePermission) ?? "") == "r"
aliases:
event:
filter: !vrl |
true
select:
alias: event
ttl: 30
on_correlate: !vrl |
. |= compact({
"act" : %event.act,
"suser" : %event.suser,
"sproc" : %event.sproc,
"dproc" : %event.dproc,
"dpid" : %event.dpid,
"shost" : %event.shost,
"externalId" : %event.externalId,
"cmd": %event.cmd,
"fname" : %event.fname,
"duser" : %event.duser,
"sntdom" : %event.sntdom,
"dntdom" : %event.dntdom,
"sourceSessionId" : %event.sourceSessionId,
"targetSessionId" : %event.targetSessionId,
"msg" : join(["На хосте", (to_string(%event.dvchost) ?? "-"), "учетной записью",(to_string(%event.duser) ?? "-"), "выполнено чтение Ticket CCACHE файла", (to_string(%event.filePath) ?? "-"), "при помощи команды", (to_string(%event.cmd) ?? "-")], separator: " ") ?? "-",
"dhost" : %event.dhost,
"dvchost" : %event.dvchost,
"cs6Label" : %event.cs6Label,
"cs6" : %event.cs6,
"cs5Label" : %event.cs5Label,
"cs5" : %event.cs5,
"oldFileName" : %event.oldFileName,
"cs8Label" : %event.cs8Label,
"cs8" : %event.cs8,
"objPath" : %event.objPath,
"filePath" : %event.filePath,
"fileId" : %event.fileId,
"cs4" : %event.cs4,
"cs4Label" : %event.cs4Label,
"cs2" : %event.cs2,
"cs2Label" : %event.cs2Label
})
.correlationSeverity = 2
As for False Positive, a normal user probably wouldn't perform such actions, even though they might have access. However, if this correlation rule is triggered, you should analyze other logs from the host for unusual activity and contact the person responsible for the account.
Another common attack vector for any system is brute force attacks. Let's look at what can be done in FreeIPA.
Brute Force
Where would we be without the good old Brute Force (T1110.001)? For example, to simulate an attack we can use the tool kerbrute
.
Example command:
./kerbrute bruteuser -d <domain> <dictionary> <user>
The screenshot shows that the utility worked successfully and a valid password was found.
Let's take a look at the events that are generated after using this utility.
During all successful and unsuccessful login attempts, events will be generated in the standard FreeIPA log kerberos
on the way /var/log/krb5kdc.log
.
If the login attempt is unsuccessful, the following event is logged:
Here we will be interested in the following fields:
AS_REQ
– contains the event type. After normalization, it is placed in the fieldcat
;PREAUTH_FAILED
– indicates unsuccessful pre-authentication. Placed in the fieldact
after normalization;bruter@DOMAIN.LOCAL
– the name of the user attempting to login. After normalization, it is broken down into fieldsduser
Anddntdom
with the username and domain respectively;10.150.50.77
– host source of activity. After normalization, it is placed in the fieldshost
.If the login attempt was successful, an AS-REQ request event is generated:
In the successful authentication event, we are interested in the presence of the field ISSUE
(fits into the field act
after normalization), as it indicates that authentication was successful and a ticket was issued.
Based on the above events, two correlation rules can be implemented with the following logic:
Multiple unsuccessful Kerberos pre-authentication attempts.
After the first event with unsuccessful authentication, a 30-second correlation window opens and counts 10 unsuccessful attempts. We will determine unsuccessful attempts by the fieldact
and the presence of meaning in itPREAUTH_FAILED
.Rule for multiple unsuccessful user login attempts in R-Vision SIEM:
FreeIPA User Password Selection
id: dc8ea3bf-099d-4582-b313-71def8878dfc
name: Подбор пароля пользователя FreeIPA
type: correlation_rule
severity: medium
version: 1.0.0
status: stable
date: 2024-04-26
author: Ilya Efimov, R-Vision
description: В домене под управлением FreeIPA в качестве основного механизма аутентификации
используется протокол Kerberos. Использование данного протокола позволяет
производить атаки, аналогичные атакам на Active Directory. Одним из видов такой
атаки является перебор паролей для учетной записи.
Для получения доступа к учетной записи или хосту, атакующий может попробовать подобрать пароль с помощью перебора.
В случае возникновения активности необходимо опросить владельца учетной записи инициатора активности.
reference:
- https://www.thehacker.recipes/a-d/movement/kerberos/pre-auth-bruteforce
known_false_positives:
- Устаревшие сохраненные учетные данные на узле инициаторе
- Забытый пароль
data_source:
- FreeIPA
- KRB5KDC
tags:
- Credential Access
- Brute Force
- attack.T1110
- attack.T1110.001
filter: !vrl |
.dvendor == "FreeIPA" &&
contains(to_string(.fname) ?? "", "krb5kdc_log") &&
downcase(to_string(.cat) ?? "") == "as_req" &&
downcase(to_string(.act) ?? "") == "preauth_failed"
aliases:
pre_auth_fail:
filter: !vrl |
true
select:
alias: pre_auth_fail
group:
- alias: pre_auth_fail
by:
- duser
count: 10
ttl: 30
on_correlate: !vrl |
. |= compact({
"act" : %pre_auth_fail[0].act,
"suser" : %pre_auth_fail[0].suser,
"sproc" : %pre_auth_fail[0].sproc,
"dproc" : %pre_auth_fail[0].dproc,
"dpid" : %pre_auth_fail[0].dpid,
"shost" : %pre_auth_fail[0].shost,
"externalId" : %pre_auth_fail[0].externalId,
"cmd": %pre_auth_fail[0].cmd,
"fname" : %pre_auth_fail[0].fname,
"duser" : %pre_auth_fail[0].duser,
"sntdom" : %pre_auth_fail[0].sntdom,
"dntdom" : %pre_auth_fail[0].dntdom,
"sourceSessionId" : %pre_auth_fail[0].sourceSessionId,
"targetSessionId" : %pre_auth_fail[0].targetSessionId,
"msg" : join(["На хосте", (to_string(%pre_auth_fail[0].dvchost) ?? "-"), "под учетной записью",(to_string(%pre_auth_fail[0].duser) ?? "-"), "с доменом", (to_string(%pre_auth_fail[0].dntdom) ?? "-"), "зафиксированы множественные неуспешные попытки kerberos пре-аутентификации с хоста", (to_string(%pre_auth_fail[0].shost) ?? "-")], separator: " ") ?? "-",
"dhost" : %pre_auth_fail[0].dhost,
"dvchost" : %pre_auth_fail[0].dvchost,
"cs6Label" : %pre_auth_fail[0].cs6Label,
"cs6" : %pre_auth_fail[0].cs6,
"cs5Label" : %pre_auth_fail[0].cs5Label,
"cs5" : %pre_auth_fail[0].cs5,
"oldFileName" : %pre_auth_fail[0].oldFileName,
"cs8Label" : %pre_auth_fail[0].cs8Label,
"cs8" : %pre_auth_fail[0].cs8,
"objPath" : %pre_auth_fail[0].objPath,
"filePath" : %pre_auth_fail[0].filePath,
"fileId" : %pre_auth_fail[0].fileId,
"cs4" : %pre_auth_fail[0].cs4,
"cs4Label" : %pre_auth_fail[0].cs4Label,
"cs2" : %pre_auth_fail[0].cs2,
"cs2Label" : %pre_auth_fail[0].cs2Label
})
.correlationSeverity = 2
Successful guessing of a user's password after multiple unsuccessful Kerberos pre-authentication attempts. The logic is the same as in the case of unsuccessful attempts, but we look at one event with a successful attempt. We need to find an occurrence of the string
issue
in fieldact
.The rule for successfully guessing a password after many unsuccessful attempts:
Successful password guessing for FreeIPA user
id: 691e0f41-3763-465b-b92a-1d542dada346
name: Успешный подбор пароля пользователя FreeIPA
type: correlation_rule
severity: medium
version: 1.0.0
status: stable
date: 2024-04-26
author: Ilya Efimov, R-Vision
description: В домене под управлением FreeIPA в качестве основного механизма аутентификации
используется протокол Kerberos. Использование данного протокола позволяет
производить атаки, аналогичные атакам на Active Directory. Одним из видов такой
атаки является перебор паролей для учетной записи.
Для получения доступа к учетной записи или хосту, атакующий может попробовать подобрать пароль с помощью перебора.
В случае возникновения активности необходимо опросить владельца учетной записи инициатора активности.
reference:
- https://www.thehacker.recipes/a-d/movement/kerberos/pre-auth-bruteforce
known_false_positives:
- Устаревшие сохраненные учетные данные на узле инициаторе
- Забытый пароль
data_source:
- FreeIPA
- KRB5KDC
tags:
- Credential Access
- Brute Force
- attack.T1110
- attack.T1110.001
filter: !vrl |
.dvendor == "FreeIPA" &&
contains(to_string(.fname) ?? "", "krb5kdc_log") &&
downcase(to_string(.cat) ?? "") == "as_req"
aliases:
pre_auth_fail:
filter: !vrl |
downcase(to_string(.act) ?? "") == "preauth_failed"
pre_auth_success:
filter: !vrl |
downcase(to_string(.act) ?? "") == "issue"
select:
alias: pre_auth_fail
join:
alias: pre_auth_success
on:
- eq: { pre_auth_fail: duser, pre_auth_success: duser }
- eq: { pre_auth_fail: dntdom, pre_auth_success: dntdom }
- eq: { pre_auth_fail: shost, pre_auth_success: shost }
group:
- alias: pre_auth_fail
by:
- duser
count: 10
ttl: 30
on_correlate: !vrl |
. |= compact({
"act" : %pre_auth_fail[0].act,
"suser" : %pre_auth_fail[0].suser,
"sproc" : %pre_auth_fail[0].sproc,
"dproc" : %pre_auth_fail[0].dproc,
"dpid" : %pre_auth_fail[0].dpid,
"shost" : %pre_auth_fail[0].shost,
"externalId" : %pre_auth_fail[0].externalId,
"cmd": %pre_auth_fail[0].cmd,
"fname" : %pre_auth_fail[0].fname,
"duser" : %pre_auth_fail[0].duser,
"sntdom" : %pre_auth_fail[0].sntdom,
"dntdom" : %pre_auth_fail[0].dntdom,
"sourceSessionId" : %pre_auth_fail[0].sourceSessionId,
"targetSessionId" : %pre_auth_fail[0].targetSessionId,
"msg" : join(["На хосте", (to_string(%pre_auth_fail[0].dvchost) ?? "-"), "под учетной записью",(to_string(%pre_auth_fail[0].duser) ?? "-"), "с доменом", (to_string(%pre_auth_fail[0].dntdom) ?? "-"), "зафиксирована успешная попытка kerberos пре-аутентификации после множества неуспешных попыток пре-аутентификации с хоста", (to_string(%pre_auth_fail[0].shost) ?? "-")], separator: " ") ?? "-",
"dhost" : %pre_auth_fail[0].dhost,
"dvchost" : %pre_auth_fail[0].dvchost,
"cs6Label" : %pre_auth_fail[0].cs6Label,
"cs6" : %pre_auth_fail[0].cs6,
"cs5Label" : %pre_auth_fail[0].cs5Label,
"cs5" : %pre_auth_fail[0].cs5,
"oldFileName" : %pre_auth_fail[0].oldFileName,
"cs8Label" : %pre_auth_fail[0].cs8Label,
"cs8" : %pre_auth_fail[0].cs8,
"objPath" : %pre_auth_fail[0].objPath,
"filePath" : %pre_auth_fail[0].filePath,
"fileId" : %pre_auth_fail[0].fileId,
"cs4" : %pre_auth_fail[0].cs4,
"cs4Label" : %pre_auth_fail[0].cs4Label,
"cs2" : %pre_auth_fail[0].cs2,
"cs2Label" : %pre_auth_fail[0].cs2Label
})
.correlationSeverity = 2
False Positive may trigger in the following situations:
We've sorted out the detection of obtaining credentials, but what's next? Since you can access the FreeIPA server not only via the web, but also via ssh, I suggest considering the Command and Scripting Interpreter: Unix Shell technique as part of the tactics Execution.
Changing the login shell
Some shells may provide more features than the default one. sh
to execute scripts or commands (according to MITRE ATT&CK Command and Scripting Interpreter: Unix Shell (T1059.004)). Attackers can take advantage of the login shell change to increase their privileges in the system. This scheme is implemented through the function user_mod()
from FreeIPA API (must be specified) ipa
before entering the command). Function user_mod()
is designed to modify user accounts and allows you to change various parameters such as the Login Shell, password, home directory, etc.
FreeIPA allows you to change the Login Shell for any user in both the UI and CLI using the function ipa user-mod
.
Change via UI
You can change the login shell in the user interface in the account settings:
Events will be generated in the FreeIPA API call logs along the path /var/log/httpd/error_log
.
Login shell change event via FreeIPA UI:
The line that interests us in this event is INFO
(after normalization this field is transformed into the field cmd
), and specifically the presence of the function in it user_mod
and substrings loginshell
which indicates a change in the default login shell.
After logging in, we can see how the login shell has changed:
Changing via CLI
Changing the login shell is also available using the command:
ipa user-mod --shell=/bin/bash 'roaster'
In the parameter --shell
You need to specify the path to the shell that will be launched when the user logs in.
Output after executing the program:
At the same time, in the magazine /var/log/httpd/error_log
an event will be generated that is almost identical to the previous one, except for one thing:
You can see that when calling the function via the UI, the function was executed user_mod
and via the CLI – the function user_mod/1
. This always happens when calling all API functions. When changing the shell, no matter through the UI or CLI, events will be generated in the log /var/log/httpd/error_log
. On this basis, it is possible to implement a detection for the presence of substrings user_mod
And loginshell=
in field INFO
(field cmd
after normalization in R-Vision SIEM).
Rule for changing user login shell:
Changing the login shell using FreeIPA tools
id: 21fe2fbd-7fea-4d42-888f-f371875d20e8
name: Изменение оболочки входа при помощи средств FreeIPA
type: correlation_rule
severity: medium
version: 1.0.0
status: stable
date: 2024-04-24
author: Ilya Efimov, R-Vision
description: Некоторые оболочки могут предоставлять больше возможностей для выполнения скриптов или команд.
Злоумышленники могут воспользоваться изменением оболочки входа для повышения своих возможностей в системе.
Данный функционал реализовывается за счет функции user_mod() из функционала API FreeIPA (ipa user-mod) или при помощи смены оболочки пользователя в web-интерфейсе.
В случае возникновения активности требуется опросить пользователя, ответственного за учетную запись инициатора активности,
на предмет осуществления активности. В случае, если активность нелегитимна, заблокировать учетную запись инициатора активности.
reference:
- https://posts.specterops.io/attacking-freeipa-part-i-authentication-77e73d837d6a
- https://freeipa.readthedocs.io/en/latest/api/commands.html
known_false_positives:
- Не выявлено
data_source:
- FreeIPA
- HTTPD
tags:
- execution
- attack.T1059
- attack.T1059.004
filter: !vrl |
.dvendor == "FreeIPA" &&
contains(to_string(.fname) ?? "", "error_log") &&
contains_all(to_string(.cmd) ?? "", ["user_mod", "loginshell="], case_sensitive: false)
aliases:
change_login_shell:
filter: !vrl |
true
select:
alias: change_login_shell
ttl: 20
on_correlate: !vrl |
. |= compact({
"act" : %change_login_shell.act,
"suser" : %change_login_shell.suser,
"sproc" : %change_login_shell.sproc,
"dproc" : %change_login_shell.dproc,
"dpid" : %change_login_shell.dpid,
"externalId" : %change_login_shell.externalId,
"cmd": %change_login_shell.cmd,
"fname" : %change_login_shell.fname,
"duser" : %change_login_shell.duser,
"sntdom" : %change_login_shell.sntdom,
"dntdom" : %change_login_shell.dntdom,
"sourceSessionId" : %change_login_shell.sourceSessionId,
"targetSessionId" : %change_login_shell.targetSessionId,
"msg" : join(["На хосте", (to_string(%change_login_shell.dvchost) ?? "-"), "учетной записью",(to_string(%change_login_shell.suser) ?? "-"), "с доменом", (to_string(%change_login_shell.sntdom) ?? "-"), "выполнено изменение оболочки входа средствами FreeIPA для пользователя", (to_string(%change_login_shell.duser) ?? "-"),"на оболочку", (to_string(%change_login_shell.cs1) ?? "-"), ". Хост инициатор активности:", (to_string(%change_login_shell.shost) ?? "-")], separator: " ") ?? "-",
"dhost" : %change_login_shell.dhost,
"dvchost" : %change_login_shell.dvchost,
"cs6Label" : %change_login_shell.cs6Label,
"cs6" : %change_login_shell.cs6,
"cs5Label" : %change_login_shell.cs5Label,
"cs5" : %change_login_shell.cs5,
"oldFileName" : %change_login_shell.oldFileName,
"cs8Label" : %change_login_shell.cs8Label,
"cs8" : %change_login_shell.cs8,
"objPath" : %change_login_shell.objPath,
"filePath" : %change_login_shell.filePath,
"fileId" : %change_login_shell.fileId,
"cs4" : %change_login_shell.cs4,
"cs4Label" : %change_login_shell.cs4Label
})
.correlationSeverity = 2
Let's take a look at the critical services that make FreeIPA work.
Stopping critical services
One of the popular techniques in tactics Impact is Service Stop (T1489). Attackers can disable services that are critical to the system's operation, making it inaccessible to ordinary legitimate users. Since FreeIPA is installed on Linux, all configuration files, services, and executable files for management will be standard for Linux systems – they can be monitored, for example, via Auditd. There are many services running on the IPA server, but we can highlight the most critical ones, stopping and disabling which can harm both the performance of FreeIPA itself and its security.
These services include:
ipa
– the main FreeIPA service that manages the LDAP server, Kerberos KDC, DNS, and other components. Stopping the main IPA service can disable the entire centralized identification and authentication management system, making it impossible to manage users, groups, hosts, and security policies.ipa-custodia
– a service responsible for secure storage and transmission of secret data between FreeIPA servers. Stopping IPA Custodia will stop secure transmission and storage of keys and secrets.ipa-ccache-sweep
(IPA Credential Cache Sweep) is a service for managing and cleaning cached credentials in IPA. Without regular cleaning of stale cached credentials, the risk of using compromised or stale accounts increases, which can lead to a CCACHE ticket theft attack.krb5kdc
– manages the issuance and verification of Kerberos tickets, which are used to authenticate users and services on the network. Stopping the Kerberos KDC will stop issuing and verifying Kerberos tickets. This will make it impossible to authenticate users and services, effectively paralyzing the entire authentication system and disrupting access to network resources.dirsrv
– refers to the Directory Server (LDAP server). This service manages the directory containing information about users, groups, hosts and other objects on the network. The directory is also responsible for authentication and authorization of users and devices in the domain. If disabled, users will lose the ability to authenticate in the domain and the operation of other FreeIPA services will be disrupted: Kerberos, DNS and PKI.
After disabling the service, an event will be generated in Auditd:
In this event we are interested in the following fields:
type
(deviceProcessName
after normalization)=SERVICE_STOP – this field value indicates that the service has been stopped;unit
(destinationServiceName
after normalization) – the name of the service that was stopped.
If the service is stopped ipa
then all other services specified above will also stop. With the help of such events, it is possible to implement a detection for disabling services that are critical for the functionality of FreeIPA. It is necessary to monitor the field cat
for the presence of meaning SERVICE_STOP
and the name of the critical FreeIPA service in the field destinationServiceName
.
The full rule code can be found under the spoiler:
Stop/Restart FreeIPA services
id: fda17910-b679-44de-9908-b5b7edbebd41
name: Остановка/перезапуск сервисов FreeIPA
version: 1.0.0
date: 27.04.2024
author: Aleksey Epishev, R-Vision
status: stable
type: correlation_rule
severity: medium
description: Для работы сервера freeipa по умолчанию устанавливается несколько сервисов.
Для применения изменения многих конфигураций требуется перегазагрузка сервисов.
Злоумышленник может перезапустить или остановить сервисы для отключения функционала или подмены легитимных сервисов на вредоносные.
tags:
- attack.T1543.002
- attack.T1543
- linux
data_source:
- Linux
- auditd
known_false_positives:
- Действия администратора
- Установка/обновления FreeIPA
aliases:
event:
filter: !vrl |
bin_list=["ipa", "ipa-custodia", "ipa-dnskeysyncd", "ipa-otpd", "ipa-ccache-sweep", "httpd-init", "httpd", "krb5kdc", "dirsrv"]
.dvendor == "Linux" &&
.cat == "SERVICE_STOP" &&
includes(bin_list, .destinationServiceName)
select:
alias: event
ttl: 10
on_correlate: !vrl
.correlationSeverity = 2
.dvchost = %event.dvchost
.duser = %event.duser
.suser = %event.duser
.dproc = %event.dproc
.filePath = %event.filePath
.msg = "На хосте " + (to_string(.dvchost) ?? "-") + " пользователь " + (to_string(.duser) ?? "-") + " оставновил критичный сервис FreeIPA " + (to_string(.filePath) ?? "-") + " с помощью процесса " + (to_string(.dproc) ?? "-")
I suggest looking at the inheritance hierarchy of rights in FreeIPA. It differs from what we are used to in Active Directory.
Abuse of IPA roles and privileges
FreeIPA has 3 main entities for assigning rights to users: Permissions, Privileges and Roles.
All of them are closely interconnected with each other:
Permissions (Permissions) – initial rights that are granted to specific attributes in the system.
Privileges (Privileges) – a set of different Permissions.
Role (Roles) – include various Privileges and can be assigned to users.
Permissions
First, let's take a quick look at permissions. Permissions allow you to grant access to specific user attributes. The most critical ones can be found using the following keywords:
"krb","admin", "trust","sudo", "services", "vaults", "permissions","privileges","roles","ssh", "private", "selinux", "secret", "users", "ipanthas", "userpassword"
Conventionally, these are point accesses that can be grouped into privileges.
Privileges
Privileges do not contain any rights by themselves. They can be assigned permissions using the following commands:
privilege-add-permission
privilege-mod
The system contains more than 30 standard privileges. You can find them using the command privilege-find
The most critical privileges will be those containing the words: “admin”, “sudo”, “selinux”, “kerberos”, “enrollment”, “manager”.
Below is the event generated when a permission is added System: Read User Kerberos Login Attributes
. This permission allows read access to the Kerberos attributes in the privilege. test_privileges
.
In the event we see that in the field INFO
(cmd
after normalization) contains the command privilege_add_permission
which adds to the privilege test_privileges
permission Read User Kerberos Login Attributes
(in field permission=
).
Based on this, you can implement detection using field checking cmd
for the presence of words inherent in critical permissions and the presence in the same line of commands for adding and modifying privileges.
To detect privilege changes we have the following rule:
Changing Privilege Configurations in FreeIPA
id: 74296c4d-6121-437a-9f6a-7d6d378ad0g6
name: Изменение конфигураций привилегий в FreeIPA
version: 1.0.0
date: 01.06.2024
author: Alexey Episev, R-Vision
status: stable
type: correlation_rule
severity: high
description: Обнаружение использования команд добавления админских прав в привилегии FreeIPA.
Злоумышленники могут изменять привилегии для закрепления в системе и повышения привилегий на доменных хостах.
tags:
- attack.T1548.003
- attack.T1548
- attack.persistence
- linux
data_source:
- FreeIPA
known_false_positives:
- Действия администратора по добавлению привилегий
- Добавление новых привилегированных пользователей
aliases:
event:
filter: !vrl |
.dvendor == "FreeIPA" &&
cmd = downcase(to_string(.cmd) ?? "")
permissions=["kerberos","admin","manag","sudo", "trust","privilege","modify",
"selinux","roles","ssh","enroll","delete","add","vault"]
filt=false
for_each(permissions) -> |_index, value| {
if contains(cmd,value) == true {
filt = true
}
}
if filt==true && (contains(cmd, "privilege_add_permission") || contains(cmd, "privilege_mod"))
{ true } else { false }
}
select:
alias: event
ttl: 10
on_correlate: !vrl |
.correlationSeverity = 3
.dvchost = %event.dvchost
.msg = %event.msg
.suser = %event.suser
.dproc = %event.dproc
.cmd = %event.cmd
.msg = "На хосте " + (to_string(.dvchost) ?? "-") + " пользователь " + (to_string(.suser) ?? "-") + " изменил изменил привилегии FreeIPA с помощью команды " + (to_string(.cmd) ?? "-")
We have created privileges, now we need to assign them to roles.
Roles
Roles can be assigned various privileges via the web interface or using commands:
role-mod
role-add-privilege
Furthermore, roles can be assigned to users also through the web interface or using the command:
role-add-member
Let's look at an example of an event with the addition of a privilege Sudo Administrator
roles test_role
:
In the event we see that in the field INFO
(cmd) contains the command role_add_privilege
which adds roles test_role
privilege Sudo Administrator
(specified in the field privilege=
). Privilege Sudo Administartor
has permissions to manage the team sudo
(adding users to groups sudo
adding commands for sudo
etc.).
The system also contains standard roles with increased privileges:
Based on this information, you can implement detection by checking the field cmd
for the presence of words inherent in critical privileges and the presence in the same line of commands for assigning and modifying roles.
To detect role changes we have the following rule:
Changing Role Configurations in FreeIPA
id: 7409eefb-c10b-4be6-8f47-7833c6cce304
name: Изменение конфигураций ролей в FreeIPA
version: 1.0.0
date: 01.06.2024
author: Alexey Episev, R-Vision
status: stable
type: correlation_rule
severity: high
description: Обнаружение использования команд добавления админских прав в привилегии и их назначение ролям FreeIPA.
Злоумышленники могут изменять роли для закрепления в системе и повышения привилегий на доменных хостах.
tags:
- attack.T1548.003
- attack.T1548
- attack.persistence
- linux
data_source:
- FreeIPA
known_false_positives:
- Действия администратора по добавлению ролей
- Добавление новых привилегированных пользователей
aliases:
event:
filter: !vrl |
.dvendor == "FreeIPA" &&
cmd = downcase(to_string(.cmd) ?? "")
if (((contains(cmd, "role_add_privilege") || contains(cmd, "role-mod")) && ((contains(cmd, "admin") || contains(cmd, "sudo") || contains(cmd, "selinux") || contains(cmd, "kerberos") ||
contains(cmd, "enrollment") || contains(cmd, "manager"))) ||
(contains(cmd, "role_add_member") && ((contains(cmd, "admin") || contains(cmd, "manager"))) )))
{ true } else { false }
}
select:
alias: event
ttl: 10
on_correlate: !vrl |
.correlationSeverity = 3
.dvchost = %event.dvchost
.msg = %event.msg
.suser = %event.suser
.dproc = %event.dproc
.cmd = %event.cmd
.msg = "На хосте " + (to_string(.dvchost) ?? "-") + " пользователь " + (to_string(.suser) ?? "-") + " изменил изменил роль FreeIPA с помощью команды " + (to_string(.cmd) ?? "-")
Conclusion
In this article, we have considered several attack scenarios on the FreeIPA domain services system and their detection. We have analyzed methods of compromising credentials via Kerberos CCACHE and brute force attack methods, executing commands via Unix Shell, stopping and restarting critical services, and abusing critical roles and privileges.
Key findings and recommendations:
Steal or Forge Kerberos Tickets: it is important to protect
Kerberos
CCACHE files. This requires setting up Auditd to monitor access to them. This allows for prompt detection of unauthorized use of tickets.Brute Force: analyze log
Kerberos
to identify brute force attacks and configure appropriate correlation rules to detect them.Login Shell: Monitor user login shell changes and set up monitoring rules to detect unauthorized changes via the FreeIPA API.
Service Stop: monitor the status of critical FreeIPA services and ensure their stable operation to prevent attacks that can disable the system.
Roles and Privileges: exercise careful control over the creation and modification of critical roles, privileges and permissions in the FreeIPA system to minimize the risks of privilege escalation by attackers.
Implementation of the proposed measures will improve the security and resistance of FreeIPA to various types of attacks, ensuring reliable protection of your network's domain infrastructure.
This article does not describe all the rules that we have for FreeIPA, otherwise it would be even longer. If you are interested in the rest of the rules, I am ready to discuss them in the comments.