Study of attacks and defense strategies

Microsoft Active Directory (AD).

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:

  1. Web server:

    • used to configure policies and manage accounts;

    • implemented on the basis of Apache HTTP Server.

  2. Directory Server 389:

    • provides centralized storage of data about users and resources;

    • uses LDAP (Lightweight Directory Access Protocol).

  3. 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.

  4. NTP (Network Time Protocol):

    • synchronizes time between all system components;

    • provides accurate time, which is critical for authentication and security.

  5. DNS:

    • manages domain names and their resolution into IP addresses;

    • Includes support for SRV records for Kerberos and LDAP.

  6. 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.

Parsing CCHACHE file

Parsing CCHACHE file

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.

Contents of CCHACHE file

Contents of CCHACHE file

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:

CCACHE file access event in R-Vision SIEM

CCACHE file access event in R-Vision SIEM

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_1472000008After normalization, this field is calledfilePath. If the CCACHE file is accessed from /tmpthe path will be specified in the field cwd= (after normalization this field objPath).

  • Syscol number (syscall=). In our case, the number 257which means openat – opening a file. After normalization, this field is called cs4.

  • The rights with which the appeal was made (a2=), are equal 0which means opening the file for reading. After normalization, this field is called filePermission.

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 /tmpwith read permissions r.

The figure below shows an example of such a rule in R-Vision SIEM:

Rule for detecting reading of CCACHE file in R-Vision SIEM

Rule for detecting reading of CCACHE file 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>
Brute force password of user bruter

Brute force password of user bruter

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:

500

Event with unsuccessful attempt to log in to R-Vision SIEM

Here we will be interested in the following fields:

  • AS_REQ – contains the event type. After normalization, it is placed in the field cat;

  • PREAUTH_FAILED – indicates unsuccessful pre-authentication. Placed in the field act after normalization;

  • bruter@DOMAIN.LOCAL – the name of the user attempting to login. After normalization, it is broken down into fields duser And dntdom with the username and domain respectively;

  • 10.150.50.77 – host source of activity. After normalization, it is placed in the field shost.

    If the login attempt was successful, an AS-REQ request event is generated:

500

Event with successful authentication and ticket issuance

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 field act and the presence of meaning in it PREAUTH_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 field act.

    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:

How to change user login shell via FreeIPA UI

How to change user login shell via FreeIPA UI

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:

400

Event about changing user login shell via R-Vision SIEM 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 loginshellwhich indicates a change in the default login shell.

After logging in, we can see how the login shell has changed:

Active login shell

Active login shell

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:

400

Output after changing shell via CLI

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:

500

Output after changing shell via CLI

You can see that when calling the function via the UI, the function was executed user_modand 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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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:

400

IPA service stop event

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 ipathen 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-findThe 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.

500

Event of adding privilege to permission from error_log

In the event we see that in the field INFO (cmd after normalization) contains the command privilege_add_permissionwhich 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
Adding Sudo Administrator privilege to test_role role

Adding Sudo Administrator privilege to test_role role

Let's look at an example of an event with the addition of a privilege Sudo Administrator roles test_role:

500

Privilege role add event from error_log

In the event we see that in the field INFO (cmd) contains the command role_add_privilegewhich 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 sudoadding commands for sudo etc.).

The system also contains standard roles with increased privileges:

Standard roles with elevated privileges

Standard roles with elevated 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:

  1. 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.

  2. Brute Force: analyze log Kerberos to identify brute force attacks and configure appropriate correlation rules to detect them.

  3. Login Shell: Monitor user login shell changes and set up monitoring rules to detect unauthorized changes via the FreeIPA API.

  4. Service Stop: monitor the status of critical FreeIPA services and ensure their stable operation to prevent attacks that can disable the system.

  5. 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.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *