Detection rules › Kusto
Kusto rules: 14
Changes to Application Ownership
#Detects changes to the ownership of an appplicaiton. Monitor these changes to make sure that they were authorized. Ref: https://learn.microsoft.com/en-gb/entra/architecture/security-operations-applications#new-owner
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence | |
| Privilege Escalation |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Azure | Add owner to application |
Rules Detecting the Same Action
These rules filter on the same operation.
- [Entra ID] Application Assigned Administrator Permissions Immediately After Obtaining Role Management Permissions (Kusto)
- [Entra ID] Application Granted Administrative Permission to Assign Microsoft Entra ID Roles (Kusto)
- Added Credentials to Existing Application (Sigma)
- Added Owner To Application (Sigma)
- Admin promotion after Role Management Application Permission Grant (Kusto)
- App Granted Microsoft Permissions (Sigma)
- App Granted Privileged Delegated Or App Permissions (Sigma)
- Application AppID Uri Configuration Changes (Sigma)
Rule Body
id: cc5780ce-3245-4bba-8bc1-e9048c2257ce
name: Changes to Application Ownership
description: |
'Detects changes to the ownership of an appplicaiton.
Monitor these changes to make sure that they were authorized.
Ref: https://learn.microsoft.com/en-gb/entra/architecture/security-operations-applications#new-owner'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
queryFrequency: 2h
queryPeriod: 2h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Persistence
- PrivilegeEscalation
relevantTechniques:
- T1078.004
tags:
- AADSecOpsGuide
query: |
AuditLogs
| where Category =~ "ApplicationManagement"
| where OperationName =~ "Add owner to application"
| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIPAddress = tostring(InitiatedBy.user.ipAddress)
| extend TargetUserPrincipalName = TargetResources[0].userPrincipalName
| extend TargetAadUserId = tostring(TargetResources[0].id)
| extend mod_props = TargetResources[0].modifiedProperties
| mv-expand mod_props
| where mod_props.displayName =~ "Application.DisplayName"
| extend TargetAppName = tostring(parse_json(tostring(mod_props.newValue)))
| extend AddedUser = TargetUserPrincipalName
| extend UpdatedBy = iif(isnotempty(InitiatingAppName), InitiatingAppName, InitiatingUserPrincipalName)
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
| extend TargetAccountName = tostring(split(TargetUserPrincipalName, "@")[0]), TargetAccountUPNSuffix = tostring(split(TargetUserPrincipalName, "@")[1])
| project-reorder TimeGenerated, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingAadUserId, InitiatingUserPrincipalName, InitiatingIPAddress, TargetAppName, AddedUser, UpdatedBy
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: InitiatingUserPrincipalName
- identifier: Name
columnName: InitiatingAccountName
- identifier: UPNSuffix
columnName: InitiatingAccountUPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: InitiatingAadUserId
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: TargetUserPrincipalName
- identifier: Name
columnName: TargetAccountName
- identifier: UPNSuffix
columnName: TargetAccountUPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: TargetAadUserId
version: 1.1.2
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
support:
tier: Community
categories:
domains: [ "Security - Others" ]
Stages and Predicates
Stage 1: source
AuditLogs
Stage 2: where
| where Category =~ "ApplicationManagement"
Stage 3: where
| where OperationName =~ "Add owner to application"
Stage 4: extend (8 consecutive steps)
| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIPAddress = tostring(InitiatedBy.user.ipAddress)
| extend TargetUserPrincipalName = TargetResources[0].userPrincipalName
| extend TargetAadUserId = tostring(TargetResources[0].id)
| extend mod_props = TargetResources[0].modifiedProperties
Stage 5: mv-expand
| mv-expand mod_props
Stage 6: where
| where mod_props.displayName =~ "Application.DisplayName"
Stage 7: extend (5 consecutive steps)
| extend TargetAppName = tostring(parse_json(tostring(mod_props.newValue)))
| extend AddedUser = TargetUserPrincipalName
| extend UpdatedBy = iif(isnotempty(InitiatingAppName), InitiatingAppName, InitiatingUserPrincipalName)
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
| extend TargetAccountName = tostring(split(TargetUserPrincipalName, "@")[0]), TargetAccountUPNSuffix = tostring(split(TargetUserPrincipalName, "@")[1])
Stage 8: project-reorder
| project-reorder TimeGenerated, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingAadUserId, InitiatingUserPrincipalName, InitiatingIPAddress, TargetAppName, AddedUser, UpdatedBy
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Category | eq |
| field:"Category" kind:eq value:"ApplicationManagement" |
OperationName | eq |
| field:"OperationName" kind:eq value:"Add owner to application" |
mod_props.displayName | eq |
| field:"mod_props.displayName" kind:eq value:"Application.DisplayName" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
InitiatingAppName | extend |
InitiatingAppServicePrincipalId | extend |
InitiatingUserPrincipalName | extend |
InitiatingAadUserId | extend |
InitiatingIPAddress | extend |
TargetUserPrincipalName | extend |
TargetAadUserId | extend |
mod_props | extend |
TargetAppName | extend |
AddedUser | extend |
UpdatedBy | extend |
InitiatingAccountName | extend |
InitiatingAccountUPNSuffix | extend |
TargetAccountName | extend |
TargetAccountUPNSuffix | extend |
ContraForce - Destructive workspace action
#'Identifies destructive actions against the ContraForce workspace or its account: workspace deletion, account deactivation, and account purge. These actions terminate or remove the security service delivery for the affected workspace and should always correspond to a planned offboarding; anything else warrants immediate investigation.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Rule Body
id: c5e9a1d7-4b2f-4e6c-8a9d-7f3b1c5e2a84
name: ContraForce - Destructive workspace action
description: |
'Identifies destructive actions against the ContraForce workspace or its account: workspace
deletion, account deactivation, and account purge. These actions terminate or remove the
security service delivery for the affected workspace and should always correspond to a
planned offboarding; anything else warrants immediate investigation.'
severity: High
requiredDataConnectors:
- connectorId: ContraForceEvents
dataTypes:
- ContraForceEvents_CL
queryFrequency: 5m
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- Impact
relevantTechniques:
- T1485
- T1531
query: |
ContraForceEvents_CL
| where ingestion_time() > ago(5m)
| where ActivityType in ("WorkspaceDeleted", "AccountDeactivated", "AccountPurged")
| extend Meta = parse_json(Metadata)
| project TimeGenerated, EventId, CfWorkspaceId, ActivityType, ActivityAction,
ActorName, ActorEmail, TargetResourceType, TargetResourceId, TargetResourceName, Metadata
eventGroupingSettings:
aggregationKind: AlertPerResult
alertDetailsOverride:
alertDisplayNameFormat: 'ContraForce destructive action: {{ActivityType}} on {{TargetResourceName}}'
alertDescriptionFormat: '{{ActorName}} performed {{ActivityType}} on {{TargetResourceName}}.'
customDetails:
EventId: EventId
ActorEmail: ActorEmail
TargetResourceId: TargetResourceId
CfWorkspaceId: CfWorkspaceId
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: PT2H
matchingMethod: Selected
groupByCustomDetails:
- EventId
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
ContraForceEvents_CL
Stage 2: where
| where ingestion_time() > ago(5m)
Stage 3: where
| where ActivityType in ("WorkspaceDeleted", "AccountDeactivated", "AccountPurged")
Stage 4: extend
| extend Meta = parse_json(Metadata)
Stage 5: project
| project TimeGenerated, EventId, CfWorkspaceId, ActivityType, ActivityAction,
ActorName, ActorEmail, TargetResourceType, TargetResourceId, TargetResourceName, Metadata
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ActivityType | in |
| field:"ActivityType" kind:in |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
ActivityAction | project |
ActivityType | project |
ActorEmail | project |
ActorName | project |
CfWorkspaceId | project |
EventId | project |
Metadata | project |
TargetResourceId | project |
TargetResourceName | project |
TargetResourceType | project |
TimeGenerated | project |
Cyble Vision Alerts Darkweb Data Breaches
#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 darkweb credential leakage and data breach records from CybleVision. Extracts leaked username, email, password hashes, registration dates, and metadata using the Alerts_DarkwebDataBreaches parser. Incidents grouped per service.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Reconnaissance | |
| Initial Access | |
| Collection | |
| Exfiltration |
Rule Body
id: 588a2ee5-978a-43f7-9c10-6d76d82026ef
name: "Cyble Vision Alerts Darkweb Data Breaches"
description: |
'Detects darkweb credential leakage and data breach records from CybleVision. Extracts leaked username, email, password hashes, registration dates, and metadata using the Alerts_DarkwebDataBreaches parser. Incidents grouped per service.'
severity: Low
status: Available
requiredDataConnectors:
- connectorId: CybleVisionAlerts
dataTypes:
- CybleVisionAlerts_CL
enabled: true
queryFrequency: 30m
queryPeriod: 30m
triggerOperator: GreaterThan
triggerThreshold: 0
suppressionDuration: PT5H
eventGroupingSettings:
aggregationKind: AlertPerResult
tactics:
- Reconnaissance
- InitialAccess
- Exfiltration
- Collection
relevantTechniques:
- T1589
- T1078
- T1048
- T1530
subTechniques: []
query: |
Alerts_darkweb_data_breaches
| where Service == "darkweb_data_breaches"
| extend MappedSeverity = Severity
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
alertDetailsOverride:
alertDisplayNameFormat: CybleVision Darkweb Breach for {{DB_Email}}
alertDescriptionFormat: |
Username {{DB_Username}} Registration date {{DB_RegistrationDate}} Breach source {{Breach_Source}}
alertDynamicProperties: []
customDetails:
MappedSeverity: Severity
Status: Status
AlertID: AlertID
Service: Service
LeakedEmail: DB_Email
UserName: DB_Username
PasswordHash: DB_PasswordHash
DisplayName: DB_DisplayName
RegistrationDate: DB_RegistrationDate
BreachDate: DB_Date
BreachSource: Breach_Source
S3Key: DB_S3Key
Structured: DB_Structured
Tags: DB_Tags
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: DB_Username
- entityType: DNS
fieldMappings:
- identifier: DomainName
columnName: Domain
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IP
- entityType: Mailbox
fieldMappings:
- identifier: MailboxPrimaryAddress
columnName: DB_Email
version: 1.0.0
kind: Scheduled
Stages and Predicates
Stage 1: source
Alerts_darkweb_data_breaches
Stage 2: where
| where Service == "darkweb_data_breaches"
Stage 3: extend
| extend MappedSeverity = Severity
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Service | eq |
| field:"Service" kind:eq value:"darkweb_data_breaches" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
MappedSeverity | extend |
Cyble Vision Alerts Github
#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 alert generates incidents for Github'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access | |
| Collection |
Rule Body
id: 117e8f7c-8f44-4061-bcc2-b444b98a3838
name: Cyble Vision Alerts Github
description: |
'This alert generates incidents for Github'
severity: Low
status: Available
requiredDataConnectors:
- connectorId: CybleVisionAlerts
dataTypes:
- CybleVisionAlerts_CL
enabled: true
queryFrequency: 30m
queryPeriod: 30m
triggerOperator: GreaterThan
triggerThreshold: 0
suppressionDuration: PT5H
eventGroupingSettings:
aggregationKind: AlertPerResult
tactics:
- Collection
- CredentialAccess
relevantTechniques:
- T1213
- T1530
- T1552
subTechniques: []
query: |
Alerts_github
| where Service contains "github"
| extend MappedSeverity = Severity
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: false
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
alertDetailsOverride:
alertDisplayNameFormat: Cyble Vision Alert for Github
alertDescriptionFormat: This Rule generate incidents for Serviec Github
alertDynamicProperties: []
customDetails:
MappedSeverity: Severity
Status: Status
AlertID: AlertID
Service: Service
GitURl: git_url
URL: html_url
Repository: repo_full_name
FileName: file_name
Owner: owner_login
SHA: sha
Score: score
OriginalSeverity: Severity
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: owner_login
- entityType: URL
fieldMappings:
- identifier: Url
columnName: html_url
- entityType: File
fieldMappings:
- identifier: Name
columnName: file_name
- identifier: Directory
columnName: file_path
version: 1.0.1
kind: Scheduled
Stages and Predicates
Stage 1: source
Alerts_github
Stage 2: where
| where Service contains "github"
Stage 3: extend
| extend MappedSeverity = Severity
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
Service | contains |
| field:"Service" kind:contains value:"github" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
MappedSeverity | extend |
Denial of Service (Microsoft Defender for IoT)
#'This alert leverages Defender for IoT to detect attacks that would prevent the use or proper operation of a DCS system including Denial of Service events.'
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Inhibit Response Function |
Rule Body
id: e068187a-01f5-4737-bc13-25db4027b7ea
name: Denial of Service (Microsoft Defender for IoT)
description: |
'This alert leverages Defender for IoT to detect attacks that would prevent the use or proper operation of a DCS system including Denial of Service events.'
severity: High
status: Available
requiredDataConnectors:
- connectorId: IoT
dataTypes:
- SecurityAlert (ASC for IoT)
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
tactics:
- InhibitResponseFunction
relevantTechniques:
- T0814
query: |
SecurityAlert
| where ProviderName == "IoTSecurity"
| where AlertName == "Suspicion of Denial Of Service Attack"
| extend ExtendedProperties = parse_json(ExtendedProperties)
| where tostring(ExtendedProperties.isNew) == "True"
| extend DeviceId = tostring(ExtendedProperties.DeviceId),
SourceDeviceAddress = tostring(ExtendedProperties.SourceDeviceAddress),
DestDeviceAddress = tostring(ExtendedProperties.DestinationDeviceAddress),
RemediationSteps = tostring(parse_json(RemediationSteps)[0]),
Protocol = tostring(ExtendedProperties.Protocol),
AlertManagementUri = tostring(ExtendedProperties.AlertManagementUri)
| project
TimeGenerated,
DeviceId,
ProductName,
ProductComponentName,
AlertSeverity,
AlertName,
Description,
Protocol,
SourceDeviceAddress,
DestDeviceAddress,
RemediationSteps,
Tactics,
Entities,
VendorOriginalId,
AlertLink,
AlertManagementUri,
Techniques
entityMappings:
sentinelEntitiesMappings:
- columnName: Entities
eventGroupingSettings:
aggregationKind: AlertPerResult
customDetails:
Sensor: DeviceId
Protocol: Protocol
VendorOriginalId: VendorOriginalId
AlertManagementUri: AlertManagementUri
alertDetailsOverride:
alertDisplayNameFormat: (MDIoT) {{AlertName}}
alertDescriptionFormat: (MDIoT) {{Description}}
alertTacticsColumnName: Tactics
alertSeverityColumnName: AlertSeverity
alertDynamicProperties:
- alertProperty: ProductName
value: ProductName
- alertProperty: RemediationSteps
value: RemediationSteps
- alertProperty: Techniques
value: Techniques
- alertProperty: ProductComponentName
value: ProductComponentName
- alertProperty: AlertLink
value: AlertLink
version: 1.0.3
kind: Scheduled
Stages and Predicates
Stage 1: source
SecurityAlert
Stage 2: where
| where ProviderName == "IoTSecurity"
Stage 3: where
| where AlertName == "Suspicion of Denial Of Service Attack"
Stage 4: extend
| extend ExtendedProperties = parse_json(ExtendedProperties)
Stage 5: where
| where tostring(ExtendedProperties.isNew) == "True"
Stage 6: extend
| extend DeviceId = tostring(ExtendedProperties.DeviceId),
SourceDeviceAddress = tostring(ExtendedProperties.SourceDeviceAddress),
DestDeviceAddress = tostring(ExtendedProperties.DestinationDeviceAddress),
RemediationSteps = tostring(parse_json(RemediationSteps)[0]),
Protocol = tostring(ExtendedProperties.Protocol),
AlertManagementUri = tostring(ExtendedProperties.AlertManagementUri)
Stage 7: project
| project
TimeGenerated,
DeviceId,
ProductName,
ProductComponentName,
AlertSeverity,
AlertName,
Description,
Protocol,
SourceDeviceAddress,
DestDeviceAddress,
RemediationSteps,
Tactics,
Entities,
VendorOriginalId,
AlertLink,
AlertManagementUri,
Techniques
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
AlertName | eq |
| field:"AlertName" kind:eq value:"Suspicion of Denial Of Service Attack" |
ExtendedProperties.isNew | eq |
| field:"ExtendedProperties.isNew" kind:eq value:"True" |
ProviderName | eq |
| field:"ProviderName" kind:eq value:"IoTSecurity" |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AlertLink | project |
AlertManagementUri | project |
AlertName | project |
AlertSeverity | project |
Description | project |
DestDeviceAddress | project |
DeviceId | project |
Entities | project |
ProductComponentName | project |
ProductName | project |
Protocol | project |
RemediationSteps | project |
SourceDeviceAddress | project |
Tactics | project |
Techniques | project |
TimeGenerated | project |
VendorOriginalId | project |
Exchange Worker Process Making Remote Call
#This query dynamically identifies Exchange servers and then looks for instances where the IIS worker process initiates a call out to a remote URL using either cmd.exe or powershell.exe. This behaviour was described as post-compromise behaviour following exploitation of CVE-2022-41040 and CVE-2022-41082, this pattern of activity was use to download additional tools to the server. This suspicious activity is generic.
MITRE ATT&CK Coverage
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Microsoft Defender for Endpoint | DeviceProcessEvents action any: Process activity |
Rule Body
id: 2c701f94-783c-4cd4-bc9b-3b3334976090
name: Exchange Worker Process Making Remote Call
description: |
'This query dynamically identifies Exchange servers and then looks for instances where the IIS worker process initiates a call out to a remote URL using either cmd.exe or powershell.exe.
This behaviour was described as post-compromise behaviour following exploitation of CVE-2022-41040 and CVE-2022-41082, this pattern of activity was use to download additional tools to the server. This suspicious activity is generic.'
severity: Medium
requiredDataConnectors:
- connectorId: AzureMonitor(IIS)
dataTypes:
- W3CIISLog
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceProcessEvents
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Execution
relevantTechniques:
- T1059.001
- T1059.003
query: |
let suspiciousCmdLineKeywords = dynamic(["http://", "https://"]);
// Identify exchange servers based on known paths
// Summarize these to get a list of exchange server hostnames
let exchangeServers = W3CIISLog
| where csUriStem has_any("/owa/","/ews/","/ecp/","/autodiscover/")
// Only where successful, rule out failed scanning
| where scStatus startswith "2"
| summarize by Computer;
DeviceProcessEvents
| where DeviceName in~ (exchangeServers)
// Where the IIS worker process initiated CMD or PowerShell
| where InitiatingProcessParentFileName == "w3wp.exe"
| where InitiatingProcessFileName has_any("cmd.exe", "powershell.exe")
// Where CMD or PowerShell command line included parameters associated with CVE-2022-41040/CVE-2022-41082 exploitation
| where ProcessCommandLine has_any(suspiciousCmdLineKeywords)
| project TimeGenerated, DeviceId, DeviceName, InitiatingProcessFileName, ProcessCommandLine, AccountDomain = InitiatingProcessAccountDomain, AccountName = InitiatingProcessAccountName
| extend Account = strcat(AccountDomain, "\\", AccountName)
| 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: Account
- identifier: Name
columnName: AccountName
- identifier: NTDomain
columnName: AccountDomain
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: DeviceName
- identifier: HostName
columnName: HostName
- identifier: NTDomain
columnName: HostNameDomain
version: 1.1.2
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Community
support:
tier: Community
categories:
domains: [ "Application" ]
Stages and Predicates
Parameters
let suspiciousCmdLineKeywords = dynamic(["http://", "https://"]);
Let Binding: exchangeServers
let exchangeServers = W3CIISLog
| where csUriStem has_any("/owa/","/ews/","/ecp/","/autodiscover/")
| where scStatus startswith "2"
| summarize by Computer;
Stage 1: source
DeviceProcessEvents
Stage 2: where
| where DeviceName in~ (exchangeServers)
Stage 3: where
| where InitiatingProcessParentFileName == "w3wp.exe"
Stage 4: where
| where InitiatingProcessFileName has_any("cmd.exe", "powershell.exe")
Stage 5: where
| where ProcessCommandLine has_any(suspiciousCmdLineKeywords)
Stage 6: project
| project TimeGenerated, DeviceId, DeviceName, InitiatingProcessFileName, ProcessCommandLine, AccountDomain = InitiatingProcessAccountDomain, AccountName = InitiatingProcessAccountName
Stage 7: extend (3 consecutive steps)
| extend Account = strcat(AccountDomain, "\\", AccountName)
| extend HostName = tostring(split(DeviceName, ".")[0]), DomainIndex = toint(indexof(DeviceName, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(DeviceName, DomainIndex + 1), DeviceName)
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
DeviceName | in |
| field:"Computer" kind:in value:"exchangeServers" |
InitiatingProcessFileName | match |
| field:"parent_process_basename" kind:match |
InitiatingProcessParentFileName | eq |
| field:"grandparent_process_basename" kind:eq value:"w3wp.exe" |
ProcessCommandLine | match |
| field:"CommandLine" kind:match |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
AccountDomain | project |
AccountName | project |
DeviceId | project |
DeviceName | project |
InitiatingProcessFileName | project |
ProcessCommandLine | project |
TimeGenerated | project |
Account | extend |
DomainIndex | extend |
HostName | extend |
HostNameDomain | extend |
SSG_Security_Incidents
#The security analytic rule is designed to scrutinize network activity involving private IP addresses within an organization's internal network. By filtering log entries to include only those where either the source or the destination IP is private, the rule focuses on internal communications that could indicate unauthorized access, internal threats, or other security anomalies.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Impact |
Rule Body
id: d41fa731-45a2-4b23-bb1d-29896fbc5298
name: SSG_Security_Incidents
version: 1.0.0
kind: NRT
description: The security analytic rule is designed to scrutinize network activity involving private IP addresses within an organization's internal network. By filtering log entries to include only those where either the source or the destination IP is private, the rule focuses on internal communications that could indicate unauthorized access, internal threats, or other security anomalies.
severity: HIGH
tactics:
- Impact
relevantTechniques:
- T1486
query: |
SINECSecurityGuard_CL
| where ipv4_is_private(source_ip) or ipv4_is_private(destination_ip)
| project source_ip, destination_ip, signature_id, signature_name
suppressionEnabled: false
eventGroupingSettings:
aggregationKind: AlertPerResult
suppressionDuration: 5h
alertDetailsOverride:
alertDisplayNameFormat: '{{signature_name}} '
alertDescriptionFormat: 'Alert {{signature_name}} generated from {{source_ip}} to {{destination_ip}} '
alertDynamicProperties: []
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 5m
matchingMethod: AnyAlert
groupByEntities:
- IP
groupByAlertDetails: []
groupByCustomDetails:
- Source_IP
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: source_ip
- entityType: IP
fieldMappings:
- identifier: Address
columnName: destination_ip
customDetails:
Source_IP: source_ip
Stages and Predicates
Stage 1: source
SINECSecurityGuard_CL
Stage 2: where
| where ipv4_is_private(source_ip) or ipv4_is_private(destination_ip)
Stage 3: project
| project source_ip, destination_ip, signature_id, signature_name
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
destination_ip | cidr_match |
| field:"destination_ip" kind:cidr_match |
source_ip | cidr_match |
| field:"src_ip" kind:cidr_match |
Output Fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
destination_ip | project |
signature_id | project |
signature_name | project |
source_ip | project |