Task Scheduler ALPC exploit high level analysis – CVE-2018–8440

Kevin Beaumont
DoublePulsar

--

Yesterday SandboxEscaper tweeted an local privilege escalation exploit for Windows, which currently has no patch. It’s a really neat flaw, in particular how it is exploited.

Update: this is now known as CVE-2018–8440, and is fixed in September 2018’s monthly patch.

High level overview

  • Needs prior code execution to exploit.
  • Proof of concept exploit currently only works on 64-bit OSes (Windows 10 and Server 2016). Update: it has been backported to Windows 7, 2008, 2012 and on 32 bit CPUs.

Let’s take a bit of a look at the code. I’ve uploaded it to Github for easier analysis, I hope SandboxEscaper doesn’t mind.

What is it the flaw?

“_SchRpcSetSecurity which is part of the task scheduler ALPC endpoint allows us to set an arbitrary DACL. It will Set the security of a file in c:\windows\tasks without impersonating, a non-admin (works from Guest too) user can write here. Before the task scheduler writes the DACL we can create a hard link to any file we have read access over. This will result in an arbitrary DACL write. This PoC will overwrite a printer related dll and use it as a hijacking vector. This is ofcourse one of many options to abuse this.” — source

The flaw is that the Task Scheduler API function SchRpcSetSecurity fails to check permissions. So anybody — even a guest — can call it and set file permissions on anything locally.

What is the exploit?

This exploit misuses SchRpcSetSecurity to alter permissions (I wouldn’t recommend running it a live system by the way) to allow a hard link to be created, and then calls a print job using XPS printer (installed with Windows XP Service Pack 2+) to call the hijack DLL as SYSTEM (via the Spooler process).

What does it look like in practice?

Thanks to Will Dormann — or is that Phil Dormann?

You get a process spawned under the Print Spooler service (spoolsv.exe) called cmd.exe, which spawns conhost.exe along with a random process. This isn’t normal behaviour.

Exploit limitations

It needs tweaking to work on 32 bit OS, as it has hardcoded paths with *AMD64* which don’t exist on 32-bit Windows. Also it hard codes prnms003 driver, which doesn’t exist on certain versions (e.g. on Windows 7 it can be prnms001). Update: somebody ported it to 32-bit, IoC
81a4dbf1132e6cb43f45b803b8f46e85cb9d3a60dbe560762f4cc49461758641

Other ways to exploit

There’s a bunch of other ways I can think that can be done. Essentially if you can alter permissions and create hardlinks you can do a bunch of Bad Things(tm).

Ways to detect

Microsoft Sysmon

If you use Microsoft Sysmon, look for spoolsv.exe spawning abnormal processes — it’s a sure sign this proof of concept exploit is being used (or another Spooler exploit).

Using audit logs and SIEM

While the following won’t detect every way this flaw can be abused, it will detect the angle in the proof of concept (and is a pretty good indicator that things have gone Very Wrong). Right now I haven’t seen any evidence this has been looked at outside the context of task scheduling. Update 5 September 2018: ESET report this is being exploited in PowerPool malware on a limited basis by Powerpool group.

If you do not already manually enable file system auditing, create a Group Policy Object and name it File System Audit Policy. Within the GPO, browse to Computer Configuration\Windows Settings\Security Settings\Advanced Audit Policy Configuration\Audit Policies and define the following Audit Policy setting:

  • Object Access: File System — Success

Next up you need to use Group Policy to push out this PowerShell script, under Computer Configuration\Policy\Windows Settings\Scripts (Startup/Shutdown) — or a scheduled task to avoid waiting for systems to reboot:

$computer = gc env:computername
$path = “C:\windows\tasks”
$user = “everyone”
$path = $path.replace(“\”, “\\”)
$SD = ([WMIClass] “Win32_SecurityDescriptor”).CreateInstance()
$ace = ([WMIClass] “Win32_ace”).CreateInstance()
$Trustee = ([WMIClass] “Win32_Trustee”).CreateInstance()
$SID = (new-object security.principal.ntaccount $user).translate([security.principal.securityidentifier])
[byte[]] $SIDArray = ,0 * $SID.BinaryLength
$SID.GetBinaryForm($SIDArray,0)
$Trustee.Name = $user
$Trustee.SID = $SIDArray
$ace.AccessMask = [System.Security.AccessControl.FileSystemRights]”Modify”
$ace.AceFlags = “0x67”
$ace.AceType = 2
$ace.Trustee = $trustee
$SD.SACL = $ace
$SD.ControlFlags=”0x10"
$wPrivilege = gwmi Win32_LogicalFileSecuritySetting -computername $computer -filter “path=’$path’”
$wPrivilege.psbase.Scope.Options.EnablePrivileges = $true
$wPrivilege.setsecuritydescriptor($SD)

This script will turn on file system auditing for the Tasks folder:

Finally, upon exploit the system will generate a Security event log called 4664, for a hardlink being created in the Tasks folder:

You should collect this event ID with a tool like Microsoft OMS/Log Analytics or Splunk. If it fires with the Link Name c:\windows\tasks, this is abnormal behaviour and Security Operations should investigate as a high priority.

YARA rule

Kinda lame but this works:

rule TaskSched
{
strings:
$a = “c:\\windows\\tasks” wide ascii nocase
$b = “.job” wide ascii nocase
$c = “ncalrpc” wide ascii nocase
$d = “MZ” wide ascii

condition:
$a and $b and $c and $d
}

Ways to mitigate

  • Antivirus, segmentation, don’t allow untrusted users to run code.

Ways to fix

  • Microsoft need to fix the function. This will probably happen in a few weeks.

CERT/CC take here.

Update 5 September 2018: corrected task folder location in PowerShell, added ESET link, added 32-bit proof of concept hash and impacted OSes.

--

--