Cross-Cloud Suspicious user activity observed in GCP Envourment
Id | 58e306fe-1c49-4b8f-9b0e-15f25e8f0cd7 |
Rulename | Cross-Cloud Suspicious user activity observed in GCP Envourment |
Description | This detection query aims to correlate potentially suspicious user activities logged in Google Cloud Platform (GCP) Audit Logs with security alerts originating from Microsoft Security products. This correlation facilitates the identification of potential cross-cloud security incidents. By summarizing these findings, the query provides valuable insights into cross-cloud identity threats and their associated details, enabling organizations to respond promptly and mitigate potential risks effectively. |
Severity | Medium |
Tactics | InitialAccess Execution Persistence PrivilegeEscalation CredentialAccess Discovery |
Techniques | T1566 T1059 T1078 T1046 T1547 T1548 T1069 T1552 |
Required data connectors | AzureActiveDirectoryIdentityProtection GCPAuditLogsDefinition MicrosoftCloudAppSecurity MicrosoftDefenderAdvancedThreatProtection MicrosoftThreatProtection |
Kind | Scheduled |
Query frequency | 1d |
Query period | 1d |
Trigger threshold | 0 |
Trigger operator | gt |
Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Multi Cloud Attack Coverage Essentials - Resource Abuse/Analytic Rules/CrossCloudSuspiciousUserActivityObservedInGCPEnvourment.yaml |
Version | 1.0.2 |
Arm template | 58e306fe-1c49-4b8f-9b0e-15f25e8f0cd7.json |
// Filter GCP Audit Logs to exclude service accounts
GCPAuditLogs
| where PrincipalEmail !endswith "gserviceaccount.com"
// Exclude system-related authentication information
| where AuthenticationInfo !has ("system:")
// Extract GCP request name and relevant attributes
| extend GCPRequestName= parse_json(Request).name
| extend
GCPAccoutType= tostring(split(GCPRequestName, "/")[2]),
GCPUserIdentity = iff(isempty(tostring(split(GCPRequestName, "/")[3])), tostring(parse_json(AuthenticationInfo).principalEmail), "na"),
GCPUserIp = tostring(parse_json(RequestMetadata).callerIp),
GCPCallerUA = tostring(parse_json(RequestMetadata).callerSuppliedUserAgent)
// Filter out empty or service account identities
| where isnotempty(GCPUserIdentity) and GCPUserIdentity !endswith "gserviceaccount.com"
// Select relevant attributes for further analysis
| project
PrincipalEmail,
GCPUserIdentity,
GCPAccoutType,
GCPRequestName,
GCPCallerUA,
Request,
RequestMetadata,
GCPUserIp,
MethodName,
ServiceName,
GCPEventTime= TimeGenerated,
ProjectId
// Join GCP Audit Logs with SecurityAlert data based on user identity and IP
| join kind=inner (
SecurityAlert
// Exclude alerts from Azure Sentinel
| where ProductName !in ("Azure Sentinel")
// Extract IP entities from alert data
| extend AlertIPEntity= tostring(extract(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", 0, Entities))
| extend
AlertUserUPN = tostring(extract(@'\b[\w\.\-]+@[\w\.\-]+\b', 0, Entities)),
AlertTime= TimeGenerated
// Filter out empty user identities and IP entities
| where isnotempty(AlertIPEntity) and isnotempty(AlertUserUPN)
)
on $left.GCPUserIdentity == $right.AlertUserUPN and $left.GCPUserIp == $right.AlertIPEntity
// Summarize the data, calculating time differences and aggregating attributes
| summarize
FirstAlert=min(AlertTime),
LastAlert=max(AlertTime),
TimeDiff=datetime_diff('minute', min(AlertTime), min(GCPEventTime)),
MethodName=make_set(MethodName),
ServiceName= make_set(ServiceName),
GCPProjctId=make_set(ProjectId),
Request=make_set(Request),
GCPCallerUA=make_set(GCPCallerUA)
by
AlertUserUPN,
AlertIPEntity,
GCPUserIp,
GCPUserIdentity,
AlertSeverity,
AlertName,
AlertLink,
Description,
Tactics,
ProductName,
SystemAlertId,
GCPAccoutType
// Extend the data with additional attributes
| extend
Name = tostring(split(GCPUserIdentity, "@")[0]),
UPNSuffix = tostring(split(GCPUserIdentity, "@")[1])
requiredDataConnectors:
- connectorId: GCPAuditLogsDefinition
dataTypes:
- GCPAuditLogs
- connectorId: AzureActiveDirectoryIdentityProtection
dataTypes:
- SecurityAlert (IPC)
- connectorId: MicrosoftThreatProtection
dataTypes:
- SecurityAlert
- connectorId: MicrosoftDefenderAdvancedThreatProtection
dataTypes:
- SecurityAlert (MDATP)
- connectorId: MicrosoftCloudAppSecurity
dataTypes:
- SecurityAlert
relevantTechniques:
- T1566
- T1059
- T1078
- T1046
- T1547
- T1548
- T1069
- T1552
queryFrequency: 1d
id: 58e306fe-1c49-4b8f-9b0e-15f25e8f0cd7
customDetails:
AlertUserUPN: AlertUserUPN
ServiceName: ServiceName
Request: Request
MethodName: MethodName
AlertName: AlertName
TimeDiff: TimeDiff
LastAlert: LastAlert
GCPCallerUA: GCPCallerUA
Tactics: Tactics
CorrelationWith: GCPAuditLogs
SystemAlertId: SystemAlertId
FirstAlert: FirstAlert
GCPProjctId: GCPProjctId
name: Cross-Cloud Suspicious user activity observed in GCP Envourment
severity: Medium
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Multi Cloud Attack Coverage Essentials - Resource Abuse/Analytic Rules/CrossCloudSuspiciousUserActivityObservedInGCPEnvourment.yaml
queryPeriod: 1d
entityMappings:
- fieldMappings:
- columnName: GCPUserIp
identifier: Address
entityType: IP
- fieldMappings:
- columnName: GCPUserIdentity
identifier: FullName
- columnName: Name
identifier: Name
- columnName: UPNSuffix
identifier: UPNSuffix
entityType: Account
description: |
'This detection query aims to correlate potentially suspicious user activities logged in Google Cloud Platform (GCP) Audit Logs with security alerts originating from Microsoft Security products. This correlation facilitates the identification of potential cross-cloud security incidents. By summarizing these findings, the query provides valuable insights into cross-cloud identity threats and their associated details, enabling organizations to respond promptly and mitigate potential risks effectively.'
triggerThreshold: 0
tactics:
- InitialAccess
- Execution
- Persistence
- PrivilegeEscalation
- CredentialAccess
- Discovery
query: |
// Filter GCP Audit Logs to exclude service accounts
GCPAuditLogs
| where PrincipalEmail !endswith "gserviceaccount.com"
// Exclude system-related authentication information
| where AuthenticationInfo !has ("system:")
// Extract GCP request name and relevant attributes
| extend GCPRequestName= parse_json(Request).name
| extend
GCPAccoutType= tostring(split(GCPRequestName, "/")[2]),
GCPUserIdentity = iff(isempty(tostring(split(GCPRequestName, "/")[3])), tostring(parse_json(AuthenticationInfo).principalEmail), "na"),
GCPUserIp = tostring(parse_json(RequestMetadata).callerIp),
GCPCallerUA = tostring(parse_json(RequestMetadata).callerSuppliedUserAgent)
// Filter out empty or service account identities
| where isnotempty(GCPUserIdentity) and GCPUserIdentity !endswith "gserviceaccount.com"
// Select relevant attributes for further analysis
| project
PrincipalEmail,
GCPUserIdentity,
GCPAccoutType,
GCPRequestName,
GCPCallerUA,
Request,
RequestMetadata,
GCPUserIp,
MethodName,
ServiceName,
GCPEventTime= TimeGenerated,
ProjectId
// Join GCP Audit Logs with SecurityAlert data based on user identity and IP
| join kind=inner (
SecurityAlert
// Exclude alerts from Azure Sentinel
| where ProductName !in ("Azure Sentinel")
// Extract IP entities from alert data
| extend AlertIPEntity= tostring(extract(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", 0, Entities))
| extend
AlertUserUPN = tostring(extract(@'\b[\w\.\-]+@[\w\.\-]+\b', 0, Entities)),
AlertTime= TimeGenerated
// Filter out empty user identities and IP entities
| where isnotempty(AlertIPEntity) and isnotempty(AlertUserUPN)
)
on $left.GCPUserIdentity == $right.AlertUserUPN and $left.GCPUserIp == $right.AlertIPEntity
// Summarize the data, calculating time differences and aggregating attributes
| summarize
FirstAlert=min(AlertTime),
LastAlert=max(AlertTime),
TimeDiff=datetime_diff('minute', min(AlertTime), min(GCPEventTime)),
MethodName=make_set(MethodName),
ServiceName= make_set(ServiceName),
GCPProjctId=make_set(ProjectId),
Request=make_set(Request),
GCPCallerUA=make_set(GCPCallerUA)
by
AlertUserUPN,
AlertIPEntity,
GCPUserIp,
GCPUserIdentity,
AlertSeverity,
AlertName,
AlertLink,
Description,
Tactics,
ProductName,
SystemAlertId,
GCPAccoutType
// Extend the data with additional attributes
| extend
Name = tostring(split(GCPUserIdentity, "@")[0]),
UPNSuffix = tostring(split(GCPUserIdentity, "@")[1])
kind: Scheduled
triggerOperator: gt
alertDetailsOverride:
alertDynamicProperties:
- alertProperty: AlertLink
value: AlertLink
- alertProperty: ProviderName
value: ProductName
- alertProperty: ProductComponentName
value: Microsoft Security
alertDisplayNameFormat: A user {{GCPUserUPN}} has been linked to {{AlertName}}, and has potentially suspicious behavior within the GCP environment from, originating from the IP address {{GCPUserIp}}.
alertDescriptionFormat: |2-
This detection compiles and correlates unauthorized user access alerts originating from {{ProductName}} With Alert Description '{{Description}}' observed activity in GCP environmeny. It focuses on Microsoft Security, specifically targeting user bhaviour and network IP associations tied to activities such as logins from malicious IP addresses or instance credential exfiltration attempts. The detection leverages these common network IP advisories to detect and pinpoint users suspicious activity to access both Azure and GCP resources.
Microsoft Security ALert Link : '{{AlertLink}}'
alertSeverityColumnName: AlertSeverity
version: 1.0.2
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/58e306fe-1c49-4b8f-9b0e-15f25e8f0cd7')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/58e306fe-1c49-4b8f-9b0e-15f25e8f0cd7')]",
"properties": {
"alertDetailsOverride": {
"alertDescriptionFormat": " This detection compiles and correlates unauthorized user access alerts originating from {{ProductName}} With Alert Description '{{Description}}' observed activity in GCP environmeny. It focuses on Microsoft Security, specifically targeting user bhaviour and network IP associations tied to activities such as logins from malicious IP addresses or instance credential exfiltration attempts. The detection leverages these common network IP advisories to detect and pinpoint users suspicious activity to access both Azure and GCP resources. \n\n Microsoft Security ALert Link : '{{AlertLink}}'",
"alertDisplayNameFormat": "A user {{GCPUserUPN}} has been linked to {{AlertName}}, and has potentially suspicious behavior within the GCP environment from, originating from the IP address {{GCPUserIp}}.",
"alertDynamicProperties": [
{
"alertProperty": "AlertLink",
"value": "AlertLink"
},
{
"alertProperty": "ProviderName",
"value": "ProductName"
},
{
"alertProperty": "ProductComponentName",
"value": "Microsoft Security"
}
],
"alertSeverityColumnName": "AlertSeverity"
},
"alertRuleTemplateName": "58e306fe-1c49-4b8f-9b0e-15f25e8f0cd7",
"customDetails": {
"AlertName": "AlertName",
"AlertUserUPN": "AlertUserUPN",
"CorrelationWith": "GCPAuditLogs",
"FirstAlert": "FirstAlert",
"GCPCallerUA": "GCPCallerUA",
"GCPProjctId": "GCPProjctId",
"LastAlert": "LastAlert",
"MethodName": "MethodName",
"Request": "Request",
"ServiceName": "ServiceName",
"SystemAlertId": "SystemAlertId",
"Tactics": "Tactics",
"TimeDiff": "TimeDiff"
},
"description": "'This detection query aims to correlate potentially suspicious user activities logged in Google Cloud Platform (GCP) Audit Logs with security alerts originating from Microsoft Security products. This correlation facilitates the identification of potential cross-cloud security incidents. By summarizing these findings, the query provides valuable insights into cross-cloud identity threats and their associated details, enabling organizations to respond promptly and mitigate potential risks effectively.'\n",
"displayName": "Cross-Cloud Suspicious user activity observed in GCP Envourment",
"enabled": true,
"entityMappings": [
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "GCPUserIp",
"identifier": "Address"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "GCPUserIdentity",
"identifier": "FullName"
},
{
"columnName": "Name",
"identifier": "Name"
},
{
"columnName": "UPNSuffix",
"identifier": "UPNSuffix"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Multi Cloud Attack Coverage Essentials - Resource Abuse/Analytic Rules/CrossCloudSuspiciousUserActivityObservedInGCPEnvourment.yaml",
"query": "// Filter GCP Audit Logs to exclude service accounts\nGCPAuditLogs \n| where PrincipalEmail !endswith \"gserviceaccount.com\"\n// Exclude system-related authentication information\n| where AuthenticationInfo !has (\"system:\")\n// Extract GCP request name and relevant attributes\n| extend GCPRequestName= parse_json(Request).name\n| extend\n GCPAccoutType= tostring(split(GCPRequestName, \"/\")[2]),\n GCPUserIdentity = iff(isempty(tostring(split(GCPRequestName, \"/\")[3])), tostring(parse_json(AuthenticationInfo).principalEmail), \"na\"), \n GCPUserIp = tostring(parse_json(RequestMetadata).callerIp),\n GCPCallerUA = tostring(parse_json(RequestMetadata).callerSuppliedUserAgent)\n// Filter out empty or service account identities\n| where isnotempty(GCPUserIdentity) and GCPUserIdentity !endswith \"gserviceaccount.com\"\n// Select relevant attributes for further analysis\n| project\n PrincipalEmail,\n GCPUserIdentity,\n GCPAccoutType,\n GCPRequestName,\n GCPCallerUA,\n Request,\n RequestMetadata,\n GCPUserIp,\n MethodName,\n ServiceName,\n GCPEventTime= TimeGenerated,\n ProjectId\n// Join GCP Audit Logs with SecurityAlert data based on user identity and IP\n| join kind=inner ( \n SecurityAlert \n // Exclude alerts from Azure Sentinel\n | where ProductName !in (\"Azure Sentinel\")\n // Extract IP entities from alert data\n | extend AlertIPEntity= tostring(extract(@\"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\", 0, Entities))\n | extend\n AlertUserUPN = tostring(extract(@'\\b[\\w\\.\\-]+@[\\w\\.\\-]+\\b', 0, Entities)),\n AlertTime= TimeGenerated\n // Filter out empty user identities and IP entities\n | where isnotempty(AlertIPEntity) and isnotempty(AlertUserUPN)\n )\n on $left.GCPUserIdentity == $right.AlertUserUPN and $left.GCPUserIp == $right.AlertIPEntity\n// Summarize the data, calculating time differences and aggregating attributes\n| summarize\n FirstAlert=min(AlertTime),\n LastAlert=max(AlertTime),\n TimeDiff=datetime_diff('minute', min(AlertTime), min(GCPEventTime)),\n MethodName=make_set(MethodName),\n ServiceName= make_set(ServiceName),\n GCPProjctId=make_set(ProjectId),\n Request=make_set(Request),\n GCPCallerUA=make_set(GCPCallerUA)\n by\n AlertUserUPN,\n AlertIPEntity,\n GCPUserIp,\n GCPUserIdentity,\n AlertSeverity,\n AlertName,\n AlertLink,\n Description,\n Tactics,\n ProductName,\n SystemAlertId,\n GCPAccoutType\n// Extend the data with additional attributes\n| extend\n Name = tostring(split(GCPUserIdentity, \"@\")[0]),\n UPNSuffix = tostring(split(GCPUserIdentity, \"@\")[1])\n",
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"severity": "Medium",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"CredentialAccess",
"Discovery",
"Execution",
"InitialAccess",
"Persistence",
"PrivilegeEscalation"
],
"techniques": [
"T1046",
"T1059",
"T1069",
"T1078",
"T1547",
"T1548",
"T1552",
"T1566"
],
"templateVersion": "1.0.2",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}