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

Microsoft Entra ID UserAgent OS Missmatch

Back
Id6a638d80-f6b2-473b-9087-3cac78a84b40
RulenameMicrosoft Entra ID UserAgent OS Missmatch
DescriptionThis query extracts the operating system from the UserAgent header and compares this to the DeviceDetail information present in Microsoft Entra ID.
SeverityMedium
TacticsDefenseEvasion
TechniquesT1036
Required data connectorsAzureActiveDirectory
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/AzureADUserAgentOSmissmatch.yaml
Version1.0.1
Arm template6a638d80-f6b2-473b-9087-3cac78a84b40.json
Deploy To Azure
let timeframe = 1d;
let ExtractOSFromUA=(ua:string) {
    case(
        ua has "Windows NT 6.0", "Windows Vista/Windows Server 2008",
        ua has "Windows NT 6.1", "Windows 7/Windows Server 2008R2",
        ua has "Windows NT 6.1", "Windows 7/Windows Server 2008",
        ua has "Windows NT 6.2", "Windows 8/Windows Server 2012",
        ua has "Windows NT 6.3", "Windows 8.1/Windows Server 2012R2",
        ua has "Windows NT 10.0", "Windows 10",
        ua has "Windows Phone", "WindowsPhone",
        ua has "Android", "Android",
        ua has "iPhone;", "IOS",
        ua has "iPad;", "IOS",
        ua has "Polycom/", "Polycom",
        ua has "Darwin/", "MacOS",
        ua has "Mac OS X", "MacOS",
        ua has "macOS", "MacOS",
        ua has "ubuntu", "Linux",
        ua has "Linux", "Linux",
        ua has "curl", "CLI",
        ua has "python", "CLI",
        "Unknown"
    )
};
// Query to obtain 'simplified' user agents in a given timespan.
union withsource=tbl_name AADNonInteractiveUserSignInLogs, SigninLogs
| where TimeGenerated >= ago(timeframe)
| extend UserAgentOS=tolower(ExtractOSFromUA(UserAgent))
| where not(isempty(UserAgent))
| where not(isempty(AppId))
| where ResultType == 0
| extend DeviceOS=tolower(DeviceDetail_dynamic.operatingSystem)
| where not(isempty(DeviceOS))
| where not(UserAgentOS == "unknown")
// Look for matches both ways, since sometimes the browser OS is more specific and sometimes the DeviceOS is more specific.
| where not(UserAgentOS contains DeviceOS) and not(DeviceOS contains UserAgentOS)
| where not(DeviceOS == "ios" and UserAgentOS == "macos") // This can happen for 'request desktop site'
| where not(DeviceOS == "android" and UserAgentOS == "linux") // Android and Linux sometimes confused
| summarize count(), arg_min(TimeGenerated,*) by DeviceOS, UserAgentOS, UserPrincipalName
// Begin allow-list.
// End allow-list.
description: |
    This query extracts the operating system from the UserAgent header and compares this to the DeviceDetail information present in Microsoft Entra ID.
queryPeriod: 1d
name: Microsoft Entra ID UserAgent OS Missmatch
triggerThreshold: 0
tactics:
- DefenseEvasion
severity: Medium
kind: Scheduled
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: FullName
    columnName: UserPrincipalName
queryFrequency: 1d
triggerOperator: gt
id: 6a638d80-f6b2-473b-9087-3cac78a84b40
status: Available
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/AzureADUserAgentOSmissmatch.yaml
version: 1.0.1
query: |
  let timeframe = 1d;
  let ExtractOSFromUA=(ua:string) {
      case(
          ua has "Windows NT 6.0", "Windows Vista/Windows Server 2008",
          ua has "Windows NT 6.1", "Windows 7/Windows Server 2008R2",
          ua has "Windows NT 6.1", "Windows 7/Windows Server 2008",
          ua has "Windows NT 6.2", "Windows 8/Windows Server 2012",
          ua has "Windows NT 6.3", "Windows 8.1/Windows Server 2012R2",
          ua has "Windows NT 10.0", "Windows 10",
          ua has "Windows Phone", "WindowsPhone",
          ua has "Android", "Android",
          ua has "iPhone;", "IOS",
          ua has "iPad;", "IOS",
          ua has "Polycom/", "Polycom",
          ua has "Darwin/", "MacOS",
          ua has "Mac OS X", "MacOS",
          ua has "macOS", "MacOS",
          ua has "ubuntu", "Linux",
          ua has "Linux", "Linux",
          ua has "curl", "CLI",
          ua has "python", "CLI",
          "Unknown"
      )
  };
  // Query to obtain 'simplified' user agents in a given timespan.
  union withsource=tbl_name AADNonInteractiveUserSignInLogs, SigninLogs
  | where TimeGenerated >= ago(timeframe)
  | extend UserAgentOS=tolower(ExtractOSFromUA(UserAgent))
  | where not(isempty(UserAgent))
  | where not(isempty(AppId))
  | where ResultType == 0
  | extend DeviceOS=tolower(DeviceDetail_dynamic.operatingSystem)
  | where not(isempty(DeviceOS))
  | where not(UserAgentOS == "unknown")
  // Look for matches both ways, since sometimes the browser OS is more specific and sometimes the DeviceOS is more specific.
  | where not(UserAgentOS contains DeviceOS) and not(DeviceOS contains UserAgentOS)
  | where not(DeviceOS == "ios" and UserAgentOS == "macos") // This can happen for 'request desktop site'
  | where not(DeviceOS == "android" and UserAgentOS == "linux") // Android and Linux sometimes confused
  | summarize count(), arg_min(TimeGenerated,*) by DeviceOS, UserAgentOS, UserPrincipalName
  // Begin allow-list.
  // End allow-list.  
requiredDataConnectors:
- connectorId: AzureActiveDirectory
  dataTypes:
  - SigninLogs
- connectorId: AzureActiveDirectory
  dataTypes:
  - AADNonInteractiveUserSignInLogs
relevantTechniques:
- T1036
{
  "$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/6a638d80-f6b2-473b-9087-3cac78a84b40')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/6a638d80-f6b2-473b-9087-3cac78a84b40')]",
      "properties": {
        "alertRuleTemplateName": "6a638d80-f6b2-473b-9087-3cac78a84b40",
        "customDetails": null,
        "description": "This query extracts the operating system from the UserAgent header and compares this to the DeviceDetail information present in Microsoft Entra ID.\n",
        "displayName": "Microsoft Entra ID UserAgent OS Missmatch",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "UserPrincipalName",
                "identifier": "FullName"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/AzureADUserAgentOSmissmatch.yaml",
        "query": "let timeframe = 1d;\nlet ExtractOSFromUA=(ua:string) {\n    case(\n        ua has \"Windows NT 6.0\", \"Windows Vista/Windows Server 2008\",\n        ua has \"Windows NT 6.1\", \"Windows 7/Windows Server 2008R2\",\n        ua has \"Windows NT 6.1\", \"Windows 7/Windows Server 2008\",\n        ua has \"Windows NT 6.2\", \"Windows 8/Windows Server 2012\",\n        ua has \"Windows NT 6.3\", \"Windows 8.1/Windows Server 2012R2\",\n        ua has \"Windows NT 10.0\", \"Windows 10\",\n        ua has \"Windows Phone\", \"WindowsPhone\",\n        ua has \"Android\", \"Android\",\n        ua has \"iPhone;\", \"IOS\",\n        ua has \"iPad;\", \"IOS\",\n        ua has \"Polycom/\", \"Polycom\",\n        ua has \"Darwin/\", \"MacOS\",\n        ua has \"Mac OS X\", \"MacOS\",\n        ua has \"macOS\", \"MacOS\",\n        ua has \"ubuntu\", \"Linux\",\n        ua has \"Linux\", \"Linux\",\n        ua has \"curl\", \"CLI\",\n        ua has \"python\", \"CLI\",\n        \"Unknown\"\n    )\n};\n// Query to obtain 'simplified' user agents in a given timespan.\nunion withsource=tbl_name AADNonInteractiveUserSignInLogs, SigninLogs\n| where TimeGenerated >= ago(timeframe)\n| extend UserAgentOS=tolower(ExtractOSFromUA(UserAgent))\n| where not(isempty(UserAgent))\n| where not(isempty(AppId))\n| where ResultType == 0\n| extend DeviceOS=tolower(DeviceDetail_dynamic.operatingSystem)\n| where not(isempty(DeviceOS))\n| where not(UserAgentOS == \"unknown\")\n// Look for matches both ways, since sometimes the browser OS is more specific and sometimes the DeviceOS is more specific.\n| where not(UserAgentOS contains DeviceOS) and not(DeviceOS contains UserAgentOS)\n| where not(DeviceOS == \"ios\" and UserAgentOS == \"macos\") // This can happen for 'request desktop site'\n| where not(DeviceOS == \"android\" and UserAgentOS == \"linux\") // Android and Linux sometimes confused\n| summarize count(), arg_min(TimeGenerated,*) by DeviceOS, UserAgentOS, UserPrincipalName\n// Begin allow-list.\n// End allow-list.\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "DefenseEvasion"
        ],
        "techniques": [
          "T1036"
        ],
        "templateVersion": "1.0.1",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}