Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
[metadata]
creation_date = "2026/03/28"
integration = ["freeipa"]
maturity = "development"
updated_date = "2026/03/28"

[rule]
author = ["Elastic"]
description = """
Identifies LDAP search operations against the FreeIPA 389 Directory Server that return an unusually large number of
entries in a single query. Large result sets from subtree searches against the domain base DN indicate bulk directory
data exfiltration. SSSD clients typically perform targeted searches returning small result sets.
"""
false_positives = [
"""
Legitimate LDAP replication, backup tools, or directory synchronization agents may perform large queries.
Exclude known replication manager DNs and backup service IPs. SSSD clients performing group cache refreshes
may return moderately large result sets but typically stay well below 500 entries per query.
""",
]
from = "now-9m"
interval = "5m"
language = "esql"
license = "Elastic License v2"
name = "FreeIPA LDAP Mass Data Exfiltration"
note = """## Triage and analysis

### Investigating FreeIPA LDAP Mass Data Exfiltration

Large LDAP searches against FreeIPA can expose user details, group memberships, SSH public keys, sudo rules, HBAC policies, and other sensitive directory data. An attacker with authenticated LDAP access can dump the entire directory for offline analysis.

### Possible investigation steps

- Check `freeipa.directory.bind_dn` to identify the account performing the search.
- Review `freeipa.directory.base_dn`, `freeipa.directory.scope`, and `freeipa.directory.filter` to understand what was queried.
- Check `freeipa.directory.entries_returned` to quantify the exposure.
- Correlate with `source.ip` to identify the origin.
- Determine if the bind DN is a legitimate service account, replication manager, or a compromised user.

### Response and remediation

- Block the source IP if unauthorized.
- Reset credentials for the bind DN if compromised.
- Review LDAP ACIs to restrict the maximum entries returned per query.
- Implement `nsslapd-sizelimit` to cap LDAP result sizes for non-admin users.
"""
references = [
"https://attack.mitre.org/techniques/T1213/",
"https://specterops.io/blog/2019/12/04/attacking-freeipa-part-ii-enumeration/",
]
risk_score = 47
rule_id = "f8a1b2c3-4d5e-6f7a-8b9c-0d1e2f3a4b5c"
setup = """## Setup

This rule requires the FreeIPA integration to be installed and configured to collect logs from FreeIPA servers.

### FreeIPA Integration Setup
1. Install the FreeIPA integration in Kibana Fleet.
2. Add the integration to an Elastic Agent policy deployed on your FreeIPA server(s).
3. Ensure the relevant log paths are accessible:
- 389DS access: `/var/log/dirsrv/slapd-*/access` (directory_access data stream)
"""
severity = "medium"
tags = [
"Domain: Identity",
"Data Source: FreeIPA",
"Data Source: FreeIPA Directory Server",
"Use Case: Threat Detection",
"Tactic: Collection",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-freeipa.directory_access-*
| where freeipa.directory.operation == "RESULT"
and freeipa.directory.entries_returned >= 500
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1213"
name = "Data from Information Repositories"
reference = "https://attack.mitre.org/techniques/T1213/"


[rule.threat.tactic]
id = "TA0009"
name = "Collection"
reference = "https://attack.mitre.org/tactics/TA0009/"

[rule.investigation_fields]
field_names = [
"@timestamp",
"source.ip",
"freeipa.directory.bind_dn",
"freeipa.directory.base_dn",
"freeipa.directory.scope",
"freeipa.directory.filter",
"freeipa.directory.entries_returned",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
[metadata]
creation_date = "2026/03/28"
integration = ["freeipa"]
maturity = "development"
updated_date = "2026/03/28"

[rule]
author = ["Elastic"]
description = """
Identifies a FreeIPA API password reset command (passwd) executed by a principal that is not the target user. An
adversary who has compromised an account with password reset privileges can use this to take over other accounts
without knowing their current password. Self-service password changes are expected and excluded.
"""
false_positives = [
"""
Helpdesk staff or administrators performing authorized password resets will trigger this rule. Exclude known
admin principals if they routinely perform password resets. Automated password rotation systems that use a
service account to reset passwords may also trigger this rule.
""",
]
from = "now-9m"
interval = "5m"
language = "esql"
license = "Elastic License v2"
name = "FreeIPA Password Reset by Another User"
note = """## Triage and analysis

### Investigating FreeIPA Password Reset by Another User

FreeIPA's `passwd` API command allows privileged users to reset another user's password. While this is a legitimate helpdesk operation, it is also a common post-compromise action — an attacker with admin or helpdesk privileges can reset target account passwords to gain access.

### Possible investigation steps

- Identify the actor by examining `user.name` and `user.id` — this is the principal who performed the reset.
- Identify the target account from `freeipa.api.parameters` — this is the account whose password was changed.
- Verify the reset was authorized through a ticket system or change management workflow.
- Check `source.ip` to determine where the reset originated.
- Review the actor's recent API activity for other suspicious commands (role changes, group modifications).
- Check if the target account had subsequent authentication activity from a new or suspicious source.

### Response and remediation

- If unauthorized, immediately reset the target account's password again and revoke all active sessions.
- Investigate the actor's account for compromise — reset their credentials and review their permissions.
- Review who has password reset privileges and apply least privilege principles.
- Consider requiring OTP/2FA for password reset operations.
"""
references = [
"https://attack.mitre.org/techniques/T1098/",
"https://www.freeipa.org/page/V4/OTP",
]
risk_score = 73
rule_id = "5a2c9b06-b1b2-4552-9b82-19646a8bc3ad"
setup = """## Setup

This rule requires the FreeIPA integration to be installed and configured to collect logs from FreeIPA servers.

### FreeIPA Integration Setup
1. Install the FreeIPA integration in Kibana Fleet.
2. Add the integration to an Elastic Agent policy deployed on your FreeIPA server(s).
3. Ensure the relevant log paths are accessible:
- IPA API: `/var/log/httpd/error_log` (ipa_api data stream)
"""
severity = "high"
tags = [
"Domain: Identity",
"Data Source: FreeIPA",
"Data Source: FreeIPA API",
"Use Case: Threat Detection",
"Use Case: Identity and Access Audit",
"Tactic: Credential Access",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-freeipa.ipa_api-*
| where event.action == "passwd" and event.outcome == "success"
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"


[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"

[rule.investigation_fields]
field_names = [
"@timestamp",
"user.name",
"user.id",
"source.ip",
"event.action",
"event.outcome",
"freeipa.api.parameters",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
[metadata]
creation_date = "2026/03/28"
integration = ["freeipa"]
maturity = "development"
updated_date = "2026/03/28"

[rule]
author = ["Elastic"]
description = """
Identifies a high number of Kerberos pre-authentication failures for a single principal from a single source IP,
indicative of a password guessing attack against a FreeIPA KDC. Adversaries may attempt to brute-force Kerberos
credentials to gain initial access to the domain. The default threshold of 25 failures in 5 minutes should be tuned
to match the target environment's normal authentication patterns and lockout policy.
"""
false_positives = [
"""
Misconfigured clients or services with expired credentials may generate repeated pre-authentication failures.
Tune the threshold to match the environment's account lockout policy. Exclude known service accounts or
monitoring systems that perform frequent authentication checks.
""",
]
from = "now-9m"
interval = "5m"
language = "esql"
license = "Elastic License v2"
name = "FreeIPA Kerberos Brute Force Attempt"
note = """## Triage and analysis

### Investigating FreeIPA Kerberos Brute Force Attempt

FreeIPA uses MIT Kerberos for authentication. When a user provides incorrect credentials, the KDC responds with a PREAUTH_FAILED error. A high volume of these errors for a single principal indicates a password guessing attack. This rule uses a threshold that should be tuned to the environment — review the domain's password lockout policy and set the threshold below the lockout limit to catch attacks before lockout occurs.

### Possible investigation steps

- Identify the targeted principal from `freeipa.kdc.client_principal` and determine if it is a high-value account (admin, service account, etc.).
- Check `source.ip` and `source.geo` to determine the origin of the attack. External IPs are higher risk.
- Query for any successful authentication (`event.outcome:success`) for the same principal around the same time window to check if the brute force succeeded.
- Check if the account was locked out by looking for `freeipa.kdc.error_code:LOCKED_OUT` events for the same principal.
- Correlate with the `directory_access` data stream for LDAP bind failures from the same `source.ip`.
- Review whether other principals were also targeted from the same source (indicating password spraying rather than targeted brute force).

### Response and remediation

- If the source is external, block the IP at the firewall or network perimeter.
- If the account was compromised (successful auth observed), reset the password immediately and revoke active Kerberos tickets.
- Review and enforce account lockout policies via `ipa pwpolicy-mod`.
- Consider enabling FreeIPA OTP/2FA for targeted high-value accounts.
- Monitor for follow-up activity from the source IP across all data streams.
"""
references = [
"https://attack.mitre.org/techniques/T1110/001/",
"https://specterops.io/blog/2019/11/25/attacking-freeipa-part-i-authentication/",
"https://book.hacktricks.xyz/linux-hardening/freeipa-pentesting",
]
risk_score = 73
rule_id = "814d541d-24fd-464f-b6a4-38988a18ba55"
setup = """## Setup

This rule requires the FreeIPA integration to be installed and configured to collect logs from FreeIPA servers.

### FreeIPA Integration Setup
1. Install the FreeIPA integration in Kibana Fleet.
2. Add the integration to an Elastic Agent policy deployed on your FreeIPA server(s).
3. Ensure the relevant log paths are accessible:
- KDC: `/var/log/krb5kdc.log` (kdc data stream)
"""
severity = "high"
tags = [
"Domain: Identity",
"Data Source: FreeIPA",
"Data Source: FreeIPA KDC",
"Use Case: Threat Detection",
"Use Case: Identity and Access Audit",
"Tactic: Credential Access",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-freeipa.kdc-*
| where event.outcome == "failure"
and freeipa.kdc.client_principal not like "*/*"
| stats Esql.failure_count = count(*) by freeipa.kdc.client_principal, source.ip
| where Esql.failure_count >= 25
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1110"
name = "Brute Force"
reference = "https://attack.mitre.org/techniques/T1110/"
[[rule.threat.technique.subtechnique]]
id = "T1110.001"
name = "Password Guessing"
reference = "https://attack.mitre.org/techniques/T1110/001/"


[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"

[rule.investigation_fields]
field_names = [
"@timestamp",
"source.ip",
"source.geo.country_name",
"freeipa.kdc.client_principal",
"freeipa.kdc.error_code",
"freeipa.kdc.request_type",
"event.outcome",
"Esql.failure_count",
]
Loading
Loading