Blog Post

Microsoft Sentinel Blog
2 MIN READ

Tip: Easily use JSON fields in Sentinel

Ofer_Shezaf's avatar
Ofer_Shezaf
Icon for Microsoft rankMicrosoft
Jul 23, 2019

One of the great features with Azure Sentinel is that you can ingest any type of data and take care of parsing it later on at query time. Specifically, events originating from cloud sources often include JSON compound elements that provide wealthy information about the event. This is a far cry from traditional SIEM systems that support a rigid event format and, in many cases, require reducing events to fit in the schema. Another common source of JSON data in Azure Sentinel would be enrichment data collected using playbooks as demonstrated by Tiander Turpin here.

 

This brings us to the question of how to write a query to use JSON fields. Sentinel’s query language, KQL, uses the parse_json function to provide access to JSON field elements. However, when the JSON structure becomes deeper, using this function can become cumbersome. Luckily, Sentinel provides new tools to help you write those queries.

 

Let’s use Microsoft Cloud App Security (MCAS) alerts as an example. Using the following query, we get MCAS alerts on impossible travel:

SecurityAlert

| where ProviderName == "MCAS"

| where DisplayName == "Impossible travel activity"

| limit 10

 

Expanding one of the events, we can see that the countries Alex visited are located in the Extended Properties JSON compound field:

 

 

To use the countries just visited value, we can use the ellipsis on the left side of it automatically add a JSON parsing function to our query. Selecting the include option updates the query automatically to the one below:

 

 

SecurityAlert

| where ProviderName == "MCAS"

| where DisplayName == "Impossible travel activity"

| limit 10 

| where parse_json(ExtendedProperties).Countries == "AU, DE, FR, GB, JP, US"

 

However, since the Counties field is a list, include and exclude might not be particularly useful as they add a condition that would require the entire list of counties to be identical. You can change the “==” or “!=” operators automatically generated to a contains or !contains operators:

SecurityAlert

| where ProviderName == "MCAS"

| where DisplayName == "Impossible travel activity"

| limit 10

| where parse_json(ExtendedProperties).Countries contains "AU"

 

A better option would be to use the extend column option, which allows to filter further and process the new field and also ensures it is presented as a field in the results. Using extend column instead of include, the query is automatically updated as follows:

SecurityAlert

| where ProviderName == "MCAS"

| where DisplayName == "Impossible travel activity"

| limit 10

| extend Countries_ = tostring(parse_json(ExtendedProperties).Countries)

Will result in the following output, adding a Countries_ field to the result set for easy viewing:

 

Updated Jul 24, 2019
Version 3.0
  • PrashTechTalk's avatar
    PrashTechTalk
    Brass Contributor

    Ofer_Shezaf  Good one. 

    Can you please share some information on how can we extract or parse the entities data when no of values within the entities are not constant.

     

    Thanks.

  • PrashTechTalk : use the mv-expand operator. It will creates a separate row in the result set for each array value, enabling processing the array using regular KQL table processing.