Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Cross-Cloud Suspicious user activity observed in GCP Envourment

Back
Id58e306fe-1c49-4b8f-9b0e-15f25e8f0cd7
RulenameCross-Cloud Suspicious user activity observed in GCP Envourment
DescriptionThis 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.
SeverityMedium
TacticsInitialAccess
Execution
Persistence
PrivilegeEscalation
CredentialAccess
Discovery
TechniquesT1566
T1059
T1078
T1046
T1547
T1548
T1069
T1552
Required data connectorsAzureActiveDirectoryIdentityProtection
GCPAuditLogsDefinition
MicrosoftCloudAppSecurity
MicrosoftDefenderAdvancedThreatProtection
MicrosoftThreatProtection
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Multi Cloud Attack Coverage Essentials - Resource Abuse/Analytic Rules/CrossCloudSuspiciousUserActivityObservedInGCPEnvourment.yaml
Version1.0.2
Arm template58e306fe-1c49-4b8f-9b0e-15f25e8f0cd7.json
Deploy To Azure
// 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"
    }
  ]
}