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

Successful logon from IP and failure from a different IP

Back
Id02ef8d7e-fc3a-4d86-a457-650fa571d8d2
RulenameSuccessful logon from IP and failure from a different IP
DescriptionIdentifies when a user account successfully logs onto an Azure App from one IP and within 10 mins failed to logon to the same App via a different IP.

This may indicate a malicious attempt at password guessing based on knowledge of the users account.
SeverityMedium
TacticsCredentialAccess
InitialAccess
TechniquesT1110
T1078
Required data connectorsAzureActiveDirectory
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Azure Active Directory/Analytic Rules/SuccessThenFail_DiffIP_SameUserandApp.yaml
Version1.1.1
Arm template02ef8d7e-fc3a-4d86-a457-650fa571d8d2.json
Deploy To Azure
let logonDiff = 10m;
let aadFunc = (tableName:string){
table(tableName)
| where ResultType == "0"
| where AppDisplayName !in ("Office 365 Exchange Online", "Skype for Business Online")
| project SuccessLogonTime = TimeGenerated, UserPrincipalName, SuccessIPAddress = IPAddress, AppDisplayName, SuccessIPBlock = strcat(split(IPAddress, ".")[0], ".", split(IPAddress, ".")[1]), Type
| join kind= inner (
    table(tableName)
    | where ResultType !in ("0", "50140")
    | where ResultDescription !~ "Other"
    | where AppDisplayName !in ("Office 365 Exchange Online", "Skype for Business Online")
    | project FailedLogonTime = TimeGenerated, UserPrincipalName, FailedIPAddress = IPAddress, AppDisplayName, ResultType, ResultDescription, Type
) on UserPrincipalName, AppDisplayName
| where SuccessLogonTime < FailedLogonTime and FailedLogonTime - SuccessLogonTime <= logonDiff and FailedIPAddress !startswith SuccessIPBlock
| summarize FailedLogonTime = max(FailedLogonTime), SuccessLogonTime = max(SuccessLogonTime) by UserPrincipalName, SuccessIPAddress, AppDisplayName, FailedIPAddress, ResultType, ResultDescription, Type
| extend timestamp = SuccessLogonTime
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
union isfuzzy=true aadSignin, aadNonInt
name: Successful logon from IP and failure from a different IP
query: |
  let logonDiff = 10m;
  let aadFunc = (tableName:string){
  table(tableName)
  | where ResultType == "0"
  | where AppDisplayName !in ("Office 365 Exchange Online", "Skype for Business Online")
  | project SuccessLogonTime = TimeGenerated, UserPrincipalName, SuccessIPAddress = IPAddress, AppDisplayName, SuccessIPBlock = strcat(split(IPAddress, ".")[0], ".", split(IPAddress, ".")[1]), Type
  | join kind= inner (
      table(tableName)
      | where ResultType !in ("0", "50140")
      | where ResultDescription !~ "Other"
      | where AppDisplayName !in ("Office 365 Exchange Online", "Skype for Business Online")
      | project FailedLogonTime = TimeGenerated, UserPrincipalName, FailedIPAddress = IPAddress, AppDisplayName, ResultType, ResultDescription, Type
  ) on UserPrincipalName, AppDisplayName
  | where SuccessLogonTime < FailedLogonTime and FailedLogonTime - SuccessLogonTime <= logonDiff and FailedIPAddress !startswith SuccessIPBlock
  | summarize FailedLogonTime = max(FailedLogonTime), SuccessLogonTime = max(SuccessLogonTime) by UserPrincipalName, SuccessIPAddress, AppDisplayName, FailedIPAddress, ResultType, ResultDescription, Type
  | extend timestamp = SuccessLogonTime
  };
  let aadSignin = aadFunc("SigninLogs");
  let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
  union isfuzzy=true aadSignin, aadNonInt  
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Azure Active Directory/Analytic Rules/SuccessThenFail_DiffIP_SameUserandApp.yaml
queryFrequency: 1d
triggerThreshold: 0
requiredDataConnectors:
- dataTypes:
  - SigninLogs
  connectorId: AzureActiveDirectory
- dataTypes:
  - AADNonInteractiveUserSignInLogs
  connectorId: AzureActiveDirectory
version: 1.1.1
status: Available
queryPeriod: 1d
id: 02ef8d7e-fc3a-4d86-a457-650fa571d8d2
triggerOperator: gt
entityMappings:
- fieldMappings:
  - identifier: FullName
    columnName: UserPrincipalName
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: SuccessIPAddress
  entityType: IP
- fieldMappings:
  - identifier: Address
    columnName: FailedIPAddress
  entityType: IP
relevantTechniques:
- T1110
- T1078
severity: Medium
description: |
  'Identifies when a user account successfully logs onto an Azure App from one IP and within 10 mins failed to logon to the same App via a different IP.
  This may indicate a malicious attempt at password guessing based on knowledge of the users account.'  
kind: Scheduled
tactics:
- CredentialAccess
- InitialAccess
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/02ef8d7e-fc3a-4d86-a457-650fa571d8d2')]",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/02ef8d7e-fc3a-4d86-a457-650fa571d8d2')]",
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules",
      "kind": "Scheduled",
      "apiVersion": "2022-11-01",
      "properties": {
        "displayName": "Successful logon from IP and failure from a different IP",
        "description": "'Identifies when a user account successfully logs onto an Azure App from one IP and within 10 mins failed to logon to the same App via a different IP.\nThis may indicate a malicious attempt at password guessing based on knowledge of the users account.'\n",
        "severity": "Medium",
        "enabled": true,
        "query": "let logonDiff = 10m;\nlet aadFunc = (tableName:string){\ntable(tableName)\n| where ResultType == \"0\"\n| where AppDisplayName !in (\"Office 365 Exchange Online\", \"Skype for Business Online\")\n| project SuccessLogonTime = TimeGenerated, UserPrincipalName, SuccessIPAddress = IPAddress, AppDisplayName, SuccessIPBlock = strcat(split(IPAddress, \".\")[0], \".\", split(IPAddress, \".\")[1]), Type\n| join kind= inner (\n    table(tableName)\n    | where ResultType !in (\"0\", \"50140\")\n    | where ResultDescription !~ \"Other\"\n    | where AppDisplayName !in (\"Office 365 Exchange Online\", \"Skype for Business Online\")\n    | project FailedLogonTime = TimeGenerated, UserPrincipalName, FailedIPAddress = IPAddress, AppDisplayName, ResultType, ResultDescription, Type\n) on UserPrincipalName, AppDisplayName\n| where SuccessLogonTime < FailedLogonTime and FailedLogonTime - SuccessLogonTime <= logonDiff and FailedIPAddress !startswith SuccessIPBlock\n| summarize FailedLogonTime = max(FailedLogonTime), SuccessLogonTime = max(SuccessLogonTime) by UserPrincipalName, SuccessIPAddress, AppDisplayName, FailedIPAddress, ResultType, ResultDescription, Type\n| extend timestamp = SuccessLogonTime\n};\nlet aadSignin = aadFunc(\"SigninLogs\");\nlet aadNonInt = aadFunc(\"AADNonInteractiveUserSignInLogs\");\nunion isfuzzy=true aadSignin, aadNonInt\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0,
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CredentialAccess",
          "InitialAccess"
        ],
        "techniques": [
          "T1110",
          "T1078"
        ],
        "alertRuleTemplateName": "02ef8d7e-fc3a-4d86-a457-650fa571d8d2",
        "customDetails": null,
        "entityMappings": [
          {
            "fieldMappings": [
              {
                "identifier": "FullName",
                "columnName": "UserPrincipalName"
              }
            ],
            "entityType": "Account"
          },
          {
            "fieldMappings": [
              {
                "identifier": "Address",
                "columnName": "SuccessIPAddress"
              }
            ],
            "entityType": "IP"
          },
          {
            "fieldMappings": [
              {
                "identifier": "Address",
                "columnName": "FailedIPAddress"
              }
            ],
            "entityType": "IP"
          }
        ],
        "status": "Available",
        "templateVersion": "1.1.1",
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Azure Active Directory/Analytic Rules/SuccessThenFail_DiffIP_SameUserandApp.yaml"
      }
    }
  ]
}