Skip to content

ALPC Task Scheduler SchRpcSetSecurity LPE (CVE-2018-8440)

Task Scheduler'ın ALPC interface'i SchRpcSetSecurity metodunu export eder; bu metot, attacker'ın verdiği bir DACL'i C:\Windows\Tasks altındaki bir path'e caller'ı impersonate etmeden yazar. Bir hardlink ile birleştiğinde, yetkisiz bir kullanıcı sistemdeki herhangi bir dosyanın ACL'ini yeniden yazar ve SYSTEM'a yükselir (privilege escalation).

Mechanism

Eksik bir impersonation, bir DACL setter'ı neden SYSTEM primitive'ine çevirir

Windows Task Scheduler servisi SYSTEM olarak çalışır ve bir ALPC (Advanced Local Procedure Call) RPC endpoint'i sunar. Metotlarından biri olan SchRpcSetSecurity, zamanlanmış bir task'ın security descriptor'ını (DACL) set etmek içindir. Implementation'da birbirini besleyen iki kusur var:

  1. Target üzerinde permission check yok. SchRpcSetSecurity, caller'ın verdiği DACL'i C:\Windows\Tasks altındaki bir dosyaya, caller'ın o object'in güvenliğini değiştirmeye yetkili olup olmadığını önce doğrulamadan uygular.

  2. Impersonation yok. Diskteki dosyaya dokunurken servis, (yetkisiz) RPC caller'ı impersonate etmez — kendi SYSTEM token'ı ile çalışır. Dolayısıyla kernel, SetSecurity işlemini SYSTEM authority ile gerçekleştirir.

Yetkili bir servisin koruması gereken invariant şu: bir client adına bir resource üzerinde işlem yaparken o client'ı impersonate et ki kernel'in access check'i servisin değil client'ın token'ını kullansın. Task Scheduler bunu burada bozuyor. Herhangi bir kullanıcı C:\Windows\Tasks içinde dosya oluşturabildiğinden, attacker oraya bir dosya yerleştirir ve onu, başka türlü korunan keyfi bir target'a (SYSTEM/TrustedInstaller'a ait bir DLL veya executable) işaret eden bir hardlink'e çevirir. SchRpcSetSecurity'den yerleştirilen ad üzerinde DACL set etmesi istendiğinde, SYSTEM servisi hardlink'i takip eder ve attacker'ın seçtiği DACL'i (örneğin Everyone: Full Control) gerçek target'a damgalar.

Attacker, bir SYSTEM process'inin daha sonra okuyup execute edeceği bir dosyanın DACL'ini kontrol ettiği an, escalation mekanik hale gelir: o dosyayı kötü niyetli bir payload ile overwrite et ve SYSTEM process'ini onu load etmeye tetikle. Public PoC, bu yeni write erişimini Print Spooler path'ine zincirledi — SYSTEM seviyesindeki spooler'ın load ettiği bir printer driver DLL'i (örneğin printer başına UpdateTask/PrintConfig component'i) — böylece bir printer eklemek attacker kodunu SYSTEM olarak çalıştırdı. Bug, SandboxEscaper tarafından 27 Aug 2018'de bir 0day olarak yayımlandı, günler içinde PowerPool malware ekibi tarafından silahlandırıldı ve 11 Sep 2018'de patch'lendi.

Bu, UNIX'teki "privileged daemon bir attacker symlink'i üzerinden yazar" (link-following / TOCTOU sınıfı) bug'ının Windows karşılığıdır: corruption primitive'i file ACL rewrite, kaldıraç ise impersonation yok + servisin güvendiği bir directory'ye kullanıcı write erişimi.

Walkthrough

Step 1 — Task Scheduler ALPC endpoint'ine bind ol ve vulnerable metodu çağır. Public PoC, local RPC interface'i reverse-engineer etti ve SchRpcSetSecurity'yi doğrudan çağırdı:

// SchRpcSetSecurity(path, sddl, flags) over the schedule-service ALPC port.
// 'path' is interpreted relative to the Tasks store; 'sddl' is the new DACL.
hr = SchRpcSetSecurity(
        L"..\\..\\..\\..\\<relative path into C:\\Windows\\Tasks\\hardlink>",
        L"D:(A;;FA;;;WD)",   // Everyone (WD) : Full Access (FA)
        0);

Step 2 — hardlink'i yerleştir. Attacker (yetkisiz) C:\Windows\Tasks içinde dosya oluşturabildiğinden, orada ACL'ini ele geçirmek istediğin gerçek, SYSTEM'a ait target'a resolve olan bir hardlink oluştur:

C:\Windows\Tasks\poc.job   --hardlink-->   C:\Windows\System32\<targetDLL>.dll

Step 3 — fire the call. Because the service does not impersonate and does not check permission, it rewrites the DACL of the hardlink's target:

Before:  <targetDLL>.dll  owner=TrustedInstaller, write denied to users
After:   <targetDLL>.dll  DACL = Everyone:Full   (attacker now owns the ACL)

Expected observable: icacls C:\Windows\System32\<targetDLL>.dll now shows Everyone:(F).

Step 4 — convert ACL control into SYSTEM code execution. Overwrite the now attacker-writable DLL with a payload, then induce a SYSTEM process to load it. The reference chain abused the print subsystem so that adding/refreshing a printer caused the SYSTEM spooler to load the replaced driver DLL:

copy payload.dll  C:\Windows\System32\<targetDLL>.dll     (overwrite)
Add-Printer / spooler refresh  ->  spoolsv.exe (SYSTEM) loads <targetDLL>.dll
->  payload runs as NT AUTHORITY\SYSTEM

Step 5 — verify. The payload (e.g. a cmd.exe spawn) runs in session 0 as SYSTEM:

whoami  ->  nt authority\system
Why the relative-path + hardlink combination is the whole trick

SchRpcSetSecurity was only ever supposed to touch a task's descriptor inside the scheduler's store. The PoC passes a path that escapes that store only as far as a file the user can already create (C:\Windows\Tasks), then relies on NTFS hardlinks to make that user-creatable name alias a file the user cannot normally modify. The privileged service does the forbidden write on the user's behalf because it never re-checks who is asking. Microsoft's fix added the missing access/impersonation checks so the DACL set is evaluated against the caller's token.

Detection

  • File-integrity / EDR: DACL changes (SetSecurity) on System32 DLLs, or new hardlinks created in C:\Windows\Tasks pointing outside the Tasks store, by a non-system process.
  • Spooler anomaly: spoolsv.exe loading a freshly-modified driver DLL, or printer-add operations immediately following ACL changes.
  • PowerPool IOCs: the in-the-wild campaign that weaponized this is documented by AV vendors; the dropped second stage modified Task Scheduler artifacts.

Mitigation

  • Apply the September 2018 cumulative update (fixes CVE-2018-8440) — it adds the missing permission/impersonation checks in SchRpcSetSecurity.
  • Restrict / monitor write access to C:\Windows\Tasks and watch for hardlink creation there (link-following hardening).
  • General defense for "no-impersonation" service bugs: privileged services must impersonate the client before touching client-named filesystem objects.

References