Azure Sentinel is a powerful cloud based SIEM solution.
This blog series will be on how to work with Sentinel.
It will be example based on different solutions which we might run into.
This first post is about how you can work with logs and get insight in Scheduled Tasks as a way for attackers to persist in your network
For further information regards Sentinel, visit https://azure.microsoft.com/en-us/services/azure-sentinel/
Scheduled Tasks
By default there are no events created if someone creates or modifieds a scheduled task. To enable logging you have to enable logging of object access.
To view current settings, use the following command:
auditpol.exe /get /category:*

Only Success is required for this. This enables us to get the event 4698

To enable logging, create a new GPO and assign the following settings (depending if you want success/failure or only success)

You also have to configure your agents to send log to your workspace, you can download the agent from the Azure Sentinel workspace / <workspace name> / Advanced Settings

Otherwise, you can add the Sentinel workspace to your existing agents

$Agent = New-Object -ComObject AgentConfigManager.MgmtSvcCfg
$ID= "<WorkspaceID>"
$Key = "<key>"
$Agent.AddCloudWorkspace($ID,$Key)
restart-service HealthService
In Azure Sentinel – Data connectors, configure Security Events


Verify heartbeats from computers
Heartbeat | summarize argmax(TimeGenerated, *) by Computer

So now we have logs from 2 computers and now we want to query Scheduled Tasks
A simple way is to just query the EventID

We can use project to format our table but we still want to get information about the tasks that were created to get a better overview
According to documentation we can use Parse operator into one or more calculated columns
https://docs.microsoft.com/en-us/azure/kusto/query/parseoperator
//Example
SecurityEvent
| where EventID == "4698"
| parse EventData with * '"SubjectUserName">' SubjectUserName '<' * '"SubjectDomainName">' SubjectDomainName '<' *
This query will
- Select all events where eventid=4698
- parse the column event data and look for ‘”SubjectUserName”>’
- Put everyting to a column named SubjectUserName until character ‘<‘
- the wildcard will run the samething again
- Continue parsing until ‘”SubjectDomainName”>’
- Put everything into column SubjectDomainName until character ‘<‘

To continue this to get some really useful information we continue to parse the content until we get everything we need
//Sec-Labs Demo - Sentinel Hunting for Scheduled Tasks Persistance
let start=datetime("2019-03-12T19:39:47.762Z");
let end=datetime("2019-03-19T22:39:47.762Z");
SecurityEvent
|where TimeGenerated > start and TimeGenerated < end
| where EventID == "4698"
| parse EventData with * '"SubjectUserName">' SubjectUserName '<' * '"SubjectDomainName">' SubjectDomainName '<' * '"TaskName">\\' TaskName '<' * 'Author>' Author '<' * '<Command>' SchedCommand '</Command' * 'Arguments>' SchedArgs '</Arguments' * 'WorkingDirectory>' SchedDir '&' *
| where isnotempty (SubjectUserName)
| project TimeGenerated,SubjectUserName,Computer,Activity,SubjectDomainName,TaskName,SchedCommand,SchedArgs,SchedDir
| project-rename CreatedBy = SubjectUserName

To rename columns, you can use project-rename <new name> = <old column name>
Happy Hunting!
Hi Stefan,
Thanks for this detailed post! It would be great if you consider posting your queries also on the Azure Sentinel github (https://github.com/Azure/Azure-Sentinel)
~ Ofer