text code block:from logs-azure.aadgraphactivitylogs-* metadata _id, _version, _index | where data_stream.dataset == "azure.aadgraphactivitylogs" and to_lower(user_agent.original) like "*aiohttp*" | eval Esql.target_endpoints = case( url.path like "*/eligibleRoleAssignments*", "eligibleRoleAssignments", url.path like "*/roleAssignments*", "roleAssignments", url.path like "*/users*", "users", url.path like "*/groups*", "groups", url.path like "*/servicePrincipals*", "servicePrincipals", url.path like "*/applications*", "applications", url.path like "*/devices*", "devices", url.path like "*/directoryRoles*", "directoryRoles", url.path like "*/roleDefinitions*", "roleDefinitions", url.path like "*/administrativeUnits*", "administrativeUnits", url.path like "*/contacts*", "contacts", url.path like "*/oauth2PermissionGrants*", "oauth2PermissionGrants", url.path like "*/authorizationPolicy*", "authorizationPolicy", url.path like "*/settings*", "settings", url.path like "*/policies*", "policies", url.path like "*/tenantDetails*", "tenantDetails", "other" ) | where Esql.target_endpoints != "other" | eval Esql.time_window = date_trunc(1 minutes, @timestamp) | stats Esql.request_count = count(*), Esql.distinct_endpoints = count_distinct(Esql.target_endpoints), Esql.api_versions = values(azure.aadgraphactivitylogs.properties.api_version), Esql.app_ids = values(azure.aadgraphactivitylogs.properties.app_id), Esql.user_agent = values(user_agent.original), Esql.http_methods = values(http.request.method), Esql.status_codes = values(http.response.status_code), Esql.source_ips = values(source.ip), Esql.source_asn_orgs = values(source.`as`.organization.name), Esql.source_countries = values(source.geo.country_name), Esql.actor_types = values(azure.aadgraphactivitylogs.properties.actor_type), Esql.client_auth_methods = values(azure.aadgraphactivitylogs.properties.client_auth_method), Esql.session_ids = values(azure.aadgraphactivitylogs.properties.session_id), Esql.sign_in_activity_ids = values(azure.aadgraphactivitylogs.properties.sign_in_activity_id), Esql.scopes = values(azure.aadgraphactivitylogs.properties.scopes), Esql.first_seen = min(@timestamp), Esql.last_seen = max(@timestamp) by user.id, azure.tenant_id, Esql.time_window | where Esql.distinct_endpoints >= 5 | keep user.id, azure.tenant_id, Esql.*
Install detection rules in Elastic Security
Detect Azure AD Graph Potential Enumeration (ROADrecon) in the Elastic Security detection engine by installing this rule into your Elastic Stack.
To setup this rule, check out the installation guide for Prebuilt Security Detection Rules(external, opens in a new tab or window).