A KACE of excessive permissisons

Thomas Lilja

While digging through event logs on customer laptop exploring ways to escalate my privileges during an "assume breach" assignment I came upon something interesting. I had previously noticed that there were PowerShell scripts being run at regular intervals by the KACE Systems Management Appliance (SMA) used for endpoint management by their MSP.

The event log entry in front of me at this time however piqued my interest as the script was being run as SYSTEM from a folder that I remembered from when I was looking around the KACE file structure previously.


The reason I remembered this folder was because it was user writable. There were no PowerShell scripts in it at the time though, so I did not think much of it. Going back into the folder I noticed there were some log files written by KACE there, maybe they could help me figure out what was going on?

Searching for the file name of the PowerShell script from the event log entry in the KAgent.log file located in that same folder I suddenly realized that KACE generates the script in the folder before executing it and then subsequently deletes it after execution has finished. This explains why there were not PowerShell files in that folder, but it also gave me an idea. What if I could switch the script file between the time of creation and execution and have my own script executed as SYSTEM instead?

To be able to monitor the directory and switch the script as soon as it was created, I turned to System.IO FileSystemWatcher. Running PowerShell scripts was blocked on the client but I could still run PowerShell code from the PowerShell ISE application, so I put this script together to test my hypothesis:

// Script to watch the KACE C:\ProgramData\Quest\KACE\user\ folder for the 
// creation of a file named temp_script.ps1 and replace it with our own script. 
// Created by Thomas Lilja (@priv3sc) 2022 
$folder = 'C:\ProgramData\Quest\KACE\user\' $KACEWatcher = New-Object System.IO.FileSystemWatcher 
$KACEWatcher.Path = $folder $KACEWatcher.Filter = "temp_script.ps1" $KACEWatcher.EnableRaisingEvents = $true 
$PScreated = Register-ObjectEvent $KACEWatcher "Created" -Action { Write-Host "Found new file: $($eventArgs.FullPath)" \
             Copy-Item -Path "C:\temp\evil_script.ps1" -Destination $($eventArgs.FullPath) -Force }

I quickly whipped up a test script, evil_script.ps1 in C:\temp containing the following code:

whoami >> C:\temp\whoami.txt

Lo and behold it worked! And as I had hoped the output from evil.ps1 showed that the KACE SMA instead of performing client inventory now ran my script evil_script.ps1 as "nt authority\system".

Jackpot! Now I just needed to replace the code in evil_script.ps1 with:

Add-LocalGroupMember -Group "Administrators" -Member "domain\user"

And after the next run I had local admin rights on the client.


This bug was reported to Quest in May 2022 and was assigned CVE ID CVE-2022-35889 which at the time of writing still has the status “Reserved”.

The vulnerability has subsequently been patched in KACE SMA agents 12.0.39 and 12.1.55. For more details see: