Microsoft Windows Task Scheduler - 'DeleteExpiredTaskAfter' File Deletion Privilege Escalation








Windows: Task Scheduler DeleteExpiredTaskAfter File Deletion Elevation of Privilege
Platform: Windows 8.1 Update, looks like it should work on 7 and 10 as well
Class: Elevation of Privilege

The Task Scheduler can be made to delete a task after it’s trigger has expired. No check is made to ensure the task file is not a junction which allows arbitrary files to be deleted by the system user leading to EoP.


If a scheduled task is configured with DeleteExpiredTaskAfter setting the service will delete the task including its task file after the triggers have expired. It does the deletion in a timer callback thread but doesn’t call DeleteFile with the privileges of the task, instead running at local system. While the scheduler now seems to do some checking on the path for junction attacks this only seems to be at creation time not when it’s deleting the task file. Therefore you can mount a junction attack against the deletion process which allows you to delete any file or directory on the system which local system can delete. To delete directories you’d have to use a more advanced trick than just a directory junction as you’d need to the point the task file to name::$INDEX_ALLOCATION but it will work. 

The ability to deletes files is sufficient in some cases to elevate privileges because of the behaviour of other system processes and default permissions. For example system files created in ProgramData generally have privileges which prevent a user from modifying or replacing files, but not from creating new ones. You could use the attack to delete existing files then replace with hardlinks to overwrite system files.

Proof of Concept:

The PoC demonstrates the vulnerability deleting an arbitrary file from the system. You need to modify the $filetodelete variable to select a different file to test other than c:\protected\test

1) Copy the PoC to a location on a local hard disk and rename the file’s extension to .ps1.
2) Enable powershell scripting for the current user, this doesn’t affect the actual exploit, it’s just to get powershell to execute the script. 
2) As a normal user execute the powershell PoC
3) The PoC should complete execution.

Expected Result:
The service should detect the directory junction and not delete the target file

Observed Result:
The target file is deleted

Proof of Concept: