This projected was created during my time at Log(n) Pacific, where we used KQL maps to translate complex data into clear, actionable visuals, making it easier to spot trends, manage risks, and make informed decisions.
- Spot Trends Quickly: See where activity is happening globally, from customer logins to potential risks.
- Strengthen Security: Identify unusual activity in real time to stay ahead of threats.
- Simplify Data: Turn overwhelming data into easy-to-understand visuals for your leadership team.
- Act Proactively: Get real-time insights to respond faster to opportunities and challenges.
This query helps you track malicious network flows in Azure and enriches the data with geolocation details. Hereβs a breakdown π.
let GeoIPDB_FULL = _GetWatchlist("geoip");
let MaliciousFlows = AzureNetworkAnalytics_CL
| where FlowType_s == "MaliciousFlow"
//| where SrcIP_s == "10.0.0.5"
| order by TimeGenerated desc
| project TimeGenerated, FlowType = FlowType_s, IpAddress = SrcIP_s, DestinationIpAddress = DestIP_s, DestinationPort = DestPort_d, Protocol = L7Protocol_s, NSGRuleMatched = NSGRules_s;
MaliciousFlows
| evaluate ipv4_lookup(GeoIPDB_FULL, IpAddress, network)
| project TimeGenerated, FlowType, IpAddress, DestinationIpAddress, DestinationPort, Protocol, NSGRuleMatched, latitude, longitude, city = cityname, country = countryname, friendly_location = strcat(cityname, " (", countryname, ")")This query helps you track malicious network flows in Azure and enriches the data with geolocation details. Hereβs a breakdown:
-
GeoIP Watchlist π:
let GeoIPDB_FULL = _GetWatchlist("geoip");
This loads a geo-location database to map IP addresses to geographic details like country, city, latitude, and longitude. -
Filtering Malicious Flows
β οΈ :
TheAzureNetworkAnalytics_CLtable is filtered to identify malicious flows:FlowType_s == "MaliciousFlow"π΄: Filters the data to only include malicious flows.
-
Sorting and Selecting Data π’:
order by TimeGenerated descβ³: Orders the flows by the most recent time.project TimeGenerated, FlowType = FlowType_s, IpAddress = SrcIP_s, DestinationIpAddress = DestIP_s, DestinationPort = DestPort_d, Protocol = L7Protocol_s, NSGRuleMatched = NSGRules_s;π: Selects the relevant fields:- TimeGenerated π: When the flow was detected.
- FlowType β‘: Type of flow (in this case, "MaliciousFlow").
- IpAddress π: The source IP address.
- DestinationIpAddress π: The destination IP address.
- DestinationPort π: The destination port.
- Protocol π: The layer 7 protocol used (HTTP, etc.).
- NSGRuleMatched π‘οΈ: Any Network Security Group rules that were triggered.
-
GeoIP Enrichment ππ:
The query enriches the malicious flow data by using theipv4_lookupfunction to find geographic details based on the source IP address:evaluate ipv4_lookup(GeoIPDB_FULL, IpAddress, network)π: This function adds location details (city, country, latitude, longitude) for the source IP address.
-
Data Projection π―:
The query then selects the final output fields:- TimeGenerated π: When the flow occurred.
- FlowType β‘: Type of flow.
- IpAddress π: Source IP address.
- DestinationIpAddress π: Destination IP address.
- DestinationPort π: Destination port.
- Protocol π: Protocol used.
- NSGRuleMatched π‘οΈ: NSG rule triggered.
- Latitude π and Longitude π: Geographical coordinates.
- City ποΈ: The city associated with the IP.
- Country π: The country associated with the IP.
- Friendly_location π·οΈ: A combined label with city and country for better readability.
This query gives you a detailed view of malicious network flows, including:
- FlowType β‘: The type of flow (malicious).
- IP Addresses ππ: Source and destination IPs.
- Destination Port π: The target port.
- Protocol π: The type of protocol used.
- NSG Rule Matched π‘οΈ: Which security rules were triggered.
- Geolocation Information ππ: City, country, latitude, and longitude for the source IP, helping you track the location of malicious flows in real-time.
This helps identify threats and track malicious activity more effectively by adding geographical context to each event, improving your network security insights.
To better understand and refine your KQL query for Microsoft Defender and ensure it works seamlessly for your graph visualization, let's break it down step-by-step:
In short, this query provides a count of successful logins, along with details like where the user is logging in from π.
SigninLogs
| where ResultType == 0
| summarize LoginCount = count() by Identity, Latitude = tostring(LocationDetails["geoCoordinates"]["latitude"]), Longitude = tostring(LocationDetails["geoCoordinates"]["longitude"]), City = tostring(LocationDetails["city"]), Country = tostring(LocationDetails["countryOrRegion"])
| project Identity, Latitude, Longitude, City, Country, LoginCount, friendly_label = strcat(Identity, " - ", City, ", ", Country)This query analyzes sign-in logs to give you a clear picture of user activity. Hereβs a simple breakdown:
-
SigninLogs π: This is where Azure AD sign-in data is stored.
-
where ResultType == 0β : Filters the data to only include successful sign-ins (ResultType 0 means success). -
summarize LoginCount = count()π’: Counts how many successful logins happened and groups them by specific details, such as:- Identity π€: The user who logged in.
- Latitude π & Longitude π: The geographic location of the userβs sign-in.
- City ποΈ: The city where the sign-in occurred.
- Country π: The country where the sign-in occurred.
-
projectπ―: This step selects and renames the final data you want to display:- Identity π₯: The userβs name or ID.
- Latitude & Longitude ππ: Their location.
- City & Country ποΈπ: Where they logged in from.
- LoginCount π’: The number of successful logins from that user.
friendly_labelπ·οΈ: A friendly label that combines the user's name with their city and country for easier reference.
CEOs and non-tech people will love this because it turns complex data into easy-to-understand insights ππ. It shows where users are logging in from π, how many successful logins there are π’, and provides a clear view of business activity without technical jargon. Perfect for making fast, informed decisions and spotting trends! π‘
This query helps you identify failed sign-ins by analyzing the SigninLogs data. Here's a simple breakdown π.
SigninLogs
| where ResultType != 0
| summarize LoginCount = count() by Identity, Latitude = tostring(LocationDetails["geoCoordinates"]["latitude"]), Longitude = tostring(LocationDetails["geoCoordinates"]["longitude"]), City = tostring(LocationDetails["city"]), Country = tostring(LocationDetails["countryOrRegion"])
| project Identity, Latitude, Longitude, City, Country, LoginCount, friendly_label = strcat(Identity, " - ", City, ", ", Country)-
SigninLogs π: This is where Azure AD sign-in data is stored.
-
where ResultType != 0β: Filters the data to only include failed sign-ins (ResultType other than 0 means failure). -
summarize LoginCount = count()π’: Counts the number of failed logins, grouped by specific details, such as:- Identity π€: The user who attempted to log in.
- Latitude π & Longitude π: The geographic location of the failed sign-in.
- City ποΈ: The city where the failed sign-in occurred.
- Country π: The country where the failed sign-in occurred.
-
projectπ―: This step selects and renames the final data you want to display:- Identity π₯: The userβs name or ID.
- Latitude & Longitude ππ: Their location.
- City & Country ποΈπ: Where the failed sign-in occurred.
- LoginCount π’: The number of failed logins from that user.
friendly_labelπ·οΈ: A friendly label that combines the user's name with their city and country for easier reference.
This query gives you a view of failed logins, highlighting potential security concerns, and makes it easier to spot patterns like repeated failed attempts from specific locations π.
This query helps analyze Azure activity logs related to resource creation and enriches them with geographic details. Here's a breakdown of how it works π.
let GeoIPDB_FULL = _GetWatchlist("geoip");
let AzureActivityRecords = AzureActivity
| where not(Caller matches regex @"^[{(]?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}[)}]?$")
| where CallerIpAddress matches regex @"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b"
| where OperationNameValue endswith "WRITE" and (ActivityStatusValue == "Success" or ActivityStatusValue == "Succeeded")
| summarize ResouceCreationCount = count() by Caller, CallerIpAddress;
AzureActivityRecords
| evaluate ipv4_lookup(GeoIPDB_FULL, CallerIpAddress, network)
| project Caller,
CallerPrefix = split(Caller, "@")[0], // Splits Caller UPN and takes the part before @
CallerIpAddress,
ResouceCreationCount,
Country = countryname,
Latitude = latitude,
Longitude = longitude,
friendly_label = strcat(split(Caller, "@")[0], " - ", cityname, ", ", countryname)-
GeoIP Watchlist π:
let GeoIPDB_FULL = _GetWatchlist("geoip");
This loads a geo-location database to map IP addresses to geographic information (like country, city, latitude, and longitude). -
Filtering Azure Activity π:
TheAzureActivitytable is filtered to exclude certain caller IDs and only consider valid IP addresses and successful resource creation actions:where not(Caller matches regex ...)β: Filters out logs with GUID caller IDs (usually representing machines or services).where CallerIpAddress matches regex ...π: Ensures the logs only contain valid IPv4 addresses.where OperationNameValue endswith "WRITE" ...π: Focuses on write operations, like creating or modifying resources, and includes only successful activities.
-
Summarizing Resource Creation π’:
summarize ResouceCreationCount = count()groups the data to count how many resource creation actions took place, grouped by:- Caller π€: The user or service making the request.
- CallerIpAddress πΆ: The IP address used during the request.
-
GeoIP Enrichment ππ:
Using theipv4_lookupfunction, geographic details (such as country, latitude, and longitude) are added to the data by looking up the GeoIPDB_FULL watchlist. -
Data Projection π―:
The query then creates a friendly label and selects the fields to display:- Caller π₯: The name or ID of the user making the request.
- CallerPrefix π€: The part before the "@" in the caller's user principal name (UPN).
- CallerIpAddress π: The IP address used during the request.
- ResouceCreationCount π’: The count of resource creation actions.
- Country π, Latitude π, and Longitude π: Geographic details about the action.
- friendly_label π·οΈ: A user-friendly label combining the caller's name and location for easy reference.
This enriched query gives you a clearer view of resource creation activity, with geographic context to help identify potential suspicious behavior or patterns:
- Caller π€: Who initiated the action.
- CallerPrefix π§βπΌ: The caller's name before the "@" symbol.
- CallerIpAddress πΆ: The IP address used.
- ResourceCreationCount π’: The number of resources created.
- Country, Latitude, and Longitude π: Location details to map the activity.
- friendly_label π·οΈ: A friendly label combining the user's name and location.
This query helps you track resource creation with geographical context, making it easier to spot anomalies or track user activity across different regions.
This query helps you monitor failed logon attempts and identify potential security risks based on the geographical location of the source IP. Hereβs a breakdown π.
let GeoIPDB_FULL = _GetWatchlist("geoip");
DeviceLogonEvents
| where ActionType == "LogonFailed"
| order by TimeGenerated desc
| evaluate ipv4_lookup(GeoIPDB_FULL, RemoteIP, network)
| summarize LoginAttempts = count() by RemoteIP, City = cityname, Country = countryname, friendly_location = strcat(cityname, " (", countryname, ")"), Latitude = latitude, Longitude = longitude;-
GeoIP Watchlist π:
let GeoIPDB_FULL = _GetWatchlist("geoip");
This loads a geolocation database to map IP addresses to location details like country, city, latitude, and longitude. -
Filtering Failed Logins β:
DeviceLogonEvents: This table contains the logon data for devices.where ActionType == "LogonFailed"π: Filters the data to only include failed logon attempts.
-
Sorting Events β³:
order by TimeGenerated descπ: Sorts the events by the most recent time of occurrence.
-
GeoIP Enrichment ππ:
evaluate ipv4_lookup(GeoIPDB_FULL, RemoteIP, network): This function enriches the failed logon events by looking up the geographic location of the RemoteIP (the IP from which the logon attempt originated).
-
Summarizing Data π’:
summarize LoginAttempts = count()π’: Counts the number of failed login attempts, grouped by the following fields:- RemoteIP π: The source IP address of the failed login attempt.
- City ποΈ: The city associated with the IP address.
- Country π: The country associated with the IP address.
friendly_locationπ·οΈ: A combined label of city and country for easier readability (e.g., "London (UK)").- Latitude π and Longitude π: Geographical coordinates of the IP.
This query provides a detailed view of failed logon attempts, including:
- Remote IP π: The IP address that attempted to log in.
- City & Country ποΈπ: The city and country of the source IP.
- Latitude & Longitude ππ: The geographical coordinates.
- Login Attempts π’: The number of failed login attempts for each source IP.
- Friendly Location π·οΈ: A clear, combined label of city and country.
- Security Insights π‘οΈ: Helps detect and track failed login attempts and identify potential threats based on location.
- Geographical Context π: Adds location details to each failed logon, helping to identify if there's unusual activity originating from specific countries or cities.
- Proactive Measures
β οΈ : Enables you to take proactive security measures based on location-based anomalies, such as blocking certain regions or investigating suspicious patterns.
To create a KQL Map in Microsoft Sentinel through Workbooks:
- Go to Microsoft Sentinel π in Azure Portal.
- Select your workspace π’ and click Workbooks.
- Click + Add Workbook β.
- Choose your data source π (e.g., SigninLogs).
- Write your KQL query βοΈ (e.g.,
SigninLogs | summarize LoginCount by Latitude, Longitude). - Click + Add Visualization, select Map πΊοΈ.
- Map Latitude & Longitude fields, customize your map π¨.
- Save and Pin to Dashboard π.
And you're all set with a KQL Map! π
Conclusion: Why CEOs and Non-Tech Leaders Like KQL Maps
KQL Maps turn complex data into easy-to-understand visuals π, helping CEOs and non-tech leaders spot security risks quickly π¨. With location-based insights π, they can make informed decisions π‘ without needing technical expertise, ensuring better protection for the company π‘οΈ. Simple, actionable, and effective! β




