Detection rules › Kusto

Sdelete deployed via GPO and run recursively (ASIM Version)

Severity
medium
Time window
1d
Group by
ActingProcessId, Dvc, ParentProcessId, timekey
Author
Microsoft Security Research
Source
github.com/Azure/Azure-Sentinel

This query looks for the Sdelete process being run recursively after being deployed to a host via GPO. Attackers could use this technique to deploy Sdelete to multiple host and delete data on them. This query uses the Advanced Security Information Model. Parsers will need to be deployed before use: https://docs.microsoft.com/azure/sentinel/normalization

MITRE ATT&CK coverage

TacticTechniques
Impact

Telemetry coverage

Rule body

id: 30c8b802-ace1-4408-bc29-4c5c5afb49e1
name: Sdelete deployed via GPO and run recursively (ASIM Version)
description: |
  'This query looks for the Sdelete process being run recursively after being deployed to a host via GPO. Attackers could use this technique to deploy Sdelete to multiple host and delete data on them.
    This query uses the Advanced Security Information Model. Parsers will need to be deployed before use: https://docs.microsoft.com/azure/sentinel/normalization'
severity: Medium
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Impact
relevantTechniques:
  - T1485
tags:
  -
query: |
  _Im_ProcessEvent
  | where EventType =~ "ProcessCreated"
  | where Process endswith "svchost.exe"
  | where CommandLine has "-k GPSvcGroup" or CommandLine has "-s gpsvc"
  | extend timekey = bin(TimeGenerated, 1m)
  | project timekey, ActingProcessId, Dvc
  | join kind=inner (
    _Im_ProcessEvent
    | where EventType =~ "ProcessCreated"
    | where Process =~ "sdelete.exe" or CommandLine has "sdelete"
    | where ActingProcessName endswith "svchost.exe"
    | where CommandLine has_all ("-s", "-r")
    | extend timekey = bin(TimeGenerated, 1m)
    ) 
    on $left.ActingProcessId == $right.ParentProcessId, timekey, Dvc
  | extend AccountName = tostring(split(ActorUsername, @'\')[1]), AccountNTDomain = tostring(split(ActorUsername, @'\')[0])
  | extend HostName = tostring(split(Dvc, ".")[0]), DomainIndex = toint(indexof(Dvc, '.'))
  | extend HostNameDomain = iff(DomainIndex != -1, substring(Dvc, DomainIndex + 1), Dvc)
  | project-away DomainIndex
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: ActorUsername
      - identifier: Name
        columnName: AccountName
      - identifier: NTDomain
        columnName: AccountNTDomain
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Dvc
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: HostNameDomain
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: DvcIpAddr
version: 1.0.6
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Microsoft Security Research
    support:
        tier: Community
    categories:
        domains: [ "Security - Threat Protection" ]

Stages and Predicates

Stage 1: source

_Im_ProcessEvent

Stage 2: where

| where EventType =~ "ProcessCreated"

Stage 3: where

| where Process endswith "svchost.exe"

Stage 4: where

| where CommandLine has "-k GPSvcGroup" or CommandLine has "-s gpsvc"

Stage 5: extend

| extend timekey = bin(TimeGenerated, 1m)

Stage 6: project

| project timekey, ActingProcessId, Dvc

Stage 7: join

| join kind=inner (
  _Im_ProcessEvent
  | where EventType =~ "ProcessCreated"
  | where Process =~ "sdelete.exe" or CommandLine has "sdelete"
  | where ActingProcessName endswith "svchost.exe"
  | where CommandLine has_all ("-s", "-r")
  | extend timekey = bin(TimeGenerated, 1m)
  ) 
  on $left.ActingProcessId == $right.ParentProcessId, timekey, Dvc

Stage 8: extend (3 consecutive steps)

| extend AccountName = tostring(split(ActorUsername, @'\')[1]), AccountNTDomain = tostring(split(ActorUsername, @'\')[0])
| extend HostName = tostring(split(Dvc, ".")[0]), DomainIndex = toint(indexof(Dvc, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Dvc, DomainIndex + 1), Dvc)

Stage 9: project-away

| project-away DomainIndex

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
ActingProcessNameends_with
  • svchost.exe corpus 2 (kusto 2)
field:"ParentImage" kind:ends_with value:"svchost.exe"
CommandLinematch
  • -k GPSvcGroup transforms: term corpus 2 (kusto 2)
  • -r transforms: term corpus 13 (sigma 9, kusto 4)
  • -s transforms: term corpus 10 (sigma 4, kusto 4, elastic 1, splunk 1)
  • -s gpsvc transforms: term corpus 2 (kusto 2)
  • sdelete transforms: term corpus 2 (kusto 2)
field:"CommandLine" kind:match
EventTypeeq
  • ProcessCreated
field:"EventType" kind:eq value:"ProcessCreated"
Processends_with
  • svchost.exe
field:"Process" kind:ends_with value:"svchost.exe"
Processeq
  • sdelete.exe corpus 2 (kusto 2)
field:"Process" kind:eq value:"sdelete.exe"

Output fields

These fields are emitted when the rule matches.

FieldSource
ActingProcessIdproject
Dvcproject
timekeyproject
AccountNTDomainextend
AccountNameextend
HostNameextend
HostNameDomainextend