Task Scheduler– New Vulnerabilities for schtasks.exe

Introduction
The schtasks.exe binary is a core component of the Task Scheduler Service in Windows, enabling users to schedule and manage tasks automatically.
As part of the Windows Task Scheduler framework, schtasks.exe provides both system administrators and regular users with the ability to streamline operations by automating tasks, from simple programs to complex system maintenance processes.
In the context of Cyber Security, schtasks.exe is a powerful tool that can be used for malicious activities, aligning with Persistence, Privilege Escalation, Execution, and lateral movement tactics in the MITRE ATT&CK Framework.
This blog discloses new vulnerabilities and techniques we found, covering UAC bypass, Metadata Poisoning, Task Event Log Overflow, and Security Event Logs Overwrite, adding the technique to a new tactic category, Defense Evasion, and reinforcing the Privilege Escalation category regarding Elevation Control Mechanism Abuse.
Summary
A UAC Bypass vulnerability has been found in Microsoft Windows, enabling attackers to bypass the User Account Control prompt, allowing them to execute high-privilege (SYSTEM) commands without user approval. By exploiting this weakness, attackers can elevate their privileges and run malicious payloads with Administrators’ rights, leading to unauthorized access, data theft, or further system compromise.
It occurs when an attacker creates a task using Batch Logon and not with an Interactive Token. The Task Scheduler service, impersonating the user, is granting the running process the maximum allowed rights, elevating it from any integrity to the highest available.
In addition, two new Defense Evasion techniques have been discovered. The first vulnerability allows an attacker to leverage an unlimited buffer in Author task metadata, which is handled further by the Windows Event Log, overwriting the whole log description.
The second vulnerability is based on the first one. Since the buffer in the Event Log is user-controlled, a single overflowed log creation takes 8KB. By iterating a loop creating a task 2280 times, the default size of the Event Log Security file (Security.evtx) is overflowed, enabling a threat actor to clear logs.
Index
- Credentials Based UAC Bypass (Highest Level)
- RunLevel HIGHEST – Access Denied Bypass
- Credentials Based Impersonation with Batch Logon
- Scheduled Task Metadata Poisoning
- Task Event Log Poisoning – CWE-117
- Task Event Log Overflow – CWE-117, CWE-400
- Security Logs Saturation – CWE-117, CWE-400
Task Scheduler UAC Bypass
Specifications:
- Local administrator credentials required
- Bypasses the highest UAC level (Always Notifies)
- Can be elevated to High or SYSTEM Integrity
While creating a Scheduled Task as a standard user using an XML task file, I discovered that credentials are required for the functionality to work.
After supplying credentials with /ru and /rp, I got the following error message:

When creating a task with an XML file, the /ru and /rp flag are required to allow the service to impersonate the task principal.
Indeed, the taskhostw.exe process, hosted by svchost.exe, is running as SYSTEM. When the service is impersonating the user, a high Integrity context is initiated for the task to run. When the command is executed after the task creation, the following log is created:

Bypassing the highest level of UAC:

Example:

The difference between a password registration (Batch Logon), and a default registration (InteractiveToken) is the authentication method, as mentioned in MSDN. It will determine the integrity of the process to run.

The only limitation is to know the password.
Therefore, some methods should not be overlooked.
The first method is to get an NTLMv2 challenge from the client to an SMB server, and to crack it in offline mode. If the password can be cracked with an adapted wordlist, the credentials could be used.
Example:
First authenticate with the current session against a SMB server:

Then get the NTLMv2 hash from the server side.

Finally crack it using a wordlist, and a cracking tool (below hashcat). Password Cracked.

Another method could be to use clear-text stored passwords, with vulnerabilities like the very funny CVE-2023-21726, a Privilege Escalation vulnerability found in OOBE process, storing local administrator credentials in cleartext, in a readable by anyone HKU registry value. For more details, read the gmo-cybersecurity report.
The password was stored in:
HKEY_USERS\.DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE\Broker\LocalSystemAuthBuffer

RunLevel HIGHEST – Access Denied Bypass
Along the same lines, after elevating from a medium to a high integrity, it is not enough for our task to run as SYSTEM. Impersonating an admin user with batch logon doesn’t guarantee the ability to run as SYSTEM since it wasn’t intended to run elevated. If we add to our method the /RL HIGHEST flag, we get Access Denied.
But to remediate it, we can elevate our privileges to high with the previously mentioned UAC bypass by creating a temporary task, which then creates our SYSTEM main task from inside:

Credentials-Based Impersonation with Batch Logon
Since SYSTEM is performing an impersonation of the principal user running the task, the impersonated user must have batch logon rights.
This point is not a vulnerability, but more a feature, and a strategy to perform lateral movement and to get pivoting options for Windows and Active Directory exploitation.
The default groups granted Batch Logon are:
- Administrators
- Backup Operators
- Performance Log Users
Any low privileged user can leverage the schtasks.exe binary and impersonate a member of these groups with a known password to obtain the maximum allowed privileges.
The following explanations bring to light additional information about these groups.
Administrators
For the Administrators group, by using a local administrator password, any low privileged user can impersonate SYSTEM rights using the previously mentioned schtasks method (see previous section).
To make it work, we can do exactly what we did before on UAC – from medium to system. Notice that we run as a low privileged user, so we cannot query our own SYSTEM created task. But we can query the XML of the file directly from System32\Tasks.

Performance Log Users
The group was well known by the infamous CVE-2024-38061, and the excellent Decoder’s Blog post about his finding.
The vulnerability could allow members of Distributed COM Users and Performance Log Users to launch, activate, and distribute COM objects remotely, compromising users logged in on DC through a coerce + NTLM relay attack (Bloodhound).
Once patched, it appears that users from the mentioned group still have the mentioned privileges and can exploit them locally, but don’t have remote login rights enabled anymore. Notice that it can be logged on with schtasks since it has Batch Logon.
Backup Operators
Grants the privilege to back up the SAM, SECURITY and SYSTEM registry hives, leading to local / domain PE and DCSYNC.
Sources: BackupOperatorToDA, impacket-reg.
When running under the context of a regular session of a Backup Operator group user, we cannot perform a backup of sensitive files and registry hives.
It happens in the typical case: A persistent schtasks based reverse shell, running under the context of a Backup Operators user, with its InteractiveToken.

It will result in an Access Denied error, since an elevated session is required. Careful, talking about elevated session means here the maximum privileges enabled for the current user, and not local administrator privileges.
And in that case, our Batch Logon user impersonation with schtasks.exe is interesting.
When running schtasks under the same user, we get the following privileges granted from the Task Scheduler service to our user:

Bingo. Let’s make it happen and backup it from a Scheduled Task. And it’s a big YES!

Scheduled Task Metadata Poisoning
Local Poisoning
With the registration of a scheduled task from command line using an InteractiveToken authentication method, the running user context information is saved for the same scheduled task metadata.
However, using a Batch Logon authentication method with an XML file, the metadata is saved based on the XML tags and not on the current running user information.
For example, if the user low creates an Administrator task running under SYSTEM privileges, it can modify the task metadata Author to be Administrator and not low.
Essentially, any arbitrary data can be written in the Author tag.
Let us create a basic task, exporting its XML and recreating it with different metadata.
schtasks /create /tn poc /tr calc.exe /sc minute /mo 10 /f
schtasks /query /xml /tn poc > poc.xml
Before changing anything, we can observe the regular metadata state of the task:

Now change the XML task of our file before reimporting it.

We delete and recreate the task to observe the result.
schtasks /delete /tn poc /f
schtasks /create /tn poc /xml poc.xml /ru low /rp Password2
The task metadata has been changed.

Remote Poisoning
We can also use the task scheduler service over RPC to create a task, with poisoned metadata.
Since the task’s XML is sent over RPC, the same tags can be modified. For example, we can try it with the well-known impacket-atexec script.

Change the author’s value to look like something trustable. Like TrustedInstaller.
Don’t forget to patch the impacket script to not delete the task after, since we want to look at it registered and not hidden.

Task Information:

Looking at procmon, it shows that these metadata are also stored in HKLM. I immediately guessed that it could be accessed by security products to inspecting for the legitimacy of a task, which could lead to security issues for most of them.

After reporting it to MSRC, I got the following answer:
“We believe you are reporting that when you load an XML task, it appears as through it was authored by the user specified in the XML, not that it is being executed by that user […]
We also believe you are misunderstanding what ‘Author' is for, and indeed the whole 'RegistrationInfo’ block […]
Notably, the documentation does not say that it’s for security purposes, but for storing general details about the task.
We see this report has more of a phishing attack where the user would see this as an administrator created task and trust it for execution”
Okay! These metadata and the RegistrationInfo block exist only for “storing general details”.
Naturally, I looked for products and features that are using and relying on these metadata, and I didn’t have to look very far.
Task Event Log Poisoning
The LogID for Task Creation in Event Logs is 4698. More information in MSDN.
As we can see, the XML of the task is registered for logging as Task Information.

Besides poisoning the HKLM entries of the task, we can also poison the Event Log registered about it. I created a task with the user Cymuser and changed the Author to be Administrator.

It is a CWE-117 vulnerability, but it is not that interesting to be honest. I felt that there is something more interesting about the author XML writable value.
Task Event Log Overflow
As mentioned in the introduction, the task scheduler is mainly used for execution and backdooring. So, what would you like to hide the most in the task log? The payload.
I found that from one side, the task registration process doesn’t limit the buffer size of the Author tag value. From another side, the TaskContent entry in the 4698 Event Log, which contains the whole XML task log descriptor, has a limit of approximatively 3500 bytes.
It basically means that creating a task with an author named A*3500 would overwrite the whole XML log description TaskContent, including our payload.
I created an XML file with a charged author buffer.

Then, I registered the task.
schtasks /create /tn poc /xml poc.xml /ru Cymuser /rp Password1
Then, see the magic:

A normal log would look like the following

When querying the event from PowerShell directly we can confirm it was overwritten, and it is not a displaying error.
Get-WinEvent -FilterHashtable @{logname='security'; id=4698} | Select-Object -Property TimeCreated, Id, @{N='Detailed Message'; E={$_.Message}} | Sort-Object -Property TimeCreated | Select-Object -ExpandProperty 'Detailed Message'

As mentioned before, the XML is also sent over RPC, and no check is performed by the Task Scheduler Service as well. So, the XML log can be also overwritten remotely.
Event Log Overflow – Remote Method
Let us modify the payload sent over RPC of the impacket-atexec script.

Run the script.

Finally check the logs.

Yes, it’s working.
Don’t forget that the task is running only when the principal has Batch Logon rights, and a password is required for the task to be registered based on an XML file. I mapped the possibilities for different scenarios.

Notice the difference between the running user and the other user category.
When a Batch Logon user is creating the task without a password, its own Interactive Token is logging it, and the task is registered and running. But the privileges won’t be elevated when the task is running, since SYSTEM isn’t performing any impersonation.
I also found out that it is not exact to say that Batch Logon rights are required for an XML task to be registered from a running user context. It can be also the SeImpersonate rights.
For example, if an Administrator account is creating a task for itself without using a password from an XML file, the same shell integrity will be applied for the task to run.
When a Batch Logon user is impersonated with a password from any user creating a task, the privileges will be elevated, since SYSTEM is performing the impersonation.
When a privileged user is creating a task with another user as principal, no password is required, and the task will run under a medium integrity.
Security Logs Saturation
So, we can register a task with a 5KB XML file, with a low privileged user and a password, which will not run. But the log is still registered, with a 3500 bytes buffer. It smells like we can overwrite the whole Security.evtx database, since it is configured to contain maximum 20MB of logs by default.
I created a 4 lines batch script that will do the job:

Run it for 1:15 minutes and you will see the logs completely overwritten.
First Log, 03:54:23.

Last Log, 03:55:38.

No, it’s not a joke. The 20MB of logs are indeed overwritten.
The exploit works because we combine here 3 chained vulnerabilities:
- Uncontrolled buffer for the Author tag in XML based task registration
- Trusted user input for task logging, leading to task length overweight
- Uncontrolled task registration flow, spamming the Security Event Database
After calculating the size of a spammed log and the accepted default size for the Security Event Logs file (20480 Kb), I adapted the script to run exactly to overwrite the logs:

To prove it let’s clear the logs. The First and only 1102 Log Clear event should appear. Then run the script and recheck for 1102 events.

Conclusion
The Task Scheduler is a very interesting component. Accessible by anyone willing to create a task, initiated by a SYSTEM running service, juggling between the privileges, the process integrities and user impersonations.
The first reported vulnerability is not only a UAC Bypass. It is far more than that: it is essentially a way to impersonate any user with its password from CLI and to obtain the maximum granted privileges on the task execution session, with the /ru and /rp flags.
From metadata poisoning, through Event Log poisoning, we discovered to overflow a single log’s TaskContent entry, and even how to overflow the whole Security Event file.
MSRC didn’t consider a single report as a vulnerability.