// Illustrative; not run against live data. Microsoft Sentinel, W3CIISLog (IIS web servers). Adapt the column names for other web or WAF logs. // Machine-speed reconnaissance: one source requesting many different paths on a public site within ten minutes, most of which do not exist. // A person browsing touches a handful of pages. A scanner, AI-assisted or not, walks hundreds. let Since = ago(7d); let Sites = dynamic(["REPLACE_WITH_SITE_NAME"]); let OwnScanners = dynamic(["REPLACE_WITH_YOUR_SCANNER_IP"]); W3CIISLog | where TimeGenerated > Since | where sSiteName in (Sites) | where not(cIP in (OwnScanners)) | summarize Requests = count(), DistinctPaths = dcount(csUriStem), NotFound = countif(toint(scStatus) == 404), ServerErrors = countif(toint(scStatus) >= 500), Agents = make_set(csUserAgent, 5) by cIP, bin(TimeGenerated, 10m) | extend NotFoundRatio = round(todouble(NotFound) / Requests, 2) | where DistinctPaths > 100 and NotFoundRatio > 0.5 | order by DistinctPaths desc | take 500