Skip to content
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

Fix ldap_login and smb_login #19843

Merged
merged 1 commit into from
Jan 29, 2025

Conversation

cdelafuente-r7
Copy link
Contributor

@cdelafuente-r7 cdelafuente-r7 commented Jan 29, 2025

This fixes #19743.
This also apply the same fix to the smb_login login scanner.

The problem is that now, some login scanner modules are not only used to discover and report valid credentials, but also to get a session (e.g. SMB session, LDAP session). This means, if Kerberos is used as the authentication method, the user can omit the password and reuse tickets from the cache. Also, if the authentication method is Schannel (LDAP), the username can also be omitted since the certificate will contain everything needed to authenticate.

This causes issues with the validation and when the scanner iterates over the possible credentials to test. To fix, this, this PR introduces two new boolean attributes in the CredentialCollection class:

  • :ignore_private: Whether to ignore private (password).
  • :ignore_public: Whether to ignore public (username).

By setting these attributes to true, the scanner knows the password and/or the username can be nil and will carry-on.

Verification

Make sure the smb_session_type and ldap_session_type features are enabled with the features command.

LDAP login scanner with Kerberos authentication

  • use scanner/ldap/ldap_login
  • First run to get Kerberos tickets: run verbose=true rhost=<remote host> domain=<domain> LDAP::Auth=kerberos LDAP::Rhostname=<DC hostname> DomainControllerRhost=<DC IP address> CreateSession=true username=<admin username> password=<admin password>
  • Verify the tickets were retrieved with klist
  • Verify an LDAP session has been established
  • Retry without password: run verbose=true rhost=<remote host> domain=<domain> LDAP::Auth=kerberos LDAP::Rhostname=<DC hostname> DomainControllerRhost=<DC IP address> CreateSession=true username=<admin username>
  • Verify the cached credentials were used ([*] Using cached credential for ...)
  • Verify another LDAP session has been established
  • Retry without username: run verbose=true rhost=<remote host> domain=<domain> LDAP::Auth=kerberos LDAP::Rhostname=<DC hostname> DomainControllerRhost=<DC IP address> CreateSession=true
  • Verify a validation error is returned

LDAP login scanner with Schannel authentication

  • Get a certificate:
  • use admin/dcerpc/icpr_cert
  • run verbose=true CA=<CA> RHOSTS=<remote host> username=<admin username> password=<admin password> CERT_TEMPLATE=User
  • Run the LDAP login scanner without credentials:
  • use scanner/ldap/ldap_login
  • run verbose=true rhost=<target host> domain=<domain> LDAP::Auth=schannel rport=389 ssl=true LDAP::CertFile=<certificate filepath> CreateSession=true
  • Verify an LDAP session has been established

SMB login scanner with Kerberos authentication

  • use scanner/smb/smb_login
  • First run to get Kerberos tickets: run verbose=true rhost=<remote host> domain=<domain> SMB::Auth=kerberos SMB::Rhostname=<DC hostname> DomainControllerRhost=<DC IP address> CreateSession=true username=<admin username> password=<admin password>
  • Verify the tickets were retrieved with klist
  • Verify a SMB session has been established
  • Retry without password: run verbose=true rhost=<remote host> domain=<domain> SMB::Auth=kerberos SMB::Rhostname=<DC hostname> DomainControllerRhost=<DC IP address> CreateSession=true username=<admin username>
  • Verify the cached credentials were used ([*] Using cached credential for ...)
  • Verify another LDAP session has been established
  • Retry without username: run verbose=true rhost=<remote host> domain=<domain> SMB::Auth=kerberos SMB::Rhostname=<DC hostname> DomainControllerRhost=<DC IP address> CreateSession=true
  • Verify a validation error is returned

Scenarios

Without the fix

msf6 auxiliary(scanner/ldap/ldap_login) > run verbose=true rhost=10.187.44.121 domain=mydomain.local LDAP::Auth=schannel rport=389 ssl=true LDAP::CertFile=/home/n00tmeg/.msf4/loot/20250129113440_default_10.187.44.121_windows.ad.cs_600851.pfx
[*] Error: 10.187.44.121: Metasploit::Framework::LoginScanner::Invalid Cred details can't be blank, Cred details can't be blank (Metasploit::Framework::LoginScanner::LDAP)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Bruteforce completed, 0 credentials were successful.
[*] 0 LDAP sessions were opened successfully.
[*] Auxiliary module execution completed

With the fix

msf6 auxiliary(scanner/ldap/ldap_login) > run verbose=true rhost=10.187.44.121 domain=mydomain.local LDAP::Auth=schannel rport=389 ssl=true LDAP::CertFile=/home/n00tmeg/.msf4/loot/20250129113440_default_10.187.44.121_windows.ad.cs_600851.pfx
[+] Success: 'Cert File /home/n00tmeg/.msf4/loot/20250129113440_default_10.187.44.121_windows.ad.cs_600851.pfx'
[*] LDAP session 7 opened (192.168.211.69:41643 -> 10.187.44.121:389) at 2025-01-29 11:37:46 +0100
[*] Scanned 1 of 1 hosts (100% complete)
[*] Bruteforce completed, 1 credential was successful.
[*] 1 LDAP session was opened successfully.
[*] Auxiliary module execution completed

@jheysel-r7 jheysel-r7 self-assigned this Jan 29, 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.

Thanks for the fix @cdelafuente-r7. LGTM 👍

Testing

Before - Cred details can't be blank

  • LDAP login scanner with Kerberos authentication
msf6 auxiliary(scanner/ldap/ldap_login) > run verbose=true rhost=172.16.199.200 domain=kerberos.issue LDAP::Auth=kerberos LDAP::Rhostname=dc2.kerberos.issue
[*] Error: 172.16.199.200: Metasploit::Framework::LoginScanner::Invalid Cred details can't be blank, Cred details can't be blank (Metasploit::Framework::LoginScanner::LDAP)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Bruteforce completed, 0 credentials were successful.
[*] 0 LDAP sessions were opened successfully.
[*] Auxiliary module execution completed
  • LDAP login scanner with Schannel authentication
msf6 auxiliary(admin/dcerpc/icpr_cert) > run CA=demo-DC1-CA RHOSTS=172.16.199.100 SMBDomain=demo.lab SMBPass=N0tpassword! SMBUser=Administrator
[*] Running module against 172.16.199.100
[+] 172.16.199.100:445 - The requested certificate was issued.
[*] 172.16.199.100:445 - Certificate Policies:
[*] 172.16.199.100:445 - Certificate UPN: [email protected]
[*] 172.16.199.100:445 - Certificate stored at: /Users/jheysel/.msf4/loot/20250129121050_default_172.16.199.100_windows.ad.cs_497189.pfx
[*] Auxiliary module execution completed


msf6 auxiliary(scanner/ldap/ldap_login) > run verbose=true rhost=172.16.199.100 domain=demo.lab LDAP::Auth=schannel LDAP::CertFile=/Users/jheysel/.msf4/loot/20250129121050_default_172.16.199.100_windows.ad.cs_497189.pfx ssl=true rport=389 CreateSession=true
[*] Error: 172.16.199.100: Metasploit::Framework::LoginScanner::Invalid Cred details can't be blank, Cred details can't be blank (Metasploit::Framework::LoginScanner::LDAP)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Bruteforce completed, 0 credentials were successful.
[*] 0 LDAP sessions were opened successfully.
[*] Auxiliary module execution completed
  • SMB login scanner with Kerberos authentication
msf6 auxiliary(scanner/smb/smb_login) > run verbose=true rhost=172.16.199.200 domain=kerberos.issue SMB::Auth=kerberos SMB::Rhostname=dc2.kerberos.issue DomainControllerRhost=172.16.199.200 CreateSession=true username=Administrator password=N0tpassword!
[*] 172.16.199.200:445    - 172.16.199.200:445 - Starting SMB login bruteforce
[+] 172.16.199.200:445    - 172.16.199.200:88 - Received a valid TGT-Response
[*] 172.16.199.200:445    - 172.16.199.200:445    - TGT MIT Credential Cache ticket saved to /Users/jheysel/.msf4/loot/20250129122023_default_172.16.199.200_mit.kerberos.cca_951406.bin
[+] 172.16.199.200:445    - 172.16.199.200:88 - Received a valid TGS-Response
[*] 172.16.199.200:445    - 172.16.199.200:445    - TGS MIT Credential Cache ticket saved to /Users/jheysel/.msf4/loot/20250129122023_default_172.16.199.200_mit.kerberos.cca_736367.bin
[+] 172.16.199.200:445    - 172.16.199.200:88 - Received a valid delegation TGS-Response
[+] 172.16.199.200:445    - 172.16.199.200:445 - Success: 'kerberos.issue\Administrator:N0tpassword!' Administrator
[*] SMB session 2 opened (172.16.199.1:58318 -> 172.16.199.200:445) at 2025-01-29 12:20:24 -0800
[*] 172.16.199.200:445    - Scanned 1 of 1 hosts (100% complete)
[*] 172.16.199.200:445    - Bruteforce completed, 1 credential was successful.
[*] 172.16.199.200:445    - 1 SMB session was opened successfully.
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/smb/smb_login) >  klist
Kerberos Cache
==============
id  host            principal                     sname                                   enctype  issued                     status  path
--  ----            ---------                     -----                                   -------  ------                     ------  ----
6   172.16.199.200  [email protected]  krbtgt/[email protected]    AES256   2025-01-29 12:20:23 -0800  active  /Users/jheysel/.msf4/loot/20250129122023_default_172.16.199.200_mit.kerberos.cca_951406.bin
7   172.16.199.200  [email protected]  cifs/[email protected]  AES256   2025-01-29 12:20:23 -0800  active  /Users/jheysel/.msf4/loot/20250129122023_default_172.16.199.200_mit.kerberos.cca_736367.bin

msf6 auxiliary(scanner/smb/smb_login) > run verbose=true rhost=172.16.199.200 domain=kerberos.issue SMB::Auth=kerberos SMB::Rhostname=dc2.kerberos.issue DomainControllerRhost=172.16.199.200
[*] 172.16.199.200:445    - 172.16.199.200:445 - Starting SMB login bruteforce
[*] 172.16.199.200:445    - Error: 172.16.199.200: Metasploit::Framework::LoginScanner::Invalid Cred details can't be blank, Cred details can't be blank (Metasploit::Framework::LoginScanner::SMB)
[*] 172.16.199.200:445    - Scanned 1 of 1 hosts (100% complete)
[*] 172.16.199.200:445    - Bruteforce completed, 0 credentials were successful.
[*] 172.16.199.200:445    - You can open an SMB session with these credentials and CreateSession set to true
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/smb/smb_login) > run verbose=true rhost=172.16.199.200 domain=kerberos.issue SMB::Auth=kerberos SMB::Rhostname=dc2.kerberos.issue DomainControllerRhost=172.16.199.200 CreateSession=true
[*] 172.16.199.200:445    - 172.16.199.200:445 - Starting SMB login bruteforce
[*] 172.16.199.200:445    - Error: 172.16.199.200: Metasploit::Framework::LoginScanner::Invalid Cred details can't be blank, Cred details can't be blank (Metasploit::Framework::LoginScanner::SMB)
[*] 172.16.199.200:445    - Scanned 1 of 1 hosts (100% complete)
[*] 172.16.199.200:445    - Bruteforce completed, 0 credentials were successful.
[*] 172.16.199.200:445    - 0 SMB sessions were opened successfully.
[*] Auxiliary module execution completed

After

LDAP login scanner with Kerberos authentication

  • ldap_login works with Username & Password to get kerberos tickets
msf6 auxiliary(scanner/ldap/ldap_login) > run verbose=true rhost=172.16.199.100 domain=demo.local LDAP::Auth=kerberos LDAP::Rhostname=dc1.demo.local DomainControllerRhost=172.16.199.100 CreateSession=true username=Administrator password=N0tpassword!
[+] 172.16.199.100:88 - Received a valid TGT-Response
[*] 172.16.199.100:389 - TGT MIT Credential Cache ticket saved to /Users/jheysel/.msf4/loot/20250129122916_default_172.16.199.100_mit.kerberos.cca_627822.bin
[+] 172.16.199.100:88 - Received a valid TGS-Response
[*] 172.16.199.100:389 - TGS MIT Credential Cache ticket saved to /Users/jheysel/.msf4/loot/20250129122916_default_172.16.199.100_mit.kerberos.cca_711607.bin
[+] 172.16.199.100:88 - Received a valid delegation TGS-Response
[+] 172.16.199.100:88 - Received AP-REQ. Extracting session key...
[+] 172.16.199.100:389 - Success: 'demo.local\Administrator:N0tpassword!'
[*] LDAP session 1 opened (172.16.199.1:58395 -> 172.16.199.100:389) at 2025-01-29 12:29:17 -0800
[*] Scanned 1 of 1 hosts (100% complete)
[*] Bruteforce completed, 1 credential was successful.
[*] 1 LDAP session was opened successfully.
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/ldap/ldap_login) > klist
Kerberos Cache
==============
id  host            principal                 sname                           enctype  issued                     status  path
--  ----            ---------                 -----                           -------  ------                     ------  ----
8   172.16.199.100  [email protected]  krbtgt/[email protected]    AES256   2025-01-29 12:29:16 -0800  active  /Users/jheysel/.msf4/loot/20250129122916_default_172.16.199.100_mit.kerberos.cca_627822.bin
9   172.16.199.100  [email protected]  ldap/[email protected]  AES256   2025-01-29 12:29:16 -0800  active  /Users/jheysel/.msf4/loot/20250129122916_default_172.16.199.100_mit.kerberos.cca_711607.bin
  • Uses cached creds when username is supplied without password
msf6 auxiliary(scanner/ldap/ldap_login) > run verbose=true rhost=172.16.199.100 domain=demo.local LDAP::Auth=kerberos LDAP::Rhostname=dc1.demo.local DomainControllerRhost=172.16.199.100 CreateSession=true username=Administrator
[*] Using cached credential for ldap/[email protected] [email protected]
[+] 172.16.199.100:88 - Received AP-REQ. Extracting session key...
[+] 172.16.199.100:389 - Success: 'demo.local\Administrator:'
[*] LDAP session 2 opened (172.16.199.1:58403 -> 172.16.199.100:389) at 2025-01-29 12:29:55 -0800
[*] Scanned 1 of 1 hosts (100% complete)
[*] Bruteforce completed, 1 credential was successful.
[*] 1 LDAP session was opened successfully.
[*] Auxiliary module execution completed
  • Errors when no username is supplied:
msf6 auxiliary(scanner/ldap/ldap_login) > run verbose=true rhost=172.16.199.100 domain=demo.local LDAP::Auth=kerberos LDAP::Rhostname=dc1.demo.local DomainControllerRhost=172.16.199.100 CreateSession=true
[*] Error: 172.16.199.100: Metasploit::Framework::LoginScanner::Invalid Cred details can't be blank, Cred details can't be blank (Metasploit::Framework::LoginScanner::LDAP)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Bruteforce completed, 0 credentials were successful.
[*] 0 LDAP sessions were opened successfully.
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/ldap/ldap_login) >

LDAP login scanner with Schannel authentication

  • Geting certificate with creds work as expected
msf6 auxiliary(admin/dcerpc/icpr_cert) > run CA=demo-DC1-CA RHOSTS=172.16.199.100 SMBDomain=demo.lab SMBPass=N0tpassword! SMBUser=Administrator
[*] Running module against 172.16.199.100
[+] 172.16.199.100:445 - The requested certificate was issued.
[*] 172.16.199.100:445 - Certificate Policies:
[*] 172.16.199.100:445 - Certificate UPN: [email protected]
[*] 172.16.199.100:445 - Certificate stored at: /Users/jheysel/.msf4/loot/20250129123316_default_172.16.199.100_windows.ad.cs_713115.pfx
[*] Auxiliary module execution completed

  • Specifying CertFile without username & password fields works
msf6 auxiliary(admin/dcerpc/icpr_cert) > use ldap_login

Matching Modules
================

   #  Name                               Disclosure Date  Rank    Check  Description
   -  ----                               ---------------  ----    -----  -----------
   0  auxiliary/scanner/ldap/ldap_login  .                normal  No     LDAP Login Scanner


Interact with a module by name or index. For example info 0, use 0 or use auxiliary/scanner/ldap/ldap_login

[*] Using auxiliary/scanner/ldap/ldap_login
[*] The CreateSession option within this module can open an interactive session
msf6 auxiliary(scanner/ldap/ldap_login) > run verbose=true rhost=172.16.199.100 domain=demo.lab LDAP::Auth=schannel LDAP::CertFile=/Users/jheysel/.msf4/loot/20250129123316_default_172.16.199.100_windows.ad.cs_713115.pfx ssl=true rport=389 CreateSession=true
[+] Success: 'Cert File /Users/jheysel/.msf4/loot/20250129123316_default_172.16.199.100_windows.ad.cs_713115.pfx'
[*] LDAP session 3 opened (172.16.199.1:58425 -> 172.16.199.100:389) at 2025-01-29 12:33:47 -0800
[*] Scanned 1 of 1 hosts (100% complete)
[*] Bruteforce completed, 1 credential was successful.
[*] 1 LDAP session was opened successfully.
[*] Auxiliary module execution completed

SMB login scanner with Kerberos authentication

  • Works with Username & Password to get kerberos tickets
msf6 auxiliary(scanner/smb/smb_login) > run verbose=true rhost=172.16.199.200 domain=kerberos.issue SMB::Auth=kerberos SMB::Rhostname=dc2.kerberos.issue DomainControllerRhost=172.16.199.200 CreateSession=true username=Administrator password=N0tpassword!
[*] 172.16.199.200:445    - 172.16.199.200:445 - Starting SMB login bruteforce
[+] 172.16.199.200:445    - 172.16.199.200:88 - Received a valid TGT-Response
[*] 172.16.199.200:445    - 172.16.199.200:445    - TGT MIT Credential Cache ticket saved to /Users/jheysel/.msf4/loot/20250129123542_default_172.16.199.200_mit.kerberos.cca_616816.bin
[+] 172.16.199.200:445    - 172.16.199.200:88 - Received a valid TGS-Response
[*] 172.16.199.200:445    - 172.16.199.200:445    - TGS MIT Credential Cache ticket saved to /Users/jheysel/.msf4/loot/20250129123542_default_172.16.199.200_mit.kerberos.cca_316277.bin
[+] 172.16.199.200:445    - 172.16.199.200:88 - Received a valid delegation TGS-Response
[+] 172.16.199.200:445    - 172.16.199.200:445 - Success: 'kerberos.issue\Administrator:N0tpassword!' Administrator
[*] SMB session 4 opened (172.16.199.1:58434 -> 172.16.199.200:445) at 2025-01-29 12:35:43 -0800
[*] 172.16.199.200:445    - Scanned 1 of 1 hosts (100% complete)
[*] 172.16.199.200:445    - Bruteforce completed, 1 credential was successful.
[*] 172.16.199.200:445    - 1 SMB session was opened successfully.
[*] Auxiliary module execution completed
  • Uses cached creds when username is supplied without password
msf6 auxiliary(scanner/smb/smb_login) > run verbose=true rhost=172.16.199.200 domain=kerberos.issue SMB::Auth=kerberos SMB::Rhostname=dc2.kerberos.issue DomainControllerRhost=172.16.199.200 CreateSession=true SMBUser=Administrator
[*] 172.16.199.200:445    - 172.16.199.200:445 - Starting SMB login bruteforce
[*] 172.16.199.200:445    - Using cached credential for cifs/[email protected] [email protected]
[+] 172.16.199.200:445    - 172.16.199.200:445 - Success: 'kerberos.issue\Administrator:' Administrator
[*] SMB session 5 opened (172.16.199.1:58448 -> 172.16.199.200:445) at 2025-01-29 12:37:45 -0800
[*] 172.16.199.200:445    - Scanned 1 of 1 hosts (100% complete)
[*] 172.16.199.200:445    - Bruteforce completed, 1 credential was successful.
[*] 172.16.199.200:445    - 1 SMB session was opened successfully.
[*] Auxiliary module execution completed
  • Errors when no username is supplied:
msf6 auxiliary(scanner/smb/smb_login) > run verbose=true rhost=172.16.199.200 domain=kerberos.issue SMB::Auth=kerberos SMB::Rhostname=dc2.kerberos.issue DomainControllerRhost=172.16.199.200 CreateSession=true
[*] 172.16.199.200:445    - 172.16.199.200:445 - Starting SMB login bruteforce
[*] 172.16.199.200:445    - Error: 172.16.199.200: Metasploit::Framework::LoginScanner::Invalid Cred details can't be blank, Cred details can't be blank (Metasploit::Framework::LoginScanner::SMB)
[*] 172.16.199.200:445    - Scanned 1 of 1 hosts (100% complete)
[*] 172.16.199.200:445    - Bruteforce completed, 0 credentials were successful.
[*] 172.16.199.200:445    - 0 SMB sessions were opened successfully.
[*] Auxiliary module execution completed

@jheysel-r7 jheysel-r7 added the rn-fix release notes fix label Jan 29, 2025
@jheysel-r7 jheysel-r7 merged commit aa78924 into rapid7:master Jan 29, 2025
43 checks passed
@jheysel-r7
Copy link
Contributor

Release Notes

This fixes an issue with both the ldap_login and smb_login modules. The problem is that now, some login scanner modules are not only used to discover and report valid credentials, but also to get a session (e.g. SMB session, LDAP session). This means, if Kerberos is used as the authentication method, the user can omit the password and reuse tickets from the cache. Also, if the authentication method is Schannel (LDAP), the username can also be omitted since the certificate will contain everything needed to authenticate. Prior to this fix these modules would error if they were run without the username and password fields set. The fix introduces two new boolean attributes in the CredentialCollection class ignore_private and ignore_public which indicate whether the module should be allowed to be run without a username or password.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug rn-fix release notes fix
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

ldap/ldap_login module requires a password for schannel
2 participants