Detection rules › Kusto
Kusto rules: 12
AppServices AV Scan Failure
#'Identifies if an AV scan fails in Azure App Services.'
Rule Body
id: c2da1106-bfe4-4a63-bf14-5ab73130ccd5
name: AppServices AV Scan Failure
description: |
'Identifies if an AV scan fails in Azure App Services.'
severity: Informational
requiredDataConnectors: []
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 1
query: |
let timeframe = ago(1d);
AppServiceAntivirusScanAuditLogs
| where ScanStatus == "Failed"
| extend timestamp = TimeGenerated
entityMappings:
- entityType: Host
fieldMappings:
- identifier: AzureID
columnName: _ResourceId
version: 1.0.3
kind: Scheduled
metadata:
source:
kind: Community
author:
name: SecurityJedi
support:
tier: Community
categories:
domains: [ "Security - Others", "Platform" ]
Stages and Predicates
Parameters
let timeframe = ago(1d);
Stage 1: source
AppServiceAntivirusScanAuditLogs
Stage 2: where
| where ScanStatus == "Failed"
Stage 3: extend
| extend timestamp = TimeGenerated
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ScanStatus | eq |
| field:"ScanStatus" kind:eq value:"Failed" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
timestamp | extend |
Azure DevOps Pipeline Created and Deleted on the Same Day
#'An attacker with access to Azure DevOps could create a pipeline to inject artifacts used by other pipelines, or to create a malicious software build that looks legitimate by using a pipeline that incorporates legitimate elements. An attacker would also likely want to cover their tracks once conducting such activity. This query looks for Pipelines created and deleted within the same day, this is unlikely to be legitimate user activity in the majority of cases.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Execution |
Rule Body
id: 17f23fbe-bb73-4324-8ecf-a18545a5dc26
name: Azure DevOps Pipeline Created and Deleted on the Same Day
description: |
'An attacker with access to Azure DevOps could create a pipeline to inject artifacts used by other pipelines, or to create a malicious software build that looks legitimate by using a pipeline that incorporates legitimate elements.
An attacker would also likely want to cover their tracks once conducting such activity. This query looks for Pipelines created and deleted within the same day, this is unlikely to be legitimate user activity in the majority of cases.'
severity: Medium
status: Available
requiredDataConnectors: []
queryFrequency: 3d
queryPeriod: 3d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Execution
relevantTechniques:
- T1072
query: |
let timeframe = 3d;
// Get Release Pipeline Creation Events and group by day
ADOAuditLogs
| where TimeGenerated > ago(timeframe)
| where OperationName =~ "Release.ReleasePipelineCreated"
// Group by day
| extend timekey = bin(TimeGenerated, 1d)
| extend PipelineId = tostring(Data.PipelineId)
| extend PipelineName = tostring(Data.PipelineName)
// Rename some columns to make output clearer
| project-rename TimeCreated = TimeGenerated, CreatingUser = ActorUPN, CreatingUserAgent = UserAgent, CreatingIP = IpAddress
// Join with Release Pipeline Deletions where Pipeline ID is the same and deletion occurred on same day as creation
| join (ADOAuditLogs
| where TimeGenerated > ago(timeframe)
| where OperationName =~ "Release.ReleasePipelineDeleted"
// Group by day
| extend timekey = bin(TimeGenerated, 1d)
| extend PipelineId = tostring(Data.PipelineId)
| extend PipelineName = tostring(Data.PipelineName)
// Rename some things to make the output clearer
| project-rename TimeDeleted = TimeGenerated,DeletingUser = ActorUPN, DeletingUserAgent = UserAgent, DeletingIP = IpAddress) on PipelineId, timekey
| project TimeCreated, TimeDeleted, PipelineName, PipelineId, CreatingUser, CreatingIP, CreatingUserAgent, DeletingUser, DeletingIP, DeletingUserAgent, ScopeDisplayName, ProjectName, Data, OperationName, OperationName1
| extend timestamp = TimeCreated
| extend CreatingUserAccountName = tostring(split(CreatingUser, "@")[0]), CreatingUserAccountUPNSuffix = tostring(split(CreatingUser, "@")[1])
| extend DeletingUserAccountName = tostring(split(DeletingUser, "@")[0]), DeletingUserAccountUPNSuffix = tostring(split(DeletingUser, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: CreatingUser
- identifier: Name
columnName: CreatingUserAccountName
- identifier: UPNSuffix
columnName: CreatingUserAccountUPNSuffix
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: DeletingUser
- identifier: Name
columnName: DeletingUserAccountName
- identifier: UPNSuffix
columnName: DeletingUserAccountUPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: CreatingIP
- entityType: IP
fieldMappings:
- identifier: Address
columnName: DeletingIP
version: 1.0.4
kind: Scheduled
Stages and Predicates
Parameters
let timeframe = 3d;
Stage 1: source
ADOAuditLogs
Stage 2: where
| where TimeGenerated > ago(timeframe)
Stage 3: where
| where OperationName =~ "Release.ReleasePipelineCreated"
Stage 4: extend (3 consecutive steps)
| extend timekey = bin(TimeGenerated, 1d)
| extend PipelineId = tostring(Data.PipelineId)
| extend PipelineName = tostring(Data.PipelineName)
Stage 5: project-rename
| project-rename TimeCreated = TimeGenerated, CreatingUser = ActorUPN, CreatingUserAgent = UserAgent, CreatingIP = IpAddress
Stage 6: join
| join (ADOAuditLogs
| where TimeGenerated > ago(timeframe)
| where OperationName =~ "Release.ReleasePipelineDeleted"
| extend timekey = bin(TimeGenerated, 1d)
| extend PipelineId = tostring(Data.PipelineId)
| extend PipelineName = tostring(Data.PipelineName)
| project-rename TimeDeleted = TimeGenerated,DeletingUser = ActorUPN, DeletingUserAgent = UserAgent, DeletingIP = IpAddress) on PipelineId, timekey
Stage 7: project
project CreatingIP, CreatingUser, CreatingUserAgent, Data, DeletingIP, DeletingUser, DeletingUserAgent, OperationName, OperationName1, PipelineId, PipelineName, ProjectName, ScopeDisplayName, TimeCreated, TimeDeleted
Stage 8: extend (3 consecutive steps)
extend CreatingUserAccountName, CreatingUserAccountUPNSuffix, DeletingUserAccountName, DeletingUserAccountUPNSuffix, timestamp
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
OperationName | eq |
| field:"OperationName" kind:eq |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
CreatingIP | project |
CreatingUser | project |
CreatingUserAgent | project |
Data | project |
DeletingIP | project |
DeletingUser | project |
DeletingUserAgent | project |
OperationName | project |
OperationName1 | project |
PipelineId | project |
PipelineName | project |
ProjectName | project |
ScopeDisplayName | project |
TimeCreated | project |
TimeDeleted | project |
timestamp | extend |
CreatingUserAccountName | extend |
CreatingUserAccountUPNSuffix | extend |
DeletingUserAccountName | extend |
DeletingUserAccountUPNSuffix | extend |
Bitglass - Impossible travel distance
#'Detects logins from different geo locations.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Rule Body
id: cdb6e4a4-b9bd-4c30-94b9-ecce5a72d528
name: Bitglass - Impossible travel distance
description: |
'Detects logins from different geo locations.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Bitglass
dataTypes:
- Bitglass
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
relevantTechniques:
- T1078
query: |
Bitglass
| where EventType =~ 'access'
| where EventResultDetails startswith 'Simultaneous logins from geographically distant locations'
| extend AccountCustomEntity = User
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountCustomEntity
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
Bitglass
Stage 2: where
| where EventType =~ 'access'
Stage 3: where
| where EventResultDetails startswith 'Simultaneous logins from geographically distant locations'
Stage 4: extend
| extend AccountCustomEntity = User
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EventResultDetails | starts_with |
| field:"EventResultDetails" kind:starts_with value:"Simultaneous logins from geographically distant locations" |
EventType | eq |
| field:"EventType" kind:eq value:"access" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountCustomEntity | extend |
BloodHound Attack Path Finding - Cloud App Admin Over Tier Zero Principal
#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.
BloodHound Attack Path Finding - Cloud App Admin Over Tier Zero Principal
Rule Body
id: 39984923-f74a-45ea-b321-b1dd45ba04e2
name: BloodHound Attack Path Finding - Cloud App Admin Over Tier Zero Principal
description: BloodHound Attack Path Finding - Cloud App Admin Over Tier Zero Principal
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: BloodHoundEnterprise
dataTypes:
- BHEAttackPathsData_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: BHEAttackPathsData_CL | where Finding == "AzureT0CloudAppAdmin"
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: domain_name
customDetails:
Description: ShortDescription
Remediation: ShortRemediation
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
BHEAttackPathsData_CL
Stage 2: where
| where Finding == "AzureT0CloudAppAdmin"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Finding | eq |
| field:"Finding" kind:eq value:"AzureT0CloudAppAdmin" |
BloodHound Attack Path Finding - Kerberoastable User Accounts
#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.
BloodHound Attack Path Finding - Kerberoastable User Accounts
Rule Body
id: 008a74e7-ad90-4855-87e6-6bdb86eed127
name: BloodHound Attack Path Finding - Kerberoastable User Accounts
description: BloodHound Attack Path Finding - Kerberoastable User Accounts
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: BloodHoundEnterprise
dataTypes:
- BHEAttackPathsData_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: BHEAttackPathsData_CL | where Finding == "Kerberoasting"
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: domain_name
customDetails:
Description: ShortDescription
Remediation: ShortRemediation
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
BHEAttackPathsData_CL
Stage 2: where
| where Finding == "Kerberoasting"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Finding | eq |
| field:"Finding" kind:eq value:"Kerberoasting" |
BloodHound Attack Path Finding - Large Default Groups in Local Administrator Groups
#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.
BloodHound Attack Path Finding - Large Default Groups in Local Administrator Groups
Rule Body
id: 141b9381-50fe-4beb-a91a-799da4f466fc
name: BloodHound Attack Path Finding - Large Default Groups in Local Administrator
Groups
description: BloodHound Attack Path Finding - Large Default Groups in Local Administrator
Groups
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: BloodHoundEnterprise
dataTypes:
- BHEAttackPathsData_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: BHEAttackPathsData_CL | where Finding == "LargeDefaultGroupsAdmins"
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: domain_name
customDetails:
Description: ShortDescription
Remediation: ShortRemediation
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
BHEAttackPathsData_CL
Stage 2: where
| where Finding == "LargeDefaultGroupsAdmins"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Finding | eq |
| field:"Finding" kind:eq value:"LargeDefaultGroupsAdmins" |
BloodHound Attack Path Finding - Large Default Groups With WriteGpLink Privilege
#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.
BloodHound Attack Path Finding - Large Default Groups With WriteGpLink Privilege
Rule Body
id: 660af442-45ec-4321-b6ce-ee39677f0472
name: BloodHound Attack Path Finding - Large Default Groups With WriteGpLink Privilege
description: BloodHound Attack Path Finding - Large Default Groups With WriteGpLink
Privilege
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: BloodHoundEnterprise
dataTypes:
- BHEAttackPathsData_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics: []
relevantTechniques: []
query: BHEAttackPathsData_CL | where Finding == "LargeDefaultGroupsWriteGPLink"
entityMappings:
- entityType: URL
fieldMappings:
- identifier: Url
columnName: domain_name
customDetails:
Description: ShortDescription
Remediation: ShortRemediation
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
BHEAttackPathsData_CL
Stage 2: where
| where Finding == "LargeDefaultGroupsWriteGPLink"
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Finding | eq |
| field:"Finding" kind:eq value:"LargeDefaultGroupsWriteGPLink" |
CYFIRMA - Brand Intelligence - Malicious Mobile App Medium Rule
#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 analytic rule detects instances where malicious or unauthorized mobile applications are discovered mimicking legitimate brand assets. Such impersonations may be distributed through unofficial app stores or third-party websites, potentially deceiving customers, harvesting sensitive data, or damaging brand reputation. This alert is triggered when CYFIRMA threat intelligence identifies a suspicious mobile app associated with the organization's brand or product names."
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Resource Development | |
| Execution | |
| Defense Evasion | |
| Credential Access | |
| Collection | |
| Command and Control |
Rule Body
id: b73e6628-d44c-4ad3-a801-ea225c5744ee
name: CYFIRMA - Brand Intelligence - Malicious Mobile App Medium Rule
description: |
"This analytic rule detects instances where malicious or unauthorized mobile applications are discovered mimicking legitimate brand assets.
Such impersonations may be distributed through unofficial app stores or third-party websites, potentially deceiving customers, harvesting sensitive data, or damaging brand reputation.
This alert is triggered when CYFIRMA threat intelligence identifies a suspicious mobile app associated with the organization's brand or product names."
version: 1.0.1
kind: Scheduled
severity: Medium
requiredDataConnectors:
- connectorId: CyfirmaBrandIntelligenceAlertsDC
dataTypes:
- CyfirmaBIMaliciousMobileAppsAlerts_CL
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- ResourceDevelopment
- Execution
- DefenseEvasion
- CredentialAccess
- CommandAndControl
relevantTechniques:
- T1406
- T1414
- T1437
- T1583.001
- T1204.002
query: |
// Medium severity - Malicious Mobile App Impersonation
let timeFrame = 5m;
CyfirmaBIMaliciousMobileAppsAlerts_CL
| where severity == 'High' and TimeGenerated between (ago(timeFrame) .. now())
| extend
Description=description,
FirstSeen=first_seen,
LastSeen=last_seen,
RiskScore=risk_score,
AlertUID=alert_uid,
UID=uid,
AssetType=asset_type,
AssetValue=asset_value,
Impact=impact,
Recommendation=recommendation,
ProviderName='CYFIRMA',
ProductName='DeCYFIR/DeTCT'
| project
TimeGenerated,
Description,
RiskScore,
FirstSeen,
LastSeen,
AlertUID,
UID,
AssetType,
AssetValue,
Impact,
Recommendation,
ProductName,
ProviderName
customDetails:
AssetType: AssetType
AssetValue: AssetValue
Impact: Impact
Recommendation: Recommendation
Description: Description
RiskScore: RiskScore
TimeGenerated: TimeGenerated
FirstSeen: FirstSeen
LastSeen: LastSeen
AlertUID: AlertUID
UID: UID
alertDetailsOverride:
alertDisplayNameFormat: "CYFIRMA - Medium Severity Alert: Malicious Mobile App Impersonating Brand Detected - {{AssetType}} - {{AssetValue}} "
alertDescriptionFormat: "{{Description}} "
alertDynamicProperties:
- alertProperty: ProductName
value: ProductName
- alertProperty: ProviderName
value: ProviderName
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
eventGroupingSettings:
aggregationKind: AlertPerResult
Stages and Predicates
Parameters
let timeFrame = 5m;
Stage 1: source
CyfirmaBIMaliciousMobileAppsAlerts_CL
Stage 2: where
| where severity == 'High' and TimeGenerated between (ago(timeFrame) .. now())
Stage 3: extend
| extend
Description=description,
FirstSeen=first_seen,
LastSeen=last_seen,
RiskScore=risk_score,
AlertUID=alert_uid,
UID=uid,
AssetType=asset_type,
AssetValue=asset_value,
Impact=impact,
Recommendation=recommendation,
ProviderName='CYFIRMA',
ProductName='DeCYFIR/DeTCT'
Stage 4: project
| project
TimeGenerated,
Description,
RiskScore,
FirstSeen,
LastSeen,
AlertUID,
UID,
AssetType,
AssetValue,
Impact,
Recommendation,
ProductName,
ProviderName
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
severity | eq |
| field:"severity" kind:eq value:"High" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AlertUID | project |
AssetType | project |
AssetValue | project |
Description | project |
FirstSeen | project |
Impact | project |
LastSeen | project |
ProductName | project |
ProviderName | project |
Recommendation | project |
RiskScore | project |
TimeGenerated | project |
UID | project |
Dataverse - TI map IP to DataverseActivity
#Identifies a match in DataverseActivity from any IP IOC from Microsoft Sentinel Threat Intelligence.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Initial Access | |
| Discovery | |
| Lateral Movement | |
| Lateral Movement | |
| Initial Access | |
| Persistence | |
| Lateral Movement |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | any: Dataverse and model-driven apps audit (catch-all) |
Rule Body
id: 56d5aa0c-d871-4167-ba13-61c2f0fd17bf
kind: Scheduled
name: Dataverse - TI map IP to DataverseActivity
description: Identifies a match in DataverseActivity from any IP IOC from Microsoft
Sentinel Threat Intelligence.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Dataverse
dataTypes:
- DataverseActivity
- connectorId: ThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: ThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
dataTypes:
- ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
dataTypes:
- ThreatIntelligenceIndicator
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- LateralMovement
- Discovery
relevantTechniques:
- T1078
- T1199
- T1133
- T0886
- T0859
- T1428
- T1021
- T1210
- T1526
- T1580
query: |
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true
// Picking up only IOC's that contain the entities we want
| where isnotempty(NetworkIP)
or isnotempty(EmailSourceIpAddress)
or isnotempty(NetworkDestinationIP)
or isnotempty(NetworkSourceIP)
// As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.
// Taking the first non-empty value based on potential IOC match availability
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
//Exclude local addresses, using the ipv4_is_private operator
| where ipv4_is_private(TI_ipEntity) == false
and TI_ipEntity !startswith "fe80"
and TI_ipEntity !startswith "::"
and TI_ipEntity !startswith "127."
// 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 (
DataverseActivity
| where TimeGenerated >= ago(dt_lookBack)
| where isnotempty(ClientIp)
//Exclude local addresses, using the ipv4_is_private operator
| where ipv4_is_private(ClientIp) == false
and ClientIp !startswith "fe80"
and ClientIp !startswith "::"
and ClientIp !startswith "127."
// renaming time column so it is clear the log this came from
| extend DataverseActivity_TimeGenerated = TimeGenerated
)
on $left.TI_ipEntity == $right.ClientIp
| where DataverseActivity_TimeGenerated < ExpirationDateTime
| summarize DataverseActivity_TimeGenerated = arg_max(DataverseActivity_TimeGenerated, *) by IndicatorId, ClientIp
| project DataverseActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,
TI_ipEntity, ClientIp, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, InstanceUrl, UserId
| extend
timestamp = DataverseActivity_TimeGenerated,
AccountName = tostring(split(UserId, '@')[0]),
UPNSuffix = tostring(split(UserId, '@')[0]),
CloudAppId = int(32780)
eventGroupingSettings:
aggregationKind: AlertPerResult
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: ClientIp
- entityType: URL
fieldMappings:
- identifier: Url
columnName: Url
- entityType: CloudApplication
fieldMappings:
- identifier: AppId
columnName: CloudAppId
- identifier: InstanceName
columnName: InstanceUrl
alertDetailsOverride:
alertDisplayNameFormat: 'Dataverse - TI map IP in {{InstanceUrl}} '
alertDescriptionFormat: Malicous IP {{ClientIp}} was found in {{InstanceUrl}} .
User affected is {{UserId}}
version: 3.2.0
Stages and Predicates
Parameters
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
Stage 1: source
ThreatIntelligenceIndicator
Stage 2: where
| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()
Stage 3: summarize
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
Stage 4: where
| where Active == true
Stage 5: where
| where isnotempty(NetworkIP)
or isnotempty(EmailSourceIpAddress)
or isnotempty(NetworkDestinationIP)
or isnotempty(NetworkSourceIP)
Stage 6: extend (3 consecutive steps)
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
TI_ipEntity =isnotempty(NetworkIP)NetworkIPNetworkDestinationIPStage 7: where
| where ipv4_is_private(TI_ipEntity) == false
and TI_ipEntity !startswith "fe80"
and TI_ipEntity !startswith "::"
and TI_ipEntity !startswith "127."
Stage 8: join
| join kind=innerunique (
DataverseActivity
| where TimeGenerated >= ago(dt_lookBack)
| where isnotempty(ClientIp)
| where ipv4_is_private(ClientIp) == false
and ClientIp !startswith "fe80"
and ClientIp !startswith "::"
and ClientIp !startswith "127."
| extend DataverseActivity_TimeGenerated = TimeGenerated
)
on $left.TI_ipEntity == $right.ClientIp
Stage 9: where
where DataverseActivity_TimeGenerated < ExpirationDateTime
Stage 10: summarize
summarize DataverseActivity_TimeGenerated by IndicatorId, ClientIp
Stage 11: project
project ActivityGroupNames, ClientIp, ConfidenceScore, DataverseActivity_TimeGenerated, Description, EmailSourceIpAddress, ExpirationDateTime, IndicatorId, InstanceUrl, NetworkDestinationIP, NetworkIP, NetworkSourceIP, TI_ipEntity, ThreatType, Url, UserId
Stage 12: extend
extend AccountName, CloudAppId, UPNSuffix, timestamp
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Active | eq |
| field:"Active" kind:eq value:"true" |
ClientIp | is_not_null | field:"ClientIp" kind:is_not_null | |
EmailSourceIpAddress | is_not_null | field:"EmailSourceIpAddress" kind:is_not_null | |
NetworkDestinationIP | is_not_null | field:"NetworkDestinationIP" kind:is_not_null | |
NetworkIP | is_not_null | field:"NetworkIP" kind:is_not_null | |
NetworkSourceIP | is_not_null | field:"NetworkSourceIP" kind:is_not_null |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
TI_ipEntity | cidr_match | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, 127.0.0.0/8 | excludes:TI_ipEntity |
TI_ipEntity | starts_with | 127. | excludes:TI_ipEntity field:"TI_ipEntity" value:"127." |
TI_ipEntity | starts_with | :: | excludes:TI_ipEntity field:"TI_ipEntity" value:"::" |
TI_ipEntity | starts_with | fe80 | excludes:TI_ipEntity field:"TI_ipEntity" value:"fe80" |
ClientIp | cidr_match | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, 127.0.0.0/8 | excludes:ClientIp |
ClientIp | starts_with | 127. | excludes:ClientIp field:"ClientIp" value:"127." |
ClientIp | starts_with | :: | excludes:ClientIp field:"ClientIp" value:"::" |
ClientIp | starts_with | fe80 | excludes:ClientIp field:"ClientIp" value:"fe80" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActivityGroupNames | project |
ClientIp | project |
ConfidenceScore | project |
DataverseActivity_TimeGenerated | project |
Description | project |
EmailSourceIpAddress | project |
ExpirationDateTime | project |
IndicatorId | project |
InstanceUrl | project |
NetworkDestinationIP | project |
NetworkIP | project |
NetworkSourceIP | project |
TI_ipEntity | project |
ThreatType | project |
Url | project |
UserId | project |
AccountName | extend |
CloudAppId | extend |
UPNSuffix | extend |
timestamp | extend |
MosaicLoader
#This query looks Malware Hides Itself Among Windows Defender Exclusions to Evade Detection.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Defense Impairment |
Telemetry Coverage
Rule Body
id: 506f4d6b-3864-4bb1-8f75-a13fb066f97a
name: MosaicLoader
description: |
This query looks Malware Hides Itself Among Windows Defender Exclusions to Evade Detection.
severity: High
status: Available
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceRegistryEvents
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
relevantTechniques:
- T1562
tags:
- MosaicLoader
- Windows Defender Exclusions
query: |
DeviceRegistryEvents
| where ((ActionType == "RegistryValueSet") and (RegistryKey startswith @"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions\\Paths"
or RegistryKey startswith @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Extensions"
or RegistryKey startswith @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Processes"))
| extend HostName = iff(DeviceName has '.', substring(DeviceName, 0, indexof(DeviceName, '.')), DeviceName)
| extend DnsDomain = iff(DeviceName has '.', substring(DeviceName, indexof(DeviceName, '.') + 1), "")
entityMappings:
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: DeviceName
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: DnsDomain
- entityType: RegistryValue
fieldMappings:
- identifier: Name
columnName: RegistryValueName
- identifier: Value
columnName: RegistryValueData
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
DeviceRegistryEvents
Stage 2: where
| where ((ActionType == "RegistryValueSet") and (RegistryKey startswith @"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions\\Paths"
or RegistryKey startswith @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Extensions"
or RegistryKey startswith @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Processes"))
Stage 3: extend
| extend HostName = iff(DeviceName has '.', substring(DeviceName, 0, indexof(DeviceName, '.')), DeviceName)
HostName =DeviceName has "."substring(DeviceName, 0, indexof(DeviceName, '.'))DeviceNameStage 4: extend
| extend DnsDomain = iff(DeviceName has '.', substring(DeviceName, indexof(DeviceName, '.') + 1), "")
DnsDomain =DeviceName has "."substring(DeviceName, (indexof(DeviceName, '.') + 1))""Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ActionType | eq |
| field:"EventType" kind:eq value:"RegistryValueSet" |
RegistryKey | starts_with |
| field:"TargetObject" kind:starts_with |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
HostName | extend |
DnsDomain | extend |
Multi-Factor Authentication for User Disabled
#Detects when multi-factor authentication is disabled for a specific user.
Rule Body
id: 3fefd6c5-bbe9-49a9-95b2-d4b8a5591d9c
name: Multi-Factor Authentication for User Disabled
description: Detects when multi-factor authentication is disabled for a specific user.
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 == 40204\n| project\n Date\
\ = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),\n DataSource = original_host,\n\
\ EventId = instanceId,\n UserName = 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 == 40204
Stage 3: project
| project
Date = format_datetime(TimeGenerated, 'dd.MM.yyyy HH:mm'),
DataSource = original_host,
EventId = instanceId,
UserName = 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:"40204" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DataSource | project |
Date | project |
EventId | project |
MessageDetails | project |
Severity | project |
UserName | project |
Power Platform - Connector added to a sensitive environment
#Identifies occurrences of new API connector creations within Power Platform, specifically targeting a predefined list of sensitive environments.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Exfiltration | |
| Execution |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft 365 | PutConnection |
Rule Body
id: 886a5655-3d12-42f1-8927-4095789c575e
kind: Scheduled
name: Power Platform - Connector added to a sensitive environment
description: Identifies occurrences of new API connector creations within Power Platform,
specifically targeting a predefined list of sensitive environments.
severity: Low
status: Available
requiredDataConnectors:
- connectorId: PowerPlatformAdmin
dataTypes:
- PowerPlatformAdminActivity
queryFrequency: 1h
queryPeriod: 7d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Execution
- Exfiltration
relevantTechniques:
- T0871
- T1567
- T1537
query: |
let sensitive_environment_id = dynamic([
// Specify the list of sensitive power platform environment ID's to monitor here.
// Example: "10e72012-8886-41ec-b973-250286419b38", "183c7056-7ed0-426f-8ae6-69819cf72259"
]);
let query_frequency = 11h;
PowerPlatformAdminActivity
| where TimeGenerated >= ago (query_frequency)
| where EventOriginalType == "PutConnection"
| extend Properties = tostring(PropertyCollection)
| extend SrcIpAddr = extract(@'"enduser.ip_address","Value":"([^"]+)"', 1, Properties)
| extend SrcIpAddr = iif(SrcIpAddr startswith '::ffff:', replace_string('::ffff:', '', SrcIpAddr), SrcIpAddr)
| extend
EnvironmentId = extract(@'"powerplatform.analytics.resource.environment.id","Value":"([^"]+)"', 1, Properties),
ConnectionId = extract(@'"powerplatform.analytics.resource.connection.id","Value":"([^"]+)"', 1, Properties)
| where EnvironmentId in~ (sensitive_environment_id)
| extend
AccountName = tostring(split(ActorName, "@")[0]),
UPNSuffix = tostring(split(ActorName, "@")[1])
| project
TimeGenerated,
EventOriginalType,
ActorName,
SrcIpAddr,
ConnectionId,
EnvironmentId,
AccountName,
UPNSuffix
eventGroupingSettings:
aggregationKind: SingleAlert
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
alertDetailsOverride:
alertDisplayNameFormat: New Power Platform connector added in a sensitive environment
alertDescriptionFormat: '{{ActorName}} added a new API connector in environment
id {{EnvironmentId}}. This environment has been listed as sensitive.'
customDetails:
Environment: EnvironmentId
Connection: ConnectionId
version: 3.2.0
Stages and Predicates
Parameters
let query_frequency = 11h;
Let Binding: sensitive_environment_id
let sensitive_environment_id = dynamic([
]);
Stage 1: source
PowerPlatformAdminActivity
Stage 2: where
| where TimeGenerated >= ago (query_frequency)
Stage 3: where
| where EventOriginalType == "PutConnection"
Stage 4: extend (4 consecutive steps)
| extend Properties = tostring(PropertyCollection)
| extend SrcIpAddr = extract(@'"enduser.ip_address","Value":"([^"]+)"', 1, Properties)
| extend SrcIpAddr = iif(SrcIpAddr startswith '::ffff:', replace_string('::ffff:', '', SrcIpAddr), SrcIpAddr)
| extend
EnvironmentId = extract(@'"powerplatform.analytics.resource.environment.id","Value":"([^"]+)"', 1, Properties),
ConnectionId = extract(@'"powerplatform.analytics.resource.connection.id","Value":"([^"]+)"', 1, Properties)
Stage 5: where
| where EnvironmentId in~ (sensitive_environment_id)
Stage 6: extend
| extend
AccountName = tostring(split(ActorName, "@")[0]),
UPNSuffix = tostring(split(ActorName, "@")[1])
Stage 7: project
| project
TimeGenerated,
EventOriginalType,
ActorName,
SrcIpAddr,
ConnectionId,
EnvironmentId,
AccountName,
UPNSuffix
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
EnvironmentId | in |
| field:"EnvironmentId" kind:in value:"[]" |
EventOriginalType | eq |
| field:"EventOriginalType" kind:eq value:"PutConnection" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountName | project |
ActorName | project |
ConnectionId | project |
EnvironmentId | project |
EventOriginalType | project |
SrcIpAddr | project |
TimeGenerated | project |
UPNSuffix | project |
Theom - Healthcare data unencrypted
#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.
"Creates Sentinel incidents for critical/high Theom risks, associated with ruleId TRIS0004 (Healthcare data has been observed in unencrypted data stores. Encrypt data at rest to comply with this CIS requirement)"
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Collection |
Rule Body
id: fb1b0deb-2a8f-4d8d-8d9d-0a8d327442e7
name: Theom - Healthcare data unencrypted
description: |
"Creates Sentinel incidents for critical/high Theom risks, associated with ruleId TRIS0004 (Healthcare data has been observed in unencrypted data stores. Encrypt data at rest to comply with this CIS requirement)"
severity: High
status : Available
requiredDataConnectors:
- connectorId: Theom
dataTypes:
- TheomAlerts_CL
queryPeriod: 5m
queryFrequency: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
- Collection
relevantTechniques:
- T1213
- T1530
query: |
TheomAlerts_CL
| where customProps_RuleId_s == "TRIS0004" and (priority_s == "P1" or priority_s == "P2")
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: "Theom Alert ID: {{id_s}} "
alertDescriptionFormat: "\nSummary: {{summary_s}} \nAdditional info: {{details_s}}\nPlease investigate further on Theom UI at {{deepLink_s}}\n"
entityMappings:
- entityType: CloudApplication
fieldMappings:
- identifier: Name
columnName: customProps_AssetName_s
- entityType: URL
fieldMappings:
- identifier: Url
columnName: deepLink_s
version: 1.0.2
kind: Scheduled
Stages and Predicates
Stage 1: source
TheomAlerts_CL
Stage 2: where
| where customProps_RuleId_s == "TRIS0004" and (priority_s == "P1" or priority_s == "P2")
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
customProps_RuleId_s | eq |
| field:"customProps_RuleId_s" kind:eq value:"TRIS0004" |
priority_s | eq |
| field:"priority_s" kind:eq |
Uniqkey - Credential export from newly created account
#Detects a data export performed by an employee whose Uniqkey account was created or activated within the preceding 14 days. A freshly provisioned account has little legitimate reason to export organization credentials, so this pattern can indicate a compromised onboarding flow or an account created specifically to stage exfiltration. The action filter matches the provisioning action identifiers from the Uniqkey audit-log catalog, with a name-based fallback for future action variants.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Credential Access |
Rule Body
id: 3939f01f-9563-4cd3-8423-97a82e82719b
name: Uniqkey - Credential export from newly created account
version: 1.0.0
kind: Scheduled
description: |-
Detects a data export performed by an employee whose Uniqkey account was created or activated within the preceding 14 days. A freshly provisioned account has little legitimate reason to export organization credentials, so this pattern can indicate a compromised onboarding flow or an account created specifically to stage exfiltration. The action filter matches the provisioning action identifiers from the Uniqkey audit-log catalog, with a name-based fallback for future action variants.
severity: Medium
requiredDataConnectors:
- connectorId: UniqkeyEventsConnector
dataTypes:
- UniqkeyEvents_CL
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
- CredentialAccess
- Persistence
relevantTechniques:
- T1555
- T1136
query: |-
let lookback = 14d;
let frequency = 1h;
let provisioningActionIds = dynamic([
"eb7dea42-df3a-44c6-808d-94b7fc46dde9", // Create employee account
"263c44a2-2075-46bd-949d-aa828517a3d1", // Link employee account
"4ed5b3be-d1b1-4447-af32-9ae2f1c090c7", // Activate employee
"e494db5c-b135-441c-8fa3-6e5ad94d05f8", // Activate employee account
"a652e6df-5a3c-438b-afde-198cd62e8491", // Activated account
"c7d4f9b2-5e3a-4f8c-9b6d-2e7a1c8d5f3b", // Activate SSO employee
"3cc88450-39ef-472e-9e0c-06ad7c9af257", // Process new employee
"c9ebd265-3c60-4228-b948-863c8134d29c", // Approve process new employee
"1b6c2121-00cc-40fe-9ea4-01f6dd085c34" // Approve process invite employee
]);
let newAccounts =
UniqkeyEvents_CL
| where TimeGenerated > ago(lookback)
| where Category == "account_management"
| where tolower(ActionId) in (provisioningActionIds) or Action has_any ("create", "invite", "activate", "link")
| where TargetType == "employee"
| project CreationTime = TimeGenerated, CreationAction = Action, NewEmployeeId = TargetId, NewEmployeeName = TargetName;
UniqkeyEvents_CL
| where TimeGenerated > ago(frequency)
| where Category == "data_export"
| join kind=inner newAccounts on $left.ActorId == $right.NewEmployeeId
| where TimeGenerated > CreationTime
| project TimeGenerated, ActorEmail, ActorType, Action, TargetType, TargetName, SrcIpAddr, CreationTime, CreationAction, NewEmployeeName
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: ActorEmail
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
suppressionEnabled: false
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 5h
matchingMethod: AllEntities
suppressionDuration: 5h
eventGroupingSettings:
aggregationKind: AlertPerResult
Stages and Predicates
Parameters
let lookback = 14d;
let frequency = 1h;
Let Binding: provisioningActionIds
let provisioningActionIds = dynamic([
"eb7dea42-df3a-44c6-808d-94b7fc46dde9",
"263c44a2-2075-46bd-949d-aa828517a3d1",
"4ed5b3be-d1b1-4447-af32-9ae2f1c090c7",
"e494db5c-b135-441c-8fa3-6e5ad94d05f8",
"a652e6df-5a3c-438b-afde-198cd62e8491",
"c7d4f9b2-5e3a-4f8c-9b6d-2e7a1c8d5f3b",
"3cc88450-39ef-472e-9e0c-06ad7c9af257",
"c9ebd265-3c60-4228-b948-863c8134d29c",
"1b6c2121-00cc-40fe-9ea4-01f6dd085c34"
]);
Let Binding: newAccounts
let newAccounts = UniqkeyEvents_CL
| where TimeGenerated > ago(lookback)
| where Category == "account_management"
| where tolower(ActionId) in (provisioningActionIds) or Action has_any ("create", "invite", "activate", "link")
| where TargetType == "employee"
| project CreationTime = TimeGenerated, CreationAction = Action, NewEmployeeId = TargetId, NewEmployeeName = TargetName;
Stage 1: source
UniqkeyEvents_CL
Stage 2: where
| where TimeGenerated > ago(frequency)
Stage 3: where
| where Category == "data_export"
Stage 4: join
| join kind=inner newAccounts on $left.ActorId == $right.NewEmployeeId
Stage 5: where
where TimeGenerated > CreationTime
Stage 6: project
project Action, ActorEmail, ActorType, CreationAction, CreationTime, NewEmployeeName, SrcIpAddr, TargetName, TargetType, TimeGenerated
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Action | match |
| field:"Action" kind:match |
ActionId | in |
| field:"ActionId" kind:in |
Category | eq |
| field:"Category" kind:eq |
TargetType | eq |
| field:"TargetType" kind:eq value:"employee" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Action | project |
ActorEmail | project |
ActorType | project |
CreationAction | project |
CreationTime | project |
NewEmployeeName | project |
SrcIpAddr | project |
TargetName | project |
TargetType | project |
TimeGenerated | project |