Detection rules › Kusto
Kusto rules: 1s
Alsid Golden Ticket
#'Searches for Golden Ticket attacks'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Rule Body
id: 21ab3f52-6d79-47e3-97f8-ad65f2cb29fb
name: Alsid Golden Ticket
description: |
'Searches for Golden Ticket attacks'
severity: High
requiredDataConnectors:
- connectorId: AlsidForAD
dataTypes:
- AlsidForADLog_CL
queryFrequency: 2h
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- CredentialAccess
relevantTechniques:
- T1558.001
query: |
afad_parser
| where MessageType == 2 and Codename == "Golden Ticket"
| extend HostName = tostring(split(Host, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Host, '.'), 1, -1), '.'))
entityMappings:
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: DnsDomain
version: 1.0.1
kind: Scheduled
Stages and Predicates
Stage 1: source
afad_parser
Stage 2: where
| where MessageType == 2 and Codename == "Golden Ticket"
Stage 3: extend
| extend HostName = tostring(split(Host, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Host, '.'), 1, -1), '.'))
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Codename | eq |
| field:"Codename" kind:eq value:"Golden Ticket" |
MessageType | eq |
| field:"MessageType" kind:eq value:"2" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DnsDomain | extend |
HostName | extend |
Alsid Indicators of Exposures
#'Searches for triggered Indicators of Exposures'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Rule Body
id: 154fde9f-ae00-4422-a8da-ef00b11da3fc
name: Alsid Indicators of Exposures
description: |
'Searches for triggered Indicators of Exposures'
severity: Low
requiredDataConnectors:
- connectorId: AlsidForAD
dataTypes:
- AlsidForADLog_CL
queryFrequency: 2h
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- CredentialAccess
relevantTechniques:
- T1110
query: |
let SeverityTable=datatable(Severity:string,Level:int) [
"low", 1,
"medium", 2,
"high", 3,
"critical", 4
];
afad_parser
| where MessageType == 0
| lookup kind=leftouter SeverityTable on Severity
| order by Level
| extend HostName = tostring(split(Host, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Host, '.'), 1, -1), '.'))
entityMappings:
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: DnsDomain
version: 1.0.1
kind: Scheduled
Stages and Predicates
Let Binding: SeverityTable
let SeverityTable = datatable(Severity:string,Level:int) [
"low", 1,
"medium", 2,
"high", 3,
"critical", 4
];
Stage 1: source
afad_parser
Stage 2: where
| where MessageType == 0
Stage 3: kusto:lookup
lookup kind=leftouter (SeverityTable) on Severity
Stage 4: sort
sort by Level
Stage 5: extend
extend DnsDomain, HostName
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
MessageType | eq |
| field:"MessageType" kind:eq value:"0" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DnsDomain | extend |
HostName | extend |
Box - File containing sensitive data
#'Detects files which potentialy may contain sensitive data such as passwords, authentication tokens, secret keys.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Exfiltration |
Rule Body
id: 266746ae-5eaf-4068-a980-5d630f435c46
name: Box - File containing sensitive data
description: |
'Detects files which potentialy may contain sensitive data such as passwords, authentication tokens, secret keys.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: BoxDataConnector
dataTypes:
- BoxEvents_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Exfiltration
relevantTechniques:
- T1048
query: |
BoxEvents
| where SourceItemName =~ 'id_rsa' or SourceItemName contains 'password' or SourceItemName contains 'key' or SourceItemName contains '_key' or SourceItemName contains '.ssh' or SourceItemName endswith '.npmrc' or SourceItemName endswith '.muttrc' or SourceItemName contains 'config.json' or SourceItemName contains '.gitconfig' or SourceItemName endswith '.netrc' or SourceItemName endswith 'package.json' or SourceItemName endswith 'Gemfile' or SourceItemName endswith 'bower.json' or SourceItemName endswith 'config.gypi' or SourceItemName endswith 'travis.yml' or SourceFileName =~ 'id_rsa' or SourceFileName contains 'password' or SourceFileName contains 'key' or SourceFileName contains '_key' or SourceFileName contains '.ssh' or SourceFileName endswith '.npmrc' or SourceFileName endswith '.muttrc' or SourceFileName contains 'config.json' or SourceFileName contains '.gitconfig' or SourceFileName endswith '.netrc' or SourceFileName endswith 'package.json' or SourceFileName endswith 'Gemfile' or SourceFileName contains 'bower.json' or SourceFileName contains 'config.gypi' or SourceFileName contains 'travis.yml'
| extend AccountCustomEntity = SrcUserName
| extend IPCustomEntity = SrcIpAddr
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: AccountCustomEntity
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPCustomEntity
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
BoxEvents
Stage 2: where
| where SourceItemName =~ 'id_rsa' or SourceItemName contains 'password' or SourceItemName contains 'key' or SourceItemName contains '_key' or SourceItemName contains '.ssh' or SourceItemName endswith '.npmrc' or SourceItemName endswith '.muttrc' or SourceItemName contains 'config.json' or SourceItemName contains '.gitconfig' or SourceItemName endswith '.netrc' or SourceItemName endswith 'package.json' or SourceItemName endswith 'Gemfile' or SourceItemName endswith 'bower.json' or SourceItemName endswith 'config.gypi' or SourceItemName endswith 'travis.yml' or SourceFileName =~ 'id_rsa' or SourceFileName contains 'password' or SourceFileName contains 'key' or SourceFileName contains '_key' or SourceFileName contains '.ssh' or SourceFileName endswith '.npmrc' or SourceFileName endswith '.muttrc' or SourceFileName contains 'config.json' or SourceFileName contains '.gitconfig' or SourceFileName endswith '.netrc' or SourceFileName endswith 'package.json' or SourceFileName endswith 'Gemfile' or SourceFileName contains 'bower.json' or SourceFileName contains 'config.gypi' or SourceFileName contains 'travis.yml'
Stage 3: extend
| extend AccountCustomEntity = SrcUserName
Stage 4: extend
| extend IPCustomEntity = SrcIpAddr
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
SourceFileName | contains |
| field:"SourceFileName" kind:contains |
SourceFileName | ends_with |
| field:"SourceFileName" kind:ends_with |
SourceFileName | eq |
| field:"SourceFileName" kind:eq value:"id_rsa" |
SourceItemName | contains |
| field:"SourceItemName" kind:contains |
SourceItemName | ends_with |
| field:"SourceItemName" kind:ends_with |
SourceItemName | eq |
| field:"SourceItemName" kind:eq value:"id_rsa" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountCustomEntity | extend |
IPCustomEntity | extend |
Cognni Incidents for Medium Sensitivity HR Information
#This is a third-party alert feed, not a detection over modeled telemetry. The vendor product raised the finding; this rule forwards it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.
'Display incidents in which medium sensitivity HR information was placed at risk by user sharing.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Collection |
Rule Body
id: 75ff4f7d-0564-4a55-8b25-a75be951cde3
name: Cognni Incidents for Medium Sensitivity HR Information
description: |
'Display incidents in which medium sensitivity HR information was placed at risk by user sharing.'
severity: Medium
requiredDataConnectors:
- connectorId: CognniSentinelDataConnector
dataTypes:
- CognniIncidents_CL
queryFrequency: 5h
queryPeriod: 5h
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- Collection
relevantTechniques:
- T1530
query: |
let mediumRisk = 2;
let hr = 'HR Information';
CognniIncidents_CL
| where Severity == mediumRisk
| where informationType_s == hr
| where TimeGenerated >= ago(5h)
| extend AccountCustomEntity = userId_s
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: AccountCustomEntity
version: 1.0.0
kind: Scheduled
Stages and Predicates
Parameters
let mediumRisk = 2;
let hr = 'HR Information';
Stage 1: source
CognniIncidents_CL
Stage 2: where
| where Severity == mediumRisk
Stage 3: where
| where informationType_s == hr
Stage 4: where
| where TimeGenerated >= ago(5h)
Stage 5: extend
| extend AccountCustomEntity = userId_s
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Severity | eq |
| field:"Severity" kind:eq value:"2" |
informationType_s | eq |
| field:"informationType_s" kind:eq value:"HR Information" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountCustomEntity | extend |
Flare lookalike domain results
#This is a third-party alert feed, not a detection over modeled telemetry. The vendor product raised the finding; this rule forwards it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.
'This query searches for lookalike domains and SSL certificate registrations.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Reconnaissance |
Rule Body
id: 8e5ae0d6-7f2d-475e-ada3-ed33441deeba
name: Flare lookalike domain results
description: |
'This query searches for lookalike domains and SSL certificate registrations.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Flare
dataTypes:
- FireworkV2_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Reconnaissance
relevantTechniques:
- T1593
query: |
FireworkV2_CL
| where notempty(uid) and RiskScore >= 3
| extend index_name = split(uid, "/")[0]
| where index_name == "domain"
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
FireworkV2_CL
Stage 2: where
| where notempty(uid) and RiskScore >= 3
Stage 3: extend
| extend index_name = split(uid, "/")[0]
Stage 4: where
| where index_name == "domain"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
RiskScore | ge |
| field:"RiskScore" kind:ge value:"3" |
index_name | eq |
| field:"index_name" kind:eq value:"domain" |
uid | is_not_null | field:"uid" kind:is_not_null |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
index_name | extend |
Guardian- BII Detection Policy Violation Detection
#'This alert creates an incident when BII Detection Policy Violation detected from the Guardian.'
Rule Body
id: e7493b80-88d0-44fb-b11d-40a0467cc497
name: Guardian- BII Detection Policy Violation Detection
description: |
'This alert creates an incident when BII Detection Policy Violation detected from the Guardian.'
severity: High
status: Available
requiredDataConnectors:
- connectorId: BoschAIShield
dataTypes:
- Guardian
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: |
Guardian
| where PolicyViolatedControlFeature =~ 'BII Detection'
| where Severity =~ 'High'
entityMappings:
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: HostName
- identifier: NTDomain
columnName: NTDomain
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SourceIP
eventGroupingSettings:
aggregationKind: SingleAlert
alertDetailsOverride:
alertDisplayNameFormat: Guardian- BII Detection Policy Violation detection
alertDescriptionFormat: |
This query detects BII Detection Policy Violation detected from the Guardian generated at {{TimeGenerated}}.\n\nPlease check the source for more information and investigate further.
alertTacticsColumnName: null
alertSeverityColumnName: Severity
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
Guardian
Stage 2: where
| where PolicyViolatedControlFeature =~ 'BII Detection'
Stage 3: where
| where Severity =~ 'High'
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
PolicyViolatedControlFeature | eq |
| field:"PolicyViolatedControlFeature" kind:eq value:"BII Detection" |
Severity | eq |
| field:"Severity" kind:eq value:"High" |
HoneyLabs TI Map IP Entity to SigninLogs
#Identifies sign-ins (interactive and non-interactive) from IP addresses that HoneyLabs honeypot telemetry has observed running exploit or loader commands. A hit means credential access is being attempted from infrastructure with recent, evidenced malicious activity. Indicator Confidence reflects how much evidence HoneyLabs holds (90 = 100+ observed attacks, 60 = a single sighting); raise the threshold in the query to trade coverage for precision.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Credential Access |
Telemetry Coverage
Rule Body
id: a573396f-06ed-4139-bccc-e0f88a2cf625
name: HoneyLabs TI Map IP Entity to SigninLogs
version: 1.0.0
kind: Scheduled
description: |
'Identifies sign-ins (interactive and non-interactive) from IP addresses that HoneyLabs honeypot telemetry has observed running exploit or loader commands. A hit means credential access is being attempted from infrastructure with recent, evidenced malicious activity. Indicator Confidence reflects how much evidence HoneyLabs holds (90 = 100+ observed attacks, 60 = a single sighting); raise the threshold in the query to trade coverage for precision.'
severity: Medium
requiredDataConnectors:
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: AzureActiveDirectory
dataTypes:
- SigninLogs
- connectorId: AzureActiveDirectory
dataTypes:
- AADNonInteractiveUserSignInLogs
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- CredentialAccess
relevantTechniques:
- T1190
- T1110
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let HoneyLabs_IPs = ThreatIntelIndicators
| where TimeGenerated >= ago(ioc_lookBack)
| where IsActive == true and ValidUntil > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
| where SourceSystem startswith 'HoneyLabs'
| where ObservableKey == 'ipv4-addr:value'
| extend TI_ipEntity = tostring(ObservableValue),
HoneyLabsConfidence = Confidence,
HoneyLabsLabels = tostring(Data.labels),
IndicatorDescription = tostring(Data.description),
HoneyLabsReport = strcat('https://honeylabs.net/lookup/', tostring(ObservableValue));
let aadSignin = SigninLogs | where TimeGenerated >= ago(dt_lookBack)
| project TimeGenerated, IPAddress, UserPrincipalName, ResultType, AppDisplayName, Location;
let aadNonInt = AADNonInteractiveUserSignInLogs | where TimeGenerated >= ago(dt_lookBack)
| project TimeGenerated, IPAddress, UserPrincipalName, ResultType, AppDisplayName, Location;
HoneyLabs_IPs
| join kind=innerunique (union isfuzzy=true aadSignin, aadNonInt
| extend CS_ipEntity = IPAddress
| extend Signin_TimeGenerated = TimeGenerated
) on $left.TI_ipEntity == $right.CS_ipEntity
| where Signin_TimeGenerated < ValidUntil
| summarize Signin_TimeGenerated = arg_max(Signin_TimeGenerated, *) by Id, CS_ipEntity
| project Signin_TimeGenerated, IndicatorDescription, Id, ValidUntil, HoneyLabsConfidence,
HoneyLabsLabels, HoneyLabsReport, TI_ipEntity, CS_ipEntity, UserPrincipalName, ResultType,
AppDisplayName, Location
| extend timestamp = Signin_TimeGenerated
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: CS_ipEntity
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: UserPrincipalName
Stages and Predicates
Parameters
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let HoneyLabs_IPs is inlined into the numbered stages below.
Let Binding: aadSignin
let aadSignin = SigninLogs | where TimeGenerated >= ago(dt_lookBack)
| project TimeGenerated, IPAddress, UserPrincipalName, ResultType, AppDisplayName, Location;
Let Binding: aadNonInt
let aadNonInt = AADNonInteractiveUserSignInLogs | where TimeGenerated >= ago(dt_lookBack)
| project TimeGenerated, IPAddress, UserPrincipalName, ResultType, AppDisplayName, Location;
Stages 1 to 7 define let HoneyLabs_IPs as the rule's main pipeline source. Stages 8 to 12 use it.
Stage 1: source
ThreatIntelIndicators
Stage 2: where
| where TimeGenerated >= ago(ioc_lookBack)
Stage 3: where
| where IsActive == true and ValidUntil > now()
Stage 4: summarize
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id
Stage 5: where
| where SourceSystem startswith 'HoneyLabs'
Stage 6: where
| where ObservableKey == 'ipv4-addr:value'
Stage 7: extend
| extend TI_ipEntity = tostring(ObservableValue),
HoneyLabsConfidence = Confidence,
HoneyLabsLabels = tostring(Data.labels),
IndicatorDescription = tostring(Data.description),
HoneyLabsReport = strcat('https://honeylabs.net/lookup/', tostring(ObservableValue))
Stage 8: join
join kind=innerunique (...) on $left.TI_ipEntity, $right.CS_ipEntity
Stage 9: where
where Signin_TimeGenerated < ValidUntil
Stage 10: summarize
summarize Signin_TimeGenerated by Id, CS_ipEntity
Stage 11: project
project AppDisplayName, CS_ipEntity, HoneyLabsConfidence, HoneyLabsLabels, HoneyLabsReport, Id, IndicatorDescription, Location, ResultType, Signin_TimeGenerated, TI_ipEntity, UserPrincipalName, ValidUntil
Stage 12: extend
extend timestamp
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
IsActive | eq |
| field:"IsActive" kind:eq value:"true" |
ObservableKey | eq |
| field:"ObservableKey" kind:eq value:"ipv4-addr:value" |
SourceSystem | starts_with |
| field:"SourceSystem" kind:starts_with value:"HoneyLabs" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AppDisplayName | project |
CS_ipEntity | project |
HoneyLabsConfidence | project |
HoneyLabsLabels | project |
HoneyLabsReport | project |
Id | project |
IndicatorDescription | project |
Location | project |
ResultType | project |
Signin_TimeGenerated | project |
TI_ipEntity | project |
UserPrincipalName | project |
ValidUntil | project |
timestamp | extend |
Hunt MDE with GSA events
#This rule correlates the Microsoft Defender for Endpoint DeviceNetworkEvents table with the Global Secure Access NetworkAccessTraffic table. By doing this, you can enrich the MDE events which contains detailed process information with the GSA events that contains detailed HTTP header information and more.
References
Telemetry Coverage
Rule Body
let gsa_events = NetworkAccessTraffic
// Join DeviceInfo to get MDE DeviceID
| join kind=inner (
DeviceInfo
| distinct DeviceId, AadDeviceId
) on $left.DeviceId == $right.AadDeviceId
// Remove Entra Device ID from GSA logs
| project-away DeviceId
// Rename MDE Device ID to DeviceId column
| project-rename DeviceId = DeviceId1;
// Get all MDE network events
DeviceNetworkEvents
// Get HTTP details if HTTP connection is logged
| extend HttpStatus = toint(todynamic(AdditionalFields).status_code),
BytesIn = toint(todynamic(AdditionalFields).response_body_len),
BytesOut = toint(todynamic(AdditionalFields).request_body_len),
HttpMethod = tostring(todynamic(AdditionalFields).method),
UrlHostname = tostring(todynamic(AdditionalFields).host),
UrlPath = tostring(todynamic(AdditionalFields).uri),
UserAgent = tostring(todynamic(AdditionalFields).user_agent),
HttpVersion = tostring(todynamic(AdditionalFields).version)
// Join GSA logs
| join kind=inner gsa_events on
DeviceId,
$left.RemoteUrl == $right.DestinationFqdn,
$left.RemotePort == $right.DestinationPort,
$left.Protocol == $right.TransportProtocol,
$left.InitiatingProcessFileName == $right.InitiatingProcessName
| project-rename TimeGeneratedGsa = TimeGenerated1, TimestampMde = Timestamp
| project-away Type, TenantId, TimeGenerated, TenantId1, Type1, DeviceId1, AadDeviceId
let gsa_events = NetworkAccessTraffic
// Join DeviceInfo to get MDE DeviceID
| join kind=inner (
DeviceInfo
| distinct DeviceId, AadDeviceId
) on $left.DeviceId == $right.AadDeviceId
// Remove Entra Device ID from GSA logs
| project-away DeviceId
// Rename MDE Device ID to DeviceId column
| project-rename DeviceId = DeviceId1;
// Get all MDE network events
DeviceNetworkEvents
// Get HTTP details if HTTP connection is logged
| extend HttpStatus = toint(todynamic(AdditionalFields).status_code),
BytesIn = toint(todynamic(AdditionalFields).response_body_len),
BytesOut = toint(todynamic(AdditionalFields).request_body_len),
HttpMethod = tostring(todynamic(AdditionalFields).method),
UrlHostname = tostring(todynamic(AdditionalFields).host),
UrlPath = tostring(todynamic(AdditionalFields).uri),
UserAgent = tostring(todynamic(AdditionalFields).user_agent),
HttpVersion = tostring(todynamic(AdditionalFields).version)
// Join GSA logs
| join kind=inner gsa_events on
DeviceId,
$left.RemoteUrl == $right.DestinationFqdn,
$left.RemotePort == $right.DestinationPort,
$left.Protocol == $right.TransportProtocol,
$left.InitiatingProcessFileName == $right.InitiatingProcessName
| project-rename TimeGeneratedGsa = TimeGenerated2, TimestampMde = TimeGenerated
| project-away Type, TenantId, TimeGenerated, TenantId1, Type1, DeviceId1, AadDeviceId
Stages and Predicates
Let Binding: gsa_events
let gsa_events = NetworkAccessTraffic
| join kind=inner (
DeviceInfo
| distinct DeviceId, AadDeviceId
) on $left.DeviceId == $right.AadDeviceId
| project-away DeviceId
| project-rename DeviceId = DeviceId1;
Stage 1: source
let gsa_events
Stage 2: source
DeviceNetworkEvents
Stage 3: extend
extend BytesIn, BytesOut, HttpMethod, HttpStatus, HttpVersion, UrlHostname, UrlPath, UserAgent
Stage 4: join
join kind=inner (gsa_events) on DeviceId, $left.RemoteUrl, $right.DestinationFqdn, $left.RemotePort, $right.DestinationPort, $left.Protocol, $right.TransportProtocol, $left.InitiatingProcessFileName, $right.InitiatingProcessName
Stage 5: project-rename
project-rename
Stage 6: project-away
project-away AadDeviceId, DeviceId1, TenantId, TenantId1, TimeGenerated, Type, Type1
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
BytesIn | extend |
BytesOut | extend |
HttpMethod | extend |
HttpStatus | extend |
HttpVersion | extend |
UrlHostname | extend |
UrlPath | extend |
UserAgent | extend |
TimeGeneratedGsa | project-rename |
TimestampMde | project-rename |
Microsoft COVID-19 file hash indicator matches
#'Identifies a match in CommonSecurityLog Event data from any FileHash published in the Microsoft COVID-19 Threat Intel Feed - as described at https://www.microsoft.com/security/blog/2020/05/14/open-sourcing-covid-threat-intelligence/'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution |
Rule Body
id: 2be4ef67-a93f-4d8a-981a-88158cb73abd
name: Microsoft COVID-19 file hash indicator matches
description: |
'Identifies a match in CommonSecurityLog Event data from any FileHash published in the Microsoft COVID-19 Threat Intel Feed - as described at https://www.microsoft.com/security/blog/2020/05/14/open-sourcing-covid-threat-intelligence/'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: CefAma
dataTypes:
- CommonSecurityLog
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Execution
relevantTechniques:
- T1204.002
query: |
let dt_lookBack = 1h;
let covidIndicators = (externaldata(TimeGenerated:datetime, FileHashValue:string, FileHashType: string, TlpLevel: string, Product: string, ThreatType: string, Description: string )
[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Microsoft.Covid19.Indicators.csv"] with (format="csv"));
let fileHashIndicators = covidIndicators
| where isnotempty(FileHashValue);
// Handle matches against both lower case and uppercase versions of the hash:
(fileHashIndicators | extend FileHashValue = tolower(FileHashValue)
| union (fileHashIndicators | extend FileHashValue = toupper(FileHashValue)))
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
CommonSecurityLog | where TimeGenerated >= ago(dt_lookBack)
| where isnotempty(FileHash)
| extend CommonSecurityLog_TimeGenerated = TimeGenerated
)
on $left.FileHashValue == $right.FileHash
| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by FileHashValue
| project CommonSecurityLog_TimeGenerated, FileHashValue, FileHashType, Description, ThreatType,
SourceIP, SourcePort, DestinationIP, DestinationPort, SourceUserID, SourceUserName, DeviceName, DeviceAction,
RequestURL, DestinationUserName, DestinationUserID, ApplicationProtocol, Activity
| extend AccountName = tostring(split(SourceUserName, "@")[0]), AccountUPNSuffix = tostring(split(SourceUserName, "@")[1])
| extend HostName = tostring(split(DeviceName, ".")[0]), DomainIndex = toint(indexof(DeviceName, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(DeviceName, DomainIndex + 1), DeviceName)
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: SourceUserName
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: DeviceName
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: HostNameDomain
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SourceIP
- entityType: FileHash
fieldMappings:
- identifier: Value
columnName: FileHashValue
- identifier: Algorithm
columnName: FileHashType
version: 1.3.6
kind: Scheduled
Stages and Predicates
Parameters
let dt_lookBack = 1h;
let fileHashIndicators is inlined into the numbered stages below.
Let Binding: covidIndicators
let covidIndicators = (externaldata(TimeGenerated:datetime, FileHashValue:string, FileHashType: string, TlpLevel: string, Product: string, ThreatType: string, Description: string )
[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Microsoft.Covid19.Indicators.csv"] with (format="csv"));
Stages 1 to 2 define let fileHashIndicators as the rule's main pipeline source. Stages 3 to 11 combine it with further branches.
Stage 1: source
externaldata(...)
Stage 2: where
where isnotempty(FileHashValue)
Stage 3: extend
extend FileHashValue
Stage 4: union
union of 1 branches
Stage 5: source
externaldata(...)
Stage 6: where
where isnotempty(FileHashValue)
Stage 7: extend
extend FileHashValue
Stage 8: join
| join kind=innerunique (
CommonSecurityLog | where TimeGenerated >= ago(dt_lookBack)
| where isnotempty(FileHash)
| extend CommonSecurityLog_TimeGenerated = TimeGenerated
)
on $left.FileHashValue == $right.FileHash
Stage 9: summarize
summarize CommonSecurityLog_TimeGenerated by FileHashValue
Stage 10: project
project Activity, ApplicationProtocol, CommonSecurityLog_TimeGenerated, Description, DestinationIP, DestinationPort, DestinationUserID, DestinationUserName, DeviceAction, DeviceName, FileHashType, FileHashValue, RequestURL, SourceIP, SourcePort, SourceUserID, SourceUserName, ThreatType
Stage 11: extend (3 consecutive steps)
extend AccountName, AccountUPNSuffix, DomainIndex, HostName, HostNameDomain
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
FileHash | is_not_null | field:"FileHash" kind:is_not_null | |
FileHashValue | is_not_null | field:"FileHashValue" kind:is_not_null |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Activity | project |
ApplicationProtocol | project |
CommonSecurityLog_TimeGenerated | project |
Description | project |
DestinationIP | project |
DestinationPort | project |
DestinationUserID | project |
DestinationUserName | project |
DeviceAction | project |
DeviceName | project |
FileHashType | project |
FileHashValue | project |
RequestURL | project |
SourceIP | project |
SourcePort | project |
SourceUserID | project |
SourceUserName | project |
ThreatType | project |
AccountName | extend |
AccountUPNSuffix | extend |
DomainIndex | extend |
HostName | extend |
HostNameDomain | extend |
PROD (TM013.1) - OU - Block Inheritance was Enabled on an OU
#Blocking Inheritance on an OU will deny Tier Model GPOs from applying.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation | |
| Defense Impairment |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Security-Auditing | Event ID 5136: A directory service object was modified. |
Rule Body
id: 17371300-904a-4af5-9550-cf57ee727bb7
name: 'PROD (TM013.1) - OU - Block Inheritance was Enabled on an OU'
description: |
Blocking Inheritance on an OU will deny Tier Model GPOs from applying.
severity: High
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvent
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- DefenseEvasion
relevantTechniques:
- T1484.001
query: |
SecurityEvent
| where EventID == 5136
and Activity has "modified"
and EventData has '"ObjectClass">organizationalUnit'
and EventData has '<Data Name="AttributeLDAPDisplayName">gPOptions</Data>'
| extend ObjectName = extract("<Data Name=\"ObjectDN\">((?i)OU=[^,]+(,(?i)OU=[^,]+)*),(?i)DC=", 1, EventData)
| extend AttributeLDAP = extract("<Data Name=\"AttributeLDAPDisplayName\">([^<]+)</Data>", 1, EventData)
| extend AttributeValue = extract("<Data Name=\"AttributeValue\">([0-9]+)</Data>", 1, EventData)
| extend ActivityType = case(
AttributeValue == "1", "Block Inheritance Enabled",
AttributeValue == "0", "Block Inheritance Disabled",
"Block Inheritance Modified")
| extend ObjectClass = extract("<Data Name=\"ObjectClass\">([^<]+)</Data>", 1, EventData)
| extend Domain = extract("([^.]+\\.[^.]+)$", 1, Computer)
| project TimeGenerated
, ObjectName
, ObjectClass
, ActivityType
, AttributeLDAP
, Account
, Domain
, Computer
, Channel
, EventID
, EventData
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: ObjectName
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: Computer
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Account
customDetails:
ObjectName: ObjectName
ObjectClass: ObjectClass
ActivityType: ActivityType
AttributeLDAP: AttributeLDAP
Account: Account
Domain: Domain
Computer: Computer
Channel: Channel
EventID: EventID
EventData: EventData
eventGroupingSettings:
aggregationKind: AlertPerResult
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
alertDetailsOverride:
alertDisplayNameFormat: '(TM013.1) An OU was configured for Block Inheritance and is overwriting Tier Model GPOs'
alertDescriptionFormat: 'Block Inheritance was configured by {{Account}}'
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
SecurityEvent
Stage 2: where
| where EventID == 5136
and Activity has "modified"
and EventData has '"ObjectClass">organizationalUnit'
and EventData has '<Data Name="AttributeLDAPDisplayName">gPOptions</Data>'
Stage 3: extend (6 consecutive steps)
| extend ObjectName = extract("<Data Name=\"ObjectDN\">((?i)OU=[^,]+(,(?i)OU=[^,]+)*),(?i)DC=", 1, EventData)
| extend AttributeLDAP = extract("<Data Name=\"AttributeLDAPDisplayName\">([^<]+)</Data>", 1, EventData)
| extend AttributeValue = extract("<Data Name=\"AttributeValue\">([0-9]+)</Data>", 1, EventData)
| extend ActivityType = case(
AttributeValue == "1", "Block Inheritance Enabled",
AttributeValue == "0", "Block Inheritance Disabled",
"Block Inheritance Modified")
| extend ObjectClass = extract("<Data Name=\"ObjectClass\">([^<]+)</Data>", 1, EventData)
| extend Domain = extract("([^.]+\\.[^.]+)$", 1, Computer)
Stage 4: project
| project TimeGenerated
, ObjectName
, ObjectClass
, ActivityType
, AttributeLDAP
, Account
, Domain
, Computer
, Channel
, EventID
, EventData
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Activity | match |
| field:"Activity" kind:match value:"modified" |
EventData | match |
| field:"EventData" kind:match |
EventID | eq |
| field:"EventID" kind:eq value:"5136" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Account | project |
ActivityType | project |
AttributeLDAP | project |
Channel | project |
Computer | project |
Domain | project |
EventData | project |
EventID | project |
ObjectClass | project |
ObjectName | project |
TimeGenerated | project |
Radiflow - New Activity Detected
#'Generates an incident when a new asset or MAC is detected either by Radiflow's iSID.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Initial Access |
Rule Body
id: 8177ecff-30a1-4d4f-9a82-7fbb69019504
name: Radiflow - New Activity Detected
description: |
'Generates an incident when a new asset or MAC is detected either by Radiflow's iSID.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: RadiflowIsid
dataTypes:
- RadiflowEvent
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
relevantTechniques:
- T1133
- T0848
query: |
RadiflowEvent
| where DeviceProduct =~ 'iSID'
| where EventClassID in (1, 2, 3, 155)
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 1h
matchingMethod: AllEntities
groupByEntities: []
groupByAlertDetails: []
groupByCustomDetails: []
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: 'New Activity Detected (MAC: {{SourceMACAddress}} - IP: {{SourceIP}})'
alertDescriptionFormat: A previously undetected asset, link or entity has been detected in the network. Please check whether the activity is legitimate.
alertSeverityColumnName: EventSeverity
alertDynamicProperties: []
suppressionEnabled: false
suppressionDuration: 5h
customDetails:
SourceMAC: SourceMACAddress
SourceType: SourceType
SourceVendor: SourceVendor
SourceVLAN: SourceVLAN
DestinationMAC: DestinationMACAddress
DestinationType: DestinationType
DestinationVendor: DestinationVendor
Port: Port
Protocol: Protocol
SourceHostName: SourceHostName
SourceIP: SourceIP
DestinationHostName: DestinationHostName
DestinationIP: DestinationIP
entityMappings:
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: SourceHostName
- identifier: NetBiosName
columnName: SourceHostName
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: DestinationHostName
- identifier: NetBiosName
columnName: DestinationHostName
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SourceIP
- entityType: IP
fieldMappings:
- identifier: Address
columnName: DestinationIP
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
RadiflowEvent
Stage 2: where
| where DeviceProduct =~ 'iSID'
Stage 3: where
| where EventClassID in (1, 2, 3, 155)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DeviceProduct | eq |
| field:"DeviceProduct" kind:eq value:"iSID" |
EventClassID | in |
| field:"EventClassID" kind:in |
Starting or Stopping HealthService to Avoid Detection
#This query detects events where an actor is stopping or starting HealthService to disable telemetry collection/detection from the agent. The query requires a SACL to audit for access request to the service.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment |
Telemetry Coverage
Rule Body
id: 2bc7b4ae-eeaa-4538-ba15-ef298ec1ffae
name: Starting or Stopping HealthService to Avoid Detection
description: |
'This query detects events where an actor is stopping or starting HealthService to disable telemetry collection/detection from the agent.
The query requires a SACL to audit for access request to the service.'
severity: Medium
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvent
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- DefenseEvasion
relevantTechniques:
- T1562.001
tags:
- Solorigate
- NOBELIUM
query: |
SecurityEvent
| where EventID == 4656
| extend EventData = parse_xml(EventData).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, TargetAccount, Computer, EventSourceName, Channel, Task, Level, EventID, Activity, TargetLogonId, SourceComputerId, EventOriginId, Type, _ResourceId, TenantId, SourceSystem, ManagementGroupName, IpAddress, Account)
| extend ObjectServer = column_ifexists('ObjectServer', ""), ObjectType = column_ifexists('ObjectType', ""), ObjectName = column_ifexists('ObjectName', "")
| where isnotempty(ObjectServer) and isnotempty(ObjectType) and isnotempty(ObjectName)
| where ObjectServer =~ "SC Manager" and ObjectType =~ "SERVICE OBJECT" and ObjectName =~ "HealthService"
// Comment out the join below if the SACL only audits users that are part of the Network logon users, i.e. with user/group target pointing to "NU."
| join kind=leftouter (
SecurityEvent
| where EventID == 4624
) on TargetLogonId
| project TimeGenerated, Computer, Account, TargetAccount, IpAddress,TargetLogonId, ObjectServer, ObjectType, ObjectName
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountName = tostring(split(TargetAccount, @'\')[1]), AccountNTDomain = tostring(split(TargetAccount, @'\')[0])
| extend timestamp = TimeGenerated
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: TargetAccount
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountNTDomain
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: HostNameDomain
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IpAddress
version: 1.0.2
kind: Scheduled
Stages and Predicates
Stage 1: source
SecurityEvent
Stage 2: where
| where EventID == 4656
Stage 3: extend
| extend EventData = parse_xml(EventData).EventData.Data
Stage 4: mv-expand
| mv-expand bagexpansion=array EventData
Stage 5: evaluate
| evaluate bag_unpack(EventData)
Stage 6: extend
| extend Key = tostring(column_ifexists('@Name', "")), Value = column_ifexists('#text', "")
Stage 7: evaluate
| evaluate pivot(Key, any(Value), TimeGenerated, TargetAccount, Computer, EventSourceName, Channel, Task, Level, EventID, Activity, TargetLogonId, SourceComputerId, EventOriginId, Type, _ResourceId, TenantId, SourceSystem, ManagementGroupName, IpAddress, Account)
Stage 8: extend
| extend ObjectServer = column_ifexists('ObjectServer', ""), ObjectType = column_ifexists('ObjectType', ""), ObjectName = column_ifexists('ObjectName', "")
Stage 9: where
| where isnotempty(ObjectServer) and isnotempty(ObjectType) and isnotempty(ObjectName)
Stage 10: where
| where ObjectServer =~ "SC Manager" and ObjectType =~ "SERVICE OBJECT" and ObjectName =~ "HealthService"
Stage 11: join
| join kind=leftouter (
SecurityEvent
| where EventID == 4624
) on TargetLogonId
Stage 12: project
project Account, Computer, IpAddress, ObjectName, ObjectServer, ObjectType, TargetAccount, TargetLogonId, TimeGenerated
Stage 13: extend (4 consecutive steps)
extend AccountNTDomain, AccountName, DomainIndex, HostName, HostNameDomain, timestamp
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventID | eq |
| field:"EventID" kind:eq |
ObjectName | eq |
| field:"ObjectName" kind:eq value:"HealthService" |
ObjectName | is_not_null | field:"ObjectName" kind:is_not_null | |
ObjectServer | eq |
| field:"ObjectServer" kind:eq value:"SC Manager" |
ObjectServer | is_not_null | field:"ObjectServer" kind:is_not_null | |
ObjectType | eq |
| field:"ObjectType" kind:eq value:"SERVICE OBJECT" |
ObjectType | is_not_null | field:"ObjectType" kind:is_not_null |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Account | project |
Computer | project |
IpAddress | project |
ObjectName | project |
ObjectServer | project |
ObjectType | project |
TargetAccount | project |
TargetLogonId | project |
TimeGenerated | project |
DomainIndex | extend |
HostName | extend |
HostNameDomain | extend |
AccountNTDomain | extend |
AccountName | extend |
timestamp | extend |
Tenant Replica Stopped
#Detects when a tenant replica stops.
Rule Body
id: ef029652-d004-44e9-a70a-48dd71818aaa
name: Tenant Replica Stopped
description: Detects when a tenant replica stops.
severity: High
status: Available
requiredDataConnectors:
- connectorId: Syslog
dataTypes:
- Syslog
- connectorId: SyslogAma
dataTypes:
- Syslog
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: "Veeam_GetSecurityEvents\n| where instanceId == 26900\n| project\n Date\
\ = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),\n DataSource = original_host,\n\
\ EventId = instanceId,\n [\"User Name\"] = user,\n MessageDetails = Description,\n\
\ Severity = SeverityDescription"
version: 1.0.1
kind: Scheduled
customDetails:
Date: Date
VbrHostName: DataSource
EventId: EventId
MessageDetails: MessageDetails
Severity: Severity
Stages and Predicates
Stage 1: source
Veeam_GetSecurityEvents
Stage 2: where
| where instanceId == 26900
Stage 3: project
| project
Date = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),
DataSource = original_host,
EventId = instanceId,
["User Name"] = user,
MessageDetails = Description,
Severity = SeverityDescription
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
instanceId | eq |
| field:"instanceId" kind:eq value:"26900" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DataSource | project |
Date | project |
EventId | project |
MessageDetails | project |
Severity | project |
User Name | project |
Veeam ONE Application with No Recent Data Backup Sessions
#This is a third-party alert feed, not a detection over modeled telemetry. The vendor product raised the finding; this rule forwards it into the SIEM. It is searchable for reference but is excluded from the detection-rule browse and the ATT&CK coverage matrix.
Detects applications with no recent backup sessions.
Rule Body
id: 73e36985-d65d-4852-b3cc-5e8f4b64b39c
name: Veeam ONE Application with No Recent Data Backup Sessions
description: Detects applications with no recent backup sessions.
severity: High
status: Available
requiredDataConnectors:
- connectorId: VeeamCustomTablesDataConnector
dataTypes:
- VeeamOneTriggeredAlarms_CL
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
aggregationKind: AlertPerResult
tactics: []
relevantTechniques: []
query: VeeamOneTriggeredAlarms_CL | where PredefinedAlarmId == 391
version: 1.0.1
kind: Scheduled
customDetails:
PredefinedAlarmId: PredefinedAlarmId
TriggeredAlarmId: TriggeredAlarmId
Description: Description
Name: Name
VoneHostName: VoneHostName
TriggeredTime: TriggeredTime
Status: Status
Comment: Comment
ObjectId: ObjectId
ObjectName: ObjectName
ObjectType: ObjectType
Stages and Predicates
Stage 1: source
VeeamOneTriggeredAlarms_CL
Stage 2: where
| where PredefinedAlarmId == 391
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
PredefinedAlarmId | eq |
| field:"PredefinedAlarmId" kind:eq value:"391" |
VMware ESXi - Multiple VMs stopped
#'Detects when multiple VMs ware stopped by user.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Rule Body
id: 5fe1af14-cd40-48ff-b581-3a12a1f90785
name: VMware ESXi - Multiple VMs stopped
description: |
'Detects when multiple VMs ware stopped by user.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: SyslogAma
datatypes:
- Syslog
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
relevantTechniques:
- T1529
query: |
let threshold = 5;
VMwareESXi
| where SyslogMessage has ('VmPoweredOffEvent')
| extend SrcUsername = extract(@'\[info\]\s+\[(.*?)\]', 1, SyslogMessage)
| extend DstHostname = extract(@'\[\d+\]\s+\[(.*?)\s+on', 1, SyslogMessage)
| summarize st_vm = make_set(DstHostname,200) by SrcUsername, bin(TimeGenerated, 5m)
| where array_length(st_vm) > threshold
| extend hostname = iff(array_length(st_vm) > 0, st_vm[0], "")
| extend NTDomain = tostring(split(hostname, '\\', 0)[0]), Name = tostring(split(SrcUsername, '\\', 1)[0]), HostName = tostring(split(hostname, '.', 0)[0]), DnsDomain = tostring(split(SrcUsername, '\\', 1)[0])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: DnsDomain
columnName: DnsDomain
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: HostName
- identifier: NTDomain
columnName: NTDomain
version: 1.0.3
kind: Scheduled
Stages and Predicates
Parameters
let threshold = 5;
Stage 1: source
VMwareESXi
Stage 2: where
| where SyslogMessage has ('VmPoweredOffEvent')
Stage 3: extend
| extend SrcUsername = extract(@'\[info\]\s+\[(.*?)\]', 1, SyslogMessage)
Stage 4: extend
| extend DstHostname = extract(@'\[\d+\]\s+\[(.*?)\s+on', 1, SyslogMessage)
Stage 5: summarize
| summarize st_vm = make_set(DstHostname,200) by SrcUsername, bin(TimeGenerated, 5m)
Stage 6: where
| where array_length(st_vm) > threshold
Stage 7: extend
| extend hostname = iff(array_length(st_vm) > 0, st_vm[0], "")
hostname =st_vm > 0st_vm[0]""Stage 8: extend
| extend NTDomain = tostring(split(hostname, '\\', 0)[0]), Name = tostring(split(SrcUsername, '\\', 1)[0]), HostName = tostring(split(hostname, '.', 0)[0]), DnsDomain = tostring(split(SrcUsername, '\\', 1)[0])
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
SyslogMessage | match |
| field:"SyslogMessage" kind:match value:"VmPoweredOffEvent" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
SrcUsername | summarize |
st_vm | summarize |
hostname | extend |
DnsDomain | extend |
HostName | extend |
NTDomain | extend |
Name | extend |