Scheduled tasks run actions at a chosen privilege level, and many third-party tasks run as SYSTEM. If the action binary, a script it calls, or its directory is writable by ordinary users, replacing that file gives code execution as SYSTEM at the next trigger (T1053.005). Attackers can also change a task definition when its ACL is weak. The audit and the detection are both mostly about inventory and file integrity.
Signals at a Glance
| Signal | Where | ATT&CK |
|---|---|---|
| Task created or updated with an action in a user-writable path | Security 4698/4702, TaskScheduler 106/140 | T1053.005 |
| Write to a binary or script referenced by a SYSTEM task, by a non-admin | Sysmon 11, EDR file events | T1053.005 |
| SYSTEM task action started shortly after its file changed | TaskScheduler 200, Sysmon 11 | T1053.005 |
| Task XML under the Tasks directory modified outside the Task Scheduler service | Sysmon 11, FIM | T1053.005 |
| schtasks.exe or PowerShell registering tasks to run as SYSTEM from a user context | Sysmon 1, 4688 | T1053.005 |
Task Creation and Change Events
Security Events 4698 (created) and 4702 (updated) include the full task XML when Other Object Access auditing is on. Extract the principal and the command, then flag SYSTEM or highest-privilege tasks whose command sits in a user-writable location:
index=wineventlog source="WinEventLog:Security" (EventCode=4698 OR EventCode=4702) | rex field=Task_Content "<UserId>(?<task_user>[^<]+)</UserId>" | rex field=Task_Content "<Command>(?<task_cmd>[^<]+)</Command>" | where match(task_user,"(?i)SYSTEM|S-1-5-18") | where match(task_cmd,"(?i)(Users|ProgramData|Temp|AppData)") | table _time host Subject_Account_Name Task_Name task_user task_cmd ```tune/validate: confirm field names for your TA and enable Audit Other Object Access Events```
Finding Writable Actions
The abusable condition is a SYSTEM task whose action file is writable. Enumerate it with a script, store the result as a watchlist, then monitor those paths for writes by anything other than your deployment accounts:
Get-ScheduledTask | Where-Object { $_.Principal.UserId -match 'SYSTEM' -or $_.Principal.RunLevel -eq 'Highest' } |
ForEach-Object {
$task = $_
foreach ($a in $task.Actions) {
if ($a.Execute) {
$exe = [Environment]::ExpandEnvironmentVariables($a.Execute).Trim('"')
if (Test-Path $exe) {
$w = (Get-Acl $exe).Access | Where-Object {
$_.IdentityReference -match 'Users|Everyone' -and $_.FileSystemRights -match 'Write|Modify|FullControl' }
if ($w) { [pscustomobject]@{ Task = $task.TaskName; Binary = $exe; Who = ($w.IdentityReference -join ',') } }
}
}
}
}
# tune/validate: also check the parent directory ACL and any script the action calls.
// Microsoft Defender (KQL) - writes to files referenced by SYSTEM tasks
let taskBins = _GetWatchlist('SystemTaskActions') | project FolderPath = tolower(Path);
DeviceFileEvents
| where ActionType in ("FileCreated","FileModified","FileRenamed")
| where tolower(FolderPath) in (taskBins)
| where InitiatingProcessAccountSid !in ("S-1-5-18","S-1-5-19","S-1-5-20")
| project Timestamp, DeviceName, FolderPath, InitiatingProcessFileName, InitiatingProcessAccountName
// tune/validate: exclude your software deployment and patching accounts.
- Fix findings by tightening ACLs on action files and directories, not by deleting the task. Users should have read and execute only.
- Alert on task changes that move an action from a protected path to a writable one. That is a low-volume, high-value signal.
- Review the TaskScheduler/Operational log (106 registered, 140 updated, 141 deleted, 200 started) if Security auditing is not enabled for tasks.
Use the SigmaHQ scheduled-task rules, Elastic’s prebuilt rules for task creation and modification, MITRE CAR analytics for scheduled task behaviour, and Atomic Red Team T1053.005 for validation. Baseline your own environment — vendor updaters create and modify tasks constantly.
Build Detections That Fire
Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.
- Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
- Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
- 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Stay ahead of emerging threats. Get notified when we publish new intelligence reports and advisories.
Subscribe to Alerts