Unusual User Agent strings detected in recent traffic may indicate reconnaissance activities targeting IIS servers. SOC teams should proactively hunt for these patterns to identify potential adversary probing before exploitation occurs.
KQL Query
W3CIISLog
//Exclude local addresses, using ipv4_is_private operator
|where ipv4_is_private(cIP) == false and cIP !startswith "fe80" and cIP !startswith "::" and cIP !startswith "127."
| where isnotempty(csUserAgent) and csUserAgent !in~ ("-", "MSRPC")
| extend csUserAgent_size = string_size(csUserAgent)
| project TimeGenerated, sSiteName, sPort, csUserAgent, csUserAgent_size, csUserName , csMethod, csUriStem, sIP, cIP, scStatus,
scSubStatus, scWin32Status, csHost
| join (
W3CIISLog
// The below line can be used to exclude local IPs if these create noise
|where ipv4_is_private(cIP) == false and cIP !startswith "fe80" and cIP !startswith "::" and cIP !startswith "127."
| where isnotempty(csUserAgent) and csUserAgent !in~ ("-", "MSRPC")
| extend csUserAgent_size = string_size(csUserAgent)
| summarize csUserAgent_count = count() by bin(csUserAgent_size, 1)
| top 20 by csUserAgent_count asc nulls last
) on csUserAgent_size
| project TimeGenerated, sSiteName, sPort, sIP, cIP, csUserAgent, csUserAgent_size, csUserAgent_count, csUserName , csMethod, csUriStem,
scStatus, scSubStatus, scWin32Status, csHost
| extend timestamp = TimeGenerated, IPCustomEntity = cIP, HostCustomEntity = csHost, AccountCustomEntity = csUserName
id: 3de523b5-9608-43d5-801e-732c741dd82e
name: Rare User Agent strings
description: |
'This will check for Rare User Agent strings over the last 3 days. This can indicate potential probing of your IIS servers.'
severity: Low
requiredDataConnectors:
- connectorId: AzureMonitor(IIS)
dataTypes:
- W3CIISLog
tactics:
- InitialAccess
relevantTechniques:
- T1190
query: |
W3CIISLog
//Exclude local addresses, using ipv4_is_private operator
|where ipv4_is_private(cIP) == false and cIP !startswith "fe80" and cIP !startswith "::" and cIP !startswith "127."
| where isnotempty(csUserAgent) and csUserAgent !in~ ("-", "MSRPC")
| extend csUserAgent_size = string_size(csUserAgent)
| project TimeGenerated, sSiteName, sPort, csUserAgent, csUserAgent_size, csUserName , csMethod, csUriStem, sIP, cIP, scStatus,
scSubStatus, scWin32Status, csHost
| join (
W3CIISLog
// The below line can be used to exclude local IPs if these create noise
|where ipv4_is_private(cIP) == false and cIP !startswith "fe80" and cIP !startswith "::" and cIP !startswith "127."
| where isnotempty(csUserAgent) and csUserAgent !in~ ("-", "MSRPC")
| extend csUserAgent_size = string_size(csUserAgent)
| summarize csUserAgent_count = count() by bin(csUserAgent_size, 1)
| top 20 by csUserAgent_count asc nulls last
) on csUserAgent_size
| project TimeGenerated, sSiteName, sPort, sIP, cIP, csUserAgent, csUserAgent_size, csUserAgent_count, csUserName , csMethod, csUriStem,
scStatus, scSubStatus, scWin32Status, csHost
| extend timestamp = TimeGenerated, IPCustomEntity = cIP, HostCustomEntity = csHost, AccountCustomEntity = csUserName
version: 1.0.0
metadata:
source:
kind: Community
author:
name: Shain
support:
tier: Community
categories:
domains: [ "Security - Other" ]
| Sentinel Table | Notes |
|---|---|
W3CIISLog | Ensure this data connector is enabled |
Scenario: A system administrator is testing a new web application using a rare user agent string for compatibility checks.
Filter/Exclusion: Exclude user agent strings associated with known internal testing tools (e.g., curl/7.68.0, wget/1.20.3, or PostmanRuntime/7.26.8).
Scenario: A scheduled job is running to fetch updates from a third-party API using a non-standard user agent string.
Filter/Exclusion: Exclude user agent strings that match known API client tools (e.g., Python-urllib/3.9, Go-http-client/1.1, or Apache-HttpClient/4.5.13).
Scenario: An IT department is performing a security audit using a custom script with a rare user agent string to simulate a scan.
Filter/Exclusion: Exclude user agent strings that match internal security tools (e.g., Nmap, OpenVAS, or Qualys).
Scenario: A developer is using a browser extension or a headless browser (e.g., Puppeteer) to automate testing, resulting in a rare user agent string.
Filter/Exclusion: Exclude user agent strings that match known headless browser identifiers (e.g., HeadlessChrome/100.0.4896.60, Puppeteer/2.1.1).
Scenario: A legitimate system is using a rare user agent string for internal monitoring or logging purposes, such as a custom log collector.
Filter/Exclusion: Exclude user agent strings that match internal monitoring tools (e.g., Prometheus, Grafana, or ELK Stack components).