Recently, I started working with Azure Sentinel, and as any other technology that I want to learn more about, I decided to explore a few ways to deploy it. I got a grasp of the basic architecture and got more familiarized with it. As a researcher, I also like to simplify deployments in my lab environment and usually look for ways to implement the infrastructure I work with as code. Therefore, I started to wonder if I could automate the deployment of an Azure Sentinel solution via a template or a few scripts. Even though, it made sense to expedite the deployment of the solution, I realized I still did not have data or other resources to play with. Then, I wondered If I could integrate the deployment of an Azure Sentinel instance and other resources through the same scripts or templates covering different scenarios.
In the end, this approach allows me to also share the process with others in the community in a more practical way.
This post is part of a four-part series where I will show you how to deploy your own Azure Sentinel solution in a lab environment via Azure Resource Management (ARM) templates along with a custom logs ingestion pipeline to consume pre-recorded datasets and other resources such as network environments for research purposes.
In this post, I show you how to use ARM templates to deploy an Azure Sentinel solution and ingest pre-recorded datasets via a python script, Azure Event Hubs and a Logstash pipeline.
The other parts of this series can be found in the following links:
Microsoft Azure Sentinel is a scalable, cloud-native, security information event management (SIEM) and security orchestration automated response (SOAR) solution. An Azure service that empowers organizations to bring disparate data sources from resources hosted both on-premises and in multiple clouds and be able to detect, investigate and respond to threats.
If you want to learn more about Azure Sentinel, I would recommend to explore this Microsoft Azure document page. Also, if you want to know what you can do with it, make sure you read the articles available in the Microsoft Tech Community Sentinel blog and take a look at these awesome webinars.
Technically, all we need to do to deploy an Azure Sentinel solution is:
That basic set up allows you explore all the main features of Azure Sentinel as well as preloaded out-of-the-box resources such as queries, visualizations, response playbooks, and notebooks. You could also upload other resources and even enable data connectors in Azure Sentinel via code. Javier Soriano blogged about it in this post, and it is a great reference for production deployments.
One of the things I wanted to do different for this post was execute Azure Sentinel On-boarding steps, but in a declarative way with Azure Resource Manager (ARM) templates without having to run PowerShell commands.
To implement infrastructure as code for your Azure solutions, use Azure Resource Manager templates. The template is a JavaScript Object Notation (JSON) file that defines the infrastructure and configuration for your project. The template uses declarative syntax, which lets you state what you intend to deploy without having to write the sequence of programming commands to create it.
The Azure Resource Manager is the deployment and management service for Azure and below you can see some of the ways you could interact with it.
A few things that I like about ARM templates are the orchestration capabilities to deploy resources in parallel which makes it faster than serial deployments, and also the feature to track deployments via the Azure portal.
Now that we know a little bit more about Azure Resource Manager services, we are ready to deploy Azure Sentinel. One document that I recommend to get familiar with to learn more about Azure resources mapped to ARM template resource types is this one. In this section, we are going to deploy a Log Analytics workspace and enable Azure Sentinel. Remember that I provide the template for you so that you can follow along.
A Log Analytics workspace can be found under the Microsoft.OperationalInsights resource types as Microsoft.OperationalInsights/workspaces
{
"name": "string",
"type": "Microsoft.OperationalInsights/workspaces",
"apiVersion": "2015-11-01-preview",
"location": "string",
"tags": {},
"properties": {
"sku": {
"name": "string"
},
"retentionInDays": "integer"
},
"resources": []
}
I created an initial template with some parameters to make it modular for anyone to use. This is the initial template:
Next, I needed to define the Azure Sentinel solution and enable it on the top of the Log Analytics workspace. You can do it with a resource type found under the Microsoft.OperationsManagement resource types as Microsoft.OperationsManagement/solutions .
{
"name": "string",
"type": "Microsoft.OperationsManagement/solutions",
"apiVersion": "2015-11-01-preview",
"location": "string",
"tags": {},
"plan": {
"name": "string",
"publisher": "string",
"promotionCode": "string",
"product": "string"
},
"properties": {
"workspaceResourceId": "string",
"containedResources": [
"string"
],
"referencedResources": [
"string"
]
}
}
I added that to our initial ARM template and this is the final result:
That’s it! You can download it and use it for the next steps.
There are a few ways to execute ARM templates, and it all depends on how comfortable you are with the Azure portal and Azure tool-kits (e.g. Azure CLI)
If you want to use one command to deploy an ARM template, then this option is for you. The Azure command-line interface (CLI) is Microsoft’s cross-platform command-line experience for managing Azure resources. It can be installed in Windows, macOS and Linux environments. In addition, there is a PowerShell version of it and also an interactive, authenticated, browser-accessible option known as the Azure Cloud Shell.
We can start using Azure CLI and create a Resource Group if you have not done it yet. Run the following command to create one in a specific location:
az group create --location eastus --resource-group AzSentinelDemo
Next, you can run the following command to execute the ARM template:
az deployment group create --name AzSentinelDeploy --resource-group AzSentinelDemo --template-file <ARM Template name>.json --parameters workspaceName=AzSentinelWS
az deployment group create
: Start a deployment--name
: Name of your deployment--resource-group
: Name of the Azure Resource group--template-file
: Template that I put together for this deployment.--parameters
: Deployment parameter values (key=value). Provide a name for your Log Analytics workspace. The name must be globally unique across all Azure subscriptions. I take care of that for you in the template by adding a unique string after the name you provide.
Track your deployment: Azure Portal>Resource Group Name>Deployments
That’s it! once your deployment completes, you will be able to access the main Azure Sentinel interface. Before we do that, let me show you another way to execute our ARM template.
It takes a few more clicks to do it via the Azure portal, but it is easy to follow:
That’s it! once your deployment completes, you will be able to access the main Azure Sentinel interface.
You will be taken to the main Azure Sentinel interface. That was easy right?
“Why do I have to do all that with ARM templates when I can just follow these instructions and with a few clicks I can deploy one too?”
Deploying the solution while working in a lab environment is not enough. You need to have other resources and data to start exploring and learning about all the capabilities Azure Sentinel provides. That will take more than just a few clicks. What if we can take the ARM template that we just used and run other nested templates in parallel to deploy other resources and even ingest pre-recorded data for additional research?
Azure Sentinel2Go is an open source project developed to expedite the deployment of an Azure Sentinel lab along with other Azure resources and a data ingestion pipeline to consume pre-recorded datasets for research purposes.
Azure Sentinel2Go is part the Blacksmith project
The Blacksmith project focuses on providing dynamic easy-to-use templates for security researches to model and provision resources to automatically deploy applications and small networks in the cloud.
Azure Sentinel2Go is a work in progress, and I welcome feedback on what it is that you would like to see being deployed along with an Azure Sentinel solution and datasets you would like to work with in your lab environment.
One of the features that I have noticed security analysts get interested the most while using Azure Sentinel for the first time is the Log Analytics capabilities. Log Analytics is the primary tool in the Azure portal for writing log queries written in Kusto Query Language (KQL) to quickly retrieve, consolidate, and analyze security events. Therefore, I decided to find a way for researchers to learn about KQL with pre-recorded datasets.
Fortunately, the Log Analytics workspace allows the collection of custom logs via its HTTP Data Collector API. If you want to learn how to do it with code, there are some basic examples in Azure docs for Powershell, C# and Python.
In this section I will share a few of my favorite ways to send pre-recorded datasets to a Log Analytics workspace custom log table.
This is one of the simplest ways to send data directly to a log analytics workspace. I took the basic example available here, and extended it a little bit to be able to read from a JSON file or a folder, show a progress bar, and send smaller sized chunks of 5MB per POST request. Make sure you read the Data Limits while using a similar approach. I also extended the PowerShell script available and created a proof of concept here.
The script is available here and all the information you will need from the log analytics workspace can be found in Azure Portal>Log Analytics Workspace>Advanced Settings.
Next, we need a data sample for this exercise. Therefore, the project comes with a few data samples in this folder. Download the dataset-sample-small.tar.gz to your local computer and decompress it.
tar -xzvf dataset-sample-small.tar.gz
Next, send it over by running these commands in your local computer:
python3 ala-python-data-producer.py -w <WorkspaceID> -k <SharedKey> -l "onesample" -f dataset-sample-small.json -v
Once it completes go to your Azure Sentinel interface and click on Logs. You can see that there are no events yet. It usually takes from 5–10 mins.
You can see a new table under customs logs with the event schemas. Remember that not every event will have the same schema. Make sure you understand the schema of your events before running queries.
Based on the event schemas, we can run the following query to see what events we are working with:
onesample_CL
| summarize count() by winlog_channel_s, winlog_event_id_d, winlog_task_s
That’s it! This is a very practical way to ingest custom logs, but might not scale with larger files or hundreds of files in a loop. Therefore, I wanted to also provide another option that would allow me to send events to a more robust pipeline and let it handle the whole process. This is a proof of concept and works very well in a lab environment.
I like to use existing tools that are proven to work at scale and this is not the exception. TL;DR — I use Kafkacat to read json files stored locally and send them over to an Azure Event Hub. Next, Logstash reads them from Azure Event Hub, and sends them over to a Log Analytics workspace.
In more details the following is happening in the image above:
I already provide the following configurations as part of the Azure Sentinel2Go project.
This is the Logstash input config file to consume events from an Azure Event Hub. The plugin used is the Logstash Azure Event Hubs input plugin.
input {
azure_event_hubs {
event_hub_connections => ["${EVENTHUB_CONNECTIONSTRING}"]
threads => 2
initial_position => "end"
#codec => "json"
}
}
I do not use the input codec => "json"
property because I do not want to unpack the event Message field and exceed the max number (500) of custom fields per data type in the Log Analytics workspace.
This is the Logstash output config file to send the events that it collects from the Azure Event Hub to a Log Analytics workspace. The plugin used is the Azure Log Analytics output plugin for Logstash
developed by Microsoft.
output { microsoft-logstash-output-azure-loganalytics { workspace_id => "${WORKSPACE_ID}" workspace_key => "${WORKSPACE_KEY}" custom_log_table_name => "prerecorded" plugin_flush_interval => 5 } #stdout { codec => rubydebug } }
One thing I added to the Azure Sentinel2Go repository is a “Deploy to Azure” badge used on Azure quick-start templates to upload the ARM template directly to the Azure portal. Very convenient! You need to go to Azure-Sentinel2Go > grocery-list > custom-log-pipeline and click on the "Deploy to Azure" badge to deploy an Azure Sentinel along with a custom logs pipeline:
You will be taken to the interface to set deployment parameters. Set the Deploy Custom Logs Pipeline parameter to Logstash-EventHub. One thing to pay attention to is the virtual machine size. If you are in westus
, you need to switch it to Standard_A3
. Also, make sure you set the AllowedIPAddresses
parameter to restrict access to the Logstash box. Add your company or your house Public IP address.
Monitor your deployment. It should take around 8–10 minutes.
Once it completes, you should be able to send prerecorded data from your local computer to the Azure Event Hub.
First, create a local Kafkacat configuration file to define a few properties to be able to access the Azure Event Hub. I created one for you.
You will need to get the following values and paste them in the config file.
Second, we need a sample dataset to send over to our Azure Event Hub. We can use the same dataset we used earlier with the Python script.
Next, in your local computer, run Kafkacat in Producer mode as shown below.
kafkacat -b <EVENTHUB-NAMESPACE>.servicebus.windows.net:9093 -t <EVENTHUB-NAME> -F <KAFKACAT-FILE>.conf -P -l dataset-sample.json
-b
: Bootstrap broker(s) (host[:port]). Your Event Hub Namespace-t
: Topic to produce/send events to. The name of you Event Hub.-F
: Read configuration properties from the Kafkacat.conf file.-P
: Producer Mode : Produce/Send events.-l
: Send messages from a file. Pre-recorded dataset.
Once you run that command, you can check the events flowing through the Azure Event Hub. Go to Azure Portal > Resource Group Name > Event Hub Namespace and filter the Show Metrics view to show Messages only. It might take a few minutes for the view to update.
The Azure Sentinel view also will take a a few mins to update.
As you already know, click on Logs (Log Analytics) to explore the custom logs and their schema. One thing to remember is that the events flowing through this pipeline are packed inside of the Message field. As I mentioned before, this is to avoid exceeding the max number (500) of custom fields per data type in case you send a lot of events with different schemas.
You can unpack the Message field and get to specific nested fields with the Kusto Query function parse_json(). This function interprets a string
as a JSON value and returns the value as dynamic
.
prerecorded_CL
| extend m=parse_json(Message)
| summarize count() by EventID=tostring(m.winlog.event_id),EventProvider=tostring(m.winlog.channel),Task=tostring(m.winlog.task)
Remember that not every event will have the same schema. Make sure you understand the schema of your events before running queries.
Azure Sentinel2Go also comes with the option to load pre-recorded datasets right at deployment time from the Mordor project. It leverages the same Logstash VM for the data ingestion. You do not have to send anything from your local computer. The data from mordor is downloaded and imported all via ARM templates.
I use the following commands to download and decompress all small mordor datasets. The commands are part of the deployment and are executed inside of the Linux VM when you choose to add the item "mordor-small-datasets" to the Add to cart parameter while deploying Azure Sentinel2Go. You do not have to run anything in your local computer.
git clone https://github.com/OTRF/mordor.git
cd mordor/datasets/small/
find . -type f -name "*.zip" | grep -i 'host' | while read filename; do unzip -o -d /opt/logstash/datasets/ $filename; done;
If you choose to add the item "mordor-large-apt29" to your Add Mordor Dataset parameter while deploying Azure Sentinel2Go, the following commands are executed inside of the Linux VM:
git clone https://github.com/OTRF/mordor.git
cd mordor/datasets/large/apt29
find . -type f -name "*_manual.zip" -print0 | xargs -0 -I{} unzip {} -d /opt/logstash/datasets/
This is the additional Logstash input config to read all the JSON files. The plugin used is the Logstash File Input plugin.
input {
file {
path => "/usr/share/logstash/datasets/*.json"
start_position => "beginning"
sincedb_path => "/dev/null"
#codec => "json"
}
}
If you have resources running from the earlier deployment, I recommend to delete them (Lab environment). Similar to our previous deployment, go to Azure-Sentinel2Go > grocery-list > custom-log-pipeline. Select Logstash for the Deploy Custom Logs Pipeline parameter as shown below and add a mordor dataset to your cart (Add Mordor Dataset) . For this example, we are going to use the mordor-small-datasets scenario. Also, once again, make sure you set the AllowedIPAddresses
parameter to restrict access to the Logstash box. Add your company or your house Public IP address.
Monitor the deployment. It might take around 8–10 minutes for it to be done. When it is complete, go to your Azure Sentinel interface. Give it 2–3 mins for events to start showing. You will start getting thousands of events (300K+).
What I do while I wait for all the events (200k+) to be ingested 🙂
We can do the same as before and explore a few events to understand the event schemas. Also, since those events were generated as part of the Mordor project, you could focus on datasets mapped to specific ATT&CK tactics and techniques. The project comes with a Navigator View for the specific platforms that it supports (Currently only Windows).
One thing that I like to look for when looking for lateral movement techniques is processes created under logon sessions that were initially created as part of a network authentication event (Logon Type 3). One example can be adversaries leveraging the Windows Management Instrumentation (WMI) and Win32_Process class to execute commands over the network. This behavior would generate something similar to this:
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.