ID: Azure_AD_Rare_UserAgent_App_Sign-in
OS: N/A
FP Rate: Medium
Tactics: TA0005 - Defense Evasion
Technique | Subtechnique | Technique Name |
---|---|---|
T1036 | Masquerading | |
|
Log Provider | Event ID | Event Name | ATT&CK Data Source |
---|---|---|---|
AzureAD_SigninLog |
The query establishes a base-line of the type of UserAgent (i.e. browser, office application, etc) that is typically used for a particular application by looking back for a number of days. It then searches the current day for any deviations from this pattern, i.e. types of UserAgents not seen before in combination with this app.
User
An attacker might be able to steal an access token for a particular app and use that to connect on behalf of the user.
None.
There might be users that are using a rare UserAgent, app combination for legitimate purposes, for example a specific third party app to connect to a service.
Verify with the user whether there is a legitimate reason for using this particular UserAgent in combination with the app.
If the attacker fully mimics the user agent of the actual application this rule will not be able to detect it.
Language: Kusto
Platform: Sentinel
Query:
let minimumAppThreshold = 100;
let timeframe = 1d;
let lookback_timeframe= 7d;
let ExtractBrowserTypeFromUA=(ua:string) {
// Note these are in a specific order since for example Edge contains based
// Chrome/ and Edge/ strings
case(
ua contains "Edge/", dynamic({"AgentType": "Browser", "AgentName": "Edge"}),
ua contains "Edg/", dynamic({"AgentType": "Browser", "AgentName": "Edge"}),
ua contains "Trident/", dynamic({"AgentType": "Browser", "AgentName": "Internet Explorer"}),
ua contains "Chrome/" and ua contains "Safari/", dynamic({"AgentType": "Browser", "AgentName": "Chrome"}),
ua contains "Gecko/" and ua contains "Firefox/", dynamic({"AgentType": "Browser", "AgentName": "Firefox"}),
not(ua contains "Mobile/") and ua contains "Safari/" and ua contains "Version/", dynamic({"AgentType": "Browser", "AgentName": "Safari"}),
ua startswith "Dalvik/" and ua contains "Android", dynamic({"AgentType": "Browser", "AgentName": "Android Browser"}),
ua startswith "MobileSafari//", dynamic({"AgentType": "Browser", "AgentName": "Mobile Safari"}),
ua contains "Mobile/" and ua contains "Safari/" and ua contains "Version/", dynamic({"AgentType": "Browser", "AgentName": "Mobile Safari"}),
ua contains "Mobile/" and ua contains "FxiOS/", dynamic({"AgentType": "Browser", "AgentName": "IOS Firefox"}),
ua contains "Mobile/" and ua contains "CriOS/", dynamic({"AgentType": "Browser", "AgentName": "IOS Chrome"}),
ua contains "Mobile/" and ua contains "WebKit/", dynamic({"AgentType": "Browser", "AgentName": "Mobile Webkit"}),
//
ua startswith "Excel/", dynamic({"AgentType": "OfficeApp", "AgentName": "Excel"}),
ua startswith "Outlook/", dynamic({"AgentType": "OfficeApp", "AgentName": "Outlook"}),
ua startswith "OneDrive/", dynamic({"AgentType": "OfficeApp", "AgentName": "OneDrive"}),
ua startswith "OneNote/", dynamic({"AgentType": "OfficeApp", "AgentName": "OneNote"}),
ua startswith "Office/", dynamic({"AgentType": "OfficeApp", "AgentName": "Office"}),
ua startswith "PowerPoint/", dynamic({"AgentType": "OfficeApp", "AgentName": "PowerPoint"}),
ua startswith "PowerApps/", dynamic({"AgentType": "OfficeApp", "AgentName": "PowerApps"}),
ua startswith "SharePoint/", dynamic({"AgentType": "OfficeApp", "AgentName": "SharePoint"}),
ua startswith "Word/", dynamic({"AgentType": "OfficeApp", "AgentName": "Word"}),
ua startswith "Visio/", dynamic({"AgentType": "OfficeApp", "AgentName": "Visio"}),
ua startswith "Whiteboard/", dynamic({"AgentType": "OfficeApp", "AgentName": "Whiteboard"}),
ua == "Mozilla/5.0 (compatible; MSAL 1.0)", dynamic({"AgentType": "OfficeApp", "AgentName": "Office Telemetry"}),
//
ua contains ".NET CLR", dynamic({"AgentType": "Custom", "AgentName": "Dotnet"}),
ua startswith "Java/", dynamic({"AgentType": "Custom", "AgentName": "Java"}),
ua startswith "okhttp/", dynamic({"AgentType": "Custom", "AgentName": "okhttp"}),
ua contains "Drupal/", dynamic({"AgentType": "Custom", "AgentName": "Drupal"}),
ua contains "PHP/", dynamic({"AgentType": "Custom", "AgentName": "PHP"}),
ua startswith "curl/", dynamic({"AgentType": "Custom", "AgentName": "curl"}),
ua contains "python-requests", dynamic({"AgentType": "Custom", "AgentName": "Python"}),
pack("AgentType","Other","AgentName", extract(@"^([^/]*)/",1,ua))
)
};
// Query to obtain 'simplified' user agents in a given timespan
let QueryUserAgents = (start_time:timespan, end_time:timespan) {
union withsource=tbl_name AADNonInteractiveUserSignInLogs, SigninLogs
| where TimeGenerated >= ago(start_time)
| where TimeGenerated < ago(end_time)
| where ResultType == 0 // Only look at succesful logins
| extend ParsedUserAgent=ExtractBrowserTypeFromUA(UserAgent)
| extend UserAgentType=tostring(ParsedUserAgent.AgentType)
| extend UserAgentName=tostring(ParsedUserAgent.AgentName)
//| extend SimpleUserAgent=strcat(UserAgentType,"_",UserAgentName)
| extend SimpleUserAgent=UserAgentType
| where not(isempty(UserAgent))
| where not(isempty(AppId))
};
// Get baseline usage per app
let BaselineUserAgents=materialize(
QueryUserAgents(lookback_timeframe+timeframe, timeframe)
| summarize RequestCount=count() by AppId, AppDisplayName, SimpleUserAgent
);
let BaselineSummarizedAgents=(
BaselineUserAgents
| summarize BaselineUAs=make_set(SimpleUserAgent),BaselineRequestCount=sum(RequestCount) by AppId, AppDisplayName
);
QueryUserAgents(timeframe, 0d)
| summarize count() by AppId, AppDisplayName, UserAgent, SimpleUserAgent
| join kind=leftanti BaselineUserAgents on AppId, AppDisplayName, SimpleUserAgent
| join BaselineSummarizedAgents on AppId, AppDisplayName
| where BaselineRequestCount > minimumAppThreshold // Search only for actively used apps
// Get back full original requests
| join QueryUserAgents(timeframe, 0d) on AppId, UserAgent
| project-away ParsedUserAgent, UserAgentName
| project-reorder TimeGenerated, AppDisplayName, UserPrincipalName, UserAgent, BaselineUAs
// Begin whitelist
// End whitelist
| summarize count() by UserPrincipalName, AppDisplayName, AppId, UserAgentType, SimpleUserAgent, UserAgent