Detection rules › Kusto
Solorigate Named Pipe
Identifies a match across various data feeds for named pipe IOCs related to the Solorigate incident. For the sysmon events required for this detection, logging for Named Pipe Events needs to be configured in Sysmon config (Event ID 17 and Event ID 18) Reference: https://techcommunity.microsoft.com/t5/azure-sentinel/solarwinds-post-compromise-hunting-with-azure-sentinel/ba-p/1995095
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation | |
| Stealth |
Telemetry coverage
Rule body
id: 11b4c19d-2a79-4da3-af38-b067e1273dee
name: Solorigate Named Pipe
description: |
'Identifies a match across various data feeds for named pipe IOCs related to the Solorigate incident.
For the sysmon events required for this detection, logging for Named Pipe Events needs to be configured in Sysmon config (Event ID 17 and Event ID 18)
Reference: https://techcommunity.microsoft.com/t5/azure-sentinel/solarwinds-post-compromise-hunting-with-azure-sentinel/ba-p/1995095'
severity: High
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsForwardedEvents
dataTypes:
- WindowsEvent
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
- PrivilegeEscalation
relevantTechniques:
- T1055
tags:
- Solorigate
- NOBELIUM
query: |
(union isfuzzy=true
(Event
| where Source == "Microsoft-Windows-Sysmon"
| where EventID in (17,18)
| where EventData has '583da945-62af-10e8-4902-a8f205c72b2e'
| extend EventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand bagexpansion=array EventData
| evaluate bag_unpack(EventData)
| extend Key = tostring(column_ifexists('@Name', "")), Value = column_ifexists('#text', "")
| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, MG, ManagementGroupName, _ResourceId)
| extend PipeName = column_ifexists("PipeName", "")
| extend Account = User
| extend AccountName = tostring(split(User, @"\")[1]), AccountNTDomain = tostring(split(User, @"\")[0])
),
(
SecurityEvent
| where EventID == '5145'
// %%4418 looks for presence of CreatePipeInstance value
| where AccessList has '%%4418'
| where RelativeTargetName has '583da945-62af-10e8-4902-a8f205c72b2e'
| extend AccountName = SubjectUserName, AccountNTDomain = SubjectDomainName
),
(
WindowsEvent
| where EventID == '5145' and EventData has '%%4418' and EventData has '583da945-62af-10e8-4902-a8f205c72b2e'
// %%4418 looks for presence of CreatePipeInstance value
| extend AccessList= tostring(EventData.AccessList)
| where AccessList has '%%4418'
| extend RelativeTargetName= tostring(EventData.RelativeTargetName)
| where RelativeTargetName has '583da945-62af-10e8-4902-a8f205c72b2e'
| extend Account = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
| extend AccountName = tostring(EventData.SubjectUserName), AccountNTDomain = tostring(EventData.SubjectDomainName)
)
)
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| project-away DomainIndex
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Account
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountNTDomain
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
- identifier: HostName
columnName: HostName
- identifier: NTDomain
columnName: HostNameDomain
version: 1.2.5
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
support:
tier: Community
categories:
domains: [ "Security - 0-day Vulnerability" ]
Stages and Predicates
Stage 1: union
union of 3 branches
Stage 2: source
Event
Stage 3: where
| where Source == "Microsoft-Windows-Sysmon"
Stage 4: where
| where EventID in (17,18)
Stage 5: where
| where EventData has '583da945-62af-10e8-4902-a8f205c72b2e'
Stage 6: extend
| extend EventData = parse_xml(EventData).DataItem.EventData.Data
Stage 7: mv-expand
| mv-expand bagexpansion=array EventData
Stage 8: evaluate
| evaluate bag_unpack(EventData)
Stage 9: extend
| extend Key = tostring(column_ifexists('@Name', "")), Value = column_ifexists('#text', "")
Stage 10: evaluate
| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, MG, ManagementGroupName, _ResourceId)
Stage 11: extend (3 consecutive steps)
| extend PipeName = column_ifexists("PipeName", "")
| extend Account = User
| extend AccountName = tostring(split(User, @"\")[1]), AccountNTDomain = tostring(split(User, @"\")[0])
Stage 12: source
SecurityEvent
Stage 13: where
| where EventID == '5145'
Stage 14: where
| where AccessList has '%%4418'
Stage 15: where
| where RelativeTargetName has '583da945-62af-10e8-4902-a8f205c72b2e'
Stage 16: extend
| extend AccountName = SubjectUserName, AccountNTDomain = SubjectDomainName
Stage 17: source
WindowsEvent
Stage 18: where
| where EventID == '5145' and EventData has '%%4418' and EventData has '583da945-62af-10e8-4902-a8f205c72b2e'
Stage 19: extend
| extend AccessList= tostring(EventData.AccessList)
Stage 20: where
| where AccessList has '%%4418'
Stage 21: extend
| extend RelativeTargetName= tostring(EventData.RelativeTargetName)
Stage 22: where
| where RelativeTargetName has '583da945-62af-10e8-4902-a8f205c72b2e'
Stage 23: extend (4 consecutive steps)
| extend Account = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
| extend AccountName = tostring(EventData.SubjectUserName), AccountNTDomain = tostring(EventData.SubjectDomainName)
Stage 24: project-away
project-away DomainIndex
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
AccessList | match |
| field:"AccessList" kind:match value:"%%4418" |
EventData | match |
| field:"EventData" kind:match |
EventID | eq |
| field:"EventID" kind:eq value:"5145" |
EventID | in |
| field:"EventID" kind:in |
RelativeTargetName | match |
| field:"RelativeTargetName" kind:match value:"583da945-62af-10e8-4902-a8f205c72b2e" |
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
EventData | extend |
Key | extend |
Value | extend |
PipeName | extend |
Account | extend |
AccountNTDomain | extend |
AccountName | extend |
AccessList | extend |
RelativeTargetName | extend |
HostName | extend |
HostNameDomain | extend |