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

IP with multiple failed Microsoft Entra ID logins successfully logs in to Palo Alto VPN

Back
Idba144bf8-75b8-406f-9420-ed74397f9479
RulenameIP with multiple failed Microsoft Entra ID logins successfully logs in to Palo Alto VPN
DescriptionThis query creates a list of IP addresses with the number of failed login attempts to Entra ID

above a set threshold ( default of 5 ). It then looks for any successful Palo Alto VPN logins from any of these IPs within the same timeframe.
SeverityMedium
TacticsInitialAccess
CredentialAccess
TechniquesT1078
T1110
Required data connectorsAzureActiveDirectory
PaloAltoNetworks
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/AAD_PAVPN_Correlation.yaml
Version1.0.4
Arm templateba144bf8-75b8-406f-9420-ed74397f9479.json
Deploy To Azure
//Set a threshold of failed AAD signins from an IP address within 1 day above which we want to deem those logins suspicious.
let signin_threshold = 5; 
//Make a list of IPs with AAD signin failures above our threshold.
let aadFunc = (tableName:string){
let suspicious_signins = 
    table(tableName)
    //Looking for logon failure results
    | where ResultType !in ("0", "50125", "50140")
    //Exclude localhost addresses to reduce the chance of FPs
    | where IPAddress !in ("127.0.0.1", "::1")
    | summarize count() by IPAddress
    | where count_ >  signin_threshold
    | summarize make_set(IPAddress);
    suspicious_signins
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
let suspicious_signins = 
union isfuzzy=true aadSignin, aadNonInt
| summarize make_set(set_IPAddress);
//See if any of those IPs have sucessfully logged into PA VPNs during the same timeperiod
CommonSecurityLog
    //Select only PA VPN sucessful logons
    | where DeviceVendor == "Palo Alto Networks" and DeviceEventClassID == "globalprotect"
    | where Message has "GlobalProtect gateway user authentication succeeded"
    //Parse out the logon source IP from the Message field to match on
    | extend SourceIP = extract("Login from: ([^,]+)", 1, Message) 
    | where SourceIP in (suspicious_signins)
    | extend Reason = "Multiple failed AAD logins from SourceIP"
    //Parse out other useful information from Message field
    | extend User = extract('User name: ([^,]+)', 1, Message) 
    | extend ClientOS = extract('Client OS version: ([^,\"]+)', 1, Message)
    | extend Location = extract('Source region: ([^,]{2})',1, Message)
    | project TimeGenerated, Reason, SourceIP, User, ClientOS, Location, Message, DeviceName, ReceiptTime, DeviceVendor, DeviceEventClassID, Computer, FileName
    | extend timestamp = TimeGenerated
queryPeriod: 1d
id: ba144bf8-75b8-406f-9420-ed74397f9479
relevantTechniques:
- T1078
- T1110
triggerOperator: gt
entityMappings:
- fieldMappings:
  - columnName: User
    identifier: Name
  entityType: Account
- fieldMappings:
  - columnName: DeviceName
    identifier: HostName
  entityType: Host
- fieldMappings:
  - columnName: SourceIP
    identifier: Address
  entityType: IP
query: |
  //Set a threshold of failed AAD signins from an IP address within 1 day above which we want to deem those logins suspicious.
  let signin_threshold = 5; 
  //Make a list of IPs with AAD signin failures above our threshold.
  let aadFunc = (tableName:string){
  let suspicious_signins = 
      table(tableName)
      //Looking for logon failure results
      | where ResultType !in ("0", "50125", "50140")
      //Exclude localhost addresses to reduce the chance of FPs
      | where IPAddress !in ("127.0.0.1", "::1")
      | summarize count() by IPAddress
      | where count_ >  signin_threshold
      | summarize make_set(IPAddress);
      suspicious_signins
  };
  let aadSignin = aadFunc("SigninLogs");
  let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
  let suspicious_signins = 
  union isfuzzy=true aadSignin, aadNonInt
  | summarize make_set(set_IPAddress);
  //See if any of those IPs have sucessfully logged into PA VPNs during the same timeperiod
  CommonSecurityLog
      //Select only PA VPN sucessful logons
      | where DeviceVendor == "Palo Alto Networks" and DeviceEventClassID == "globalprotect"
      | where Message has "GlobalProtect gateway user authentication succeeded"
      //Parse out the logon source IP from the Message field to match on
      | extend SourceIP = extract("Login from: ([^,]+)", 1, Message) 
      | where SourceIP in (suspicious_signins)
      | extend Reason = "Multiple failed AAD logins from SourceIP"
      //Parse out other useful information from Message field
      | extend User = extract('User name: ([^,]+)', 1, Message) 
      | extend ClientOS = extract('Client OS version: ([^,\"]+)', 1, Message)
      | extend Location = extract('Source region: ([^,]{2})',1, Message)
      | project TimeGenerated, Reason, SourceIP, User, ClientOS, Location, Message, DeviceName, ReceiptTime, DeviceVendor, DeviceEventClassID, Computer, FileName
      | extend timestamp = TimeGenerated  
kind: Scheduled
triggerThreshold: 0
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/AAD_PAVPN_Correlation.yaml
queryFrequency: 1d
requiredDataConnectors:
- dataTypes:
  - SigninLogs
  connectorId: AzureActiveDirectory
- dataTypes:
  - AADNonInteractiveUserSignInLogs
  connectorId: AzureActiveDirectory
- dataTypes:
  - CommonSecurityLog
  connectorId: PaloAltoNetworks
metadata:
  support:
    tier: Community
  source:
    kind: Community
  categories:
    domains:
    - Security - Others
    - Identity
  author:
    name: Microsoft Security Research
name: IP with multiple failed Microsoft Entra ID logins successfully logs in to Palo Alto VPN
version: 1.0.4
description: |
  This query creates a list of IP addresses with the number of failed login attempts to Entra ID 
  above a set threshold ( default of 5 ).  It then looks for any successful Palo Alto VPN logins from any of these IPs within the same timeframe.  
tactics:
- InitialAccess
- CredentialAccess
severity: Medium
{
  "$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/ba144bf8-75b8-406f-9420-ed74397f9479')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/ba144bf8-75b8-406f-9420-ed74397f9479')]",
      "properties": {
        "alertRuleTemplateName": "ba144bf8-75b8-406f-9420-ed74397f9479",
        "customDetails": null,
        "description": "This query creates a list of IP addresses with the number of failed login attempts to Entra ID \nabove a set threshold ( default of 5 ).  It then looks for any successful Palo Alto VPN logins from any of these IPs within the same timeframe.\n",
        "displayName": "IP with multiple failed Microsoft Entra ID logins successfully logs in to Palo Alto VPN",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "User",
                "identifier": "Name"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "DeviceName",
                "identifier": "HostName"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SourceIP",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/AAD_PAVPN_Correlation.yaml",
        "query": "//Set a threshold of failed AAD signins from an IP address within 1 day above which we want to deem those logins suspicious.\nlet signin_threshold = 5; \n//Make a list of IPs with AAD signin failures above our threshold.\nlet aadFunc = (tableName:string){\nlet suspicious_signins = \n    table(tableName)\n    //Looking for logon failure results\n    | where ResultType !in (\"0\", \"50125\", \"50140\")\n    //Exclude localhost addresses to reduce the chance of FPs\n    | where IPAddress !in (\"127.0.0.1\", \"::1\")\n    | summarize count() by IPAddress\n    | where count_ >  signin_threshold\n    | summarize make_set(IPAddress);\n    suspicious_signins\n};\nlet aadSignin = aadFunc(\"SigninLogs\");\nlet aadNonInt = aadFunc(\"AADNonInteractiveUserSignInLogs\");\nlet suspicious_signins = \nunion isfuzzy=true aadSignin, aadNonInt\n| summarize make_set(set_IPAddress);\n//See if any of those IPs have sucessfully logged into PA VPNs during the same timeperiod\nCommonSecurityLog\n    //Select only PA VPN sucessful logons\n    | where DeviceVendor == \"Palo Alto Networks\" and DeviceEventClassID == \"globalprotect\"\n    | where Message has \"GlobalProtect gateway user authentication succeeded\"\n    //Parse out the logon source IP from the Message field to match on\n    | extend SourceIP = extract(\"Login from: ([^,]+)\", 1, Message) \n    | where SourceIP in (suspicious_signins)\n    | extend Reason = \"Multiple failed AAD logins from SourceIP\"\n    //Parse out other useful information from Message field\n    | extend User = extract('User name: ([^,]+)', 1, Message) \n    | extend ClientOS = extract('Client OS version: ([^,\\\"]+)', 1, Message)\n    | extend Location = extract('Source region: ([^,]{2})',1, Message)\n    | project TimeGenerated, Reason, SourceIP, User, ClientOS, Location, Message, DeviceName, ReceiptTime, DeviceVendor, DeviceEventClassID, Computer, FileName\n    | extend timestamp = TimeGenerated\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CredentialAccess",
          "InitialAccess"
        ],
        "techniques": [
          "T1078",
          "T1110"
        ],
        "templateVersion": "1.0.4",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}