Review your Azure security with the power of KQL!
❄️ This lab was created as a part of Cloud Security Podcast's "24 Days of Cloud" video event. Check it out!
Are you still waiting on CSPM budget? Have a few unmanaged Azure tenants to review? Or just curious to see your subscription's public Azure exposure?
The Azure Resource Graph Explorer can help! This web interface lets you query all your Azure infrastructure for common exposures. Try this lab out for a quick introduction on how KQL queries in the Resource Graph Explorer can help you report on VM, Storage, and Cosmos DB network exposures.
This repository is an easy lab to demonstrate how Azure Resource Graph's KQL searches can be used to provide a quick, high-level security review. The terraform
directory will deploy a few Azure resources (VMs, storage, Cosmos DB) with various network exposures. Alternatively, you can run the queries below against your own existing environment without any risk of modifying infrastructure or generating alerts.
The Azure Resource Graph Explorer provides a fantastic, super-quick web query to a database of all Azure resources within an Azure tenant. (Access to query resources is based on your Reader or equivalent roles across the tenant.) This ability to query all resources and most resource properties at scale is incredibly helpful to understand all your Azure assets at once, especially when exploring network exposures and security issues.
More defenders should know about the power of KQL for quick security reporting! It's my hope this lab can get you started.
You can find a walkthrough of this lab content as part of Cloud Security Podcast's "24 Days of Cloud" event on Day 14:
Or, go straight to the walkthrough here:
If Terraform is new to you, don't worry: The code is broken into several small files that work with the with the azurerm
resource provider to create configurations in your own Azure test environment. The goal of presenting content in this way is to make it easy to quickly understand and adapt if you want to play with these files.
The cost of running this demo environment for a couple hours should be below $5 USD. If you're concerned about running up costs, use terraform destroy
whenever you aren't actively playing with the lab. Running these queries against an existing Azure environment to see what turns up is free.
This also makes the Azure Resource Graph Explorer a great way to start environment review before your CSPM budget kicks in.
Demo KQL queries for this lab and sample security reviews are available further down this page.
All resources are created from the terraform
directory. This code creates the following Azure resources:
01-locals.tf
: Configuration variables. Also creates the resource groupkql-demo-env-rg
.02-vms.tf
: Creates 2 VMs, 1 Windows and 1 Linux, with different NSG exposures.03-storage.tf
: Creates 3 storage accounts with different exposure and network rules.04-cosmosdb.tf
: Creates 2 Cosmos DB instances, 1 public and 1 private. WARNING: Takes up 5 minutes to create, and up to 20 minutes to delete! Remove this file from the folder if you're in a hurry.05-outputs.tf
: Output shown to the user when the Terraform run completes.
It's not very complex, just split across multiple files for readability.
- Ensure you are logged in as a user with Owner or equivalent rights to create resources in an Azure subscription by executing
az login
from a terminal session. - If you need resources created in a specific subscription, set your session to that subscription using
az account set --subscription [id]
. - (Optional) Remove the
4-cosmosdb.tf
file if you don't want to wait 20 minutes to clean up this environment. - From the
terraform
folder, executeterraform init
+terraform apply
. Type "yes" to apply. Deployment will take around 5 minutes, so grab a cup of tea! - Open the Azure Resource Graph Explorer (https://portal.azure.com/#view/HubsExtension/ArgQueryBlade), or check your Terraform output for a URL that will take you directly to the created resource group.
- Play with KQL!! Sample queries to review these resources are available below.
- When you are done, execute
terraform destroy
. Cleanup will take around 20 minutes, if you included Cosmos DB.
Queries are incremental. In other words, we'll start basic and work up towards a larger query that could be helpful for security review. NOTE: If you're querying a large environment, you may get rate limited by the Azure Resource Graph.
Let's start by exploring the VMs that were deployed. We'll end with a report of exposed VMs, by analyzing their attached NSGs.
This report will build on a sample query from Microsoft. While the last few queries look complex, don't let them intimidate you! They're just a copy-paste away.
If you're new to the concept of a join
, try breaking the final three queries down (running each bit that starts with resources
) to understand them better.
# | Task | Query |
---|---|---|
1 | List all resources | resources |
2 | Compute resources | resources |
3 | Virtual machines | resources |
4 | Public IPs | resources |
5 | List of all public IPs | resources |
6 | Map all public IPs to their matching VMs | Microsoft: Resource Graph - Advanced Queries |
7 | Network Security Group Rules (ACLs) exposed to the public internet | resources |
8 | Report List VMs with public exposure, based on NSG ACLs | resources |
We'll continue by building a query to uncover exposed storage accounts.
Enabling public network access doesn't always mean a storage account is exposed to the world! We'll refine our initial search by specifying storage with a default network action of "Allow" to improve our final report.
This will filter out a storage account that allows just our IP to connect, since this isn't the kind of account we're looking for.
# | Task | Query |
---|---|---|
1 | Storage accounts | resources |
2 | Storage accounts within just our demo resource group | resources |
3 | Storage accounts allowing public network access | resources |
4 | Storage accounts exposed to all public networks | resources |
5 | Report List storage exposed to all public networks | resources |
Let's finish by looking at Cosmos DB. While network exposure is worth considering, this is also a great example of pulling a resource inventory.
In 2021, Wiz released a report on the "Chaos DB" vulnerability. In their remediation guidance, they suggested rotating Cosmos DB keys for all databases as a method to ensure data could not be accessed by attackers.
For this scenario, we'll work up to creating a resource inventory of Cosmos DB instances and when their keys were last changed. This will make it clear which databases still need their keys updated.
# | Task | Query |
---|---|---|
1 | Cosmos DB instances | resources |
2 | Cosmos DB instances with public network access enabled | resources |
3 | Cosmos DB instances, listed with their associated key metadata | resources |
4 | Report List Cosmos DB resources with last key rotation times | resources |
- Azure Resource Graph Explorer: https://portal.azure.com/#view/HubsExtension/ArgQueryBlade
- Understanding the Azure Resource Graph query language: https://learn.microsoft.com/en-us/azure/governance/resource-graph/concepts/query-language
- Starter Resource Graph query samples: https://learn.microsoft.com/en-us/azure/governance/resource-graph/samples/starter?tabs=azure-cli
- Advanced Resource Graph query samples: https://learn.microsoft.com/en-us/azure/governance/resource-graph/samples/advanced?tabs=azure-cli