Microsoft Entra ID UserAgent OS Missmatch
Id | 6a638d80-f6b2-473b-9087-3cac78a84b40 |
Rulename | Microsoft Entra ID UserAgent OS Missmatch |
Description | This query extracts the operating system from the UserAgent header and compares this to the DeviceDetail information present in Microsoft Entra ID. |
Severity | Medium |
Tactics | DefenseEvasion |
Techniques | T1036 |
Required data connectors | AzureActiveDirectory |
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/FalconFriday/Analytic Rules/AzureADUserAgentOSmissmatch.yaml |
Version | 1.0.1 |
Arm template | 6a638d80-f6b2-473b-9087-3cac78a84b40.json |
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"
}
]
}