Credential Access (TA0006)(external, opens in a new tab or window)
Initial Access (TA0001)(external, opens in a new tab or window)
text code block:from logs-azure_ai_foundry.logs-* | where data_stream.dataset == "azure_ai_foundry.logs" and azure.ai_foundry.category == "GatewayLogs" and azure.ai_foundry.properties.apim_subscription_id is not null and source.ip is not null and source.geo.location is not null and source.geo.country_name is not null | eval Esql.source_geo_lat = st_y(source.geo.location), Esql.source_geo_lon = st_x(source.geo.location) | where Esql.source_geo_lat is not null and Esql.source_geo_lon is not null | stats Esql.first_lat = first(Esql.source_geo_lat, @timestamp), Esql.first_lon = first(Esql.source_geo_lon, @timestamp), Esql.last_lat = last(Esql.source_geo_lat, @timestamp), Esql.last_lon = last(Esql.source_geo_lon, @timestamp), Esql.event_count = count(*), Esql.country_count = count_distinct(source.geo.country_name), Esql.source_ip_values = values(source.ip), Esql.source_geo_country_name_values = values(source.geo.country_name), Esql.source_geo_region_name_values = values(source.geo.region_name), Esql.source_geo_city_name_values = values(source.geo.city_name), Esql.source_as_organization_name_values = values(source.as.organization.name), Esql.azure_ai_foundry_properties_user_agent_values = values(azure.ai_foundry.properties.user_agent), Esql.azure_ai_foundry_properties_backend_response_code_values = values(azure.ai_foundry.properties.backend_response_code), Esql.azure_ai_foundry_properties_apim_subscription_id = min(azure.ai_foundry.properties.apim_subscription_id), Esql.timestamp_first_seen = min(@timestamp), Esql.timestamp_last_seen = max(@timestamp) by azure.ai_foundry.properties.apim_subscription_id, azure.ai_foundry.properties.api_id, azure.ai_foundry.properties.operation_id, azure.resource.name, azure.resource.group, url.domain, url.path | where Esql.event_count >= 2 and Esql.country_count >= 2 | eval Esql.p1 = to_geopoint(concat("POINT(", to_string(Esql.first_lon), " ", to_string(Esql.first_lat), ")")), Esql.p2 = to_geopoint(concat("POINT(", to_string(Esql.last_lon), " ", to_string(Esql.last_lat), ")")) | eval Esql.distance_km = round(st_distance(Esql.p1, Esql.p2) / 1000.0, 0), Esql.window_minutes = date_diff("minute", Esql.timestamp_first_seen, Esql.timestamp_last_seen), Esql.travel_kmh = case(Esql.window_minutes > 0, round(Esql.distance_km * 60.0 / Esql.window_minutes, 0), null), source.ip = MV_FIRST(Esql.source_ip_values) | where Esql.distance_km >= 500 and Esql.travel_kmh >= 800 | keep azure.ai_foundry.properties.apim_subscription_id, azure.ai_foundry.properties.api_id, azure.ai_foundry.properties.operation_id, azure.resource.name, azure.resource.group, url.domain, url.path, source.ip, Esql.*
Install detection rules in Elastic Security
Detect Microsoft Foundry Subscription Key Impossible Travel 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).