[vc_row content_placement=”middle”][vc_column width=”2/3″][vc_wp_text]
[xyz-ips snippet=”metadatatitle”]
[/vc_wp_text][vc_empty_space][/vc_column][vc_column width=”1/3″][vc_wp_text][xyz-ips snippet=”metadatatime”][/vc_wp_text][/vc_column][/vc_row][vc_row content_placement=”middle”][vc_column width=”2/3″][vc_column_text]
Microsoft Defender Advanced Threat Protection is an enterprise endpoint security platform designed to help organizations to prevent, detect, investigate, and respond to advanced threats. The platform offers API endpoints through which you can manage most aspects of your MDAPT instance. In this post we will be taking a look at a simple example of how we can utilize the MDATP API in a script. As a Cybersecurity professional, using a script and API’s to automate repetitive interactions or to extend your organizations capabilities, is something that you really need in your skills “toolbox”.
For our example we will be using Python and the MDATP API to generate a report of Device Alert Events every hour. To do this we will of course need Python, the Python module XlsxWriter and the following information from MDATP:
- An Application ID & Client Secret for authentication, which you can get from Azure
- Your tenant ID
- The query we want to run
Let’s first establish our query. To do this we will simply go to the MDATP Advanced Hunting page and look at our schemas. The DeviceAlertEvents table is going to be what we’re after, and we want the results to be in a timeframe that we can set in our script. Our query will look something like the following. Note the time format, is in the form “%Y-%m-%dT%H:%M:%SZ”.
[/vc_column_text][vc_separator][vc_single_image image=”30595″ img_size=”full”][vc_empty_space][vc_column_text]Let’s start putting the script together. First, we will start off with our imports.
import datetime
import json
import time
import requests
import xlsxwriter
Then we will declare a variable that will that will denote how many minutes we want in between reports being generated. In our case this will be every hour.
runEvery = 60
We want to put everything in a loop to keep our script running continuously, and then we will use the datetime module to calculate the times between which we want our query to list results.
while True:
queryUntil = datetime.datetime.utcnow()
queryFrom = queryUntil - datetime.timedelta(minutes=runEvery)
Now we can get onto the interesting stuff. To run our query, we first need to authenticate ourselves in order to get an authentication token, with which we can access the API. This is where you will need your Application ID, Client Secret and tenant ID. Your Application ID and Client Secret are a part of app registrations, which is what apps and, in our case, scripts use to authenticate (this essentially replaces service users). If you don’t have these, then you will need to look up Azure app registrations, complete the app registration and set API permissions. Once you have your app registered, we will create two dicts that will contain the headers and the data of our POST request. For those unfamiliar with what a dict is, it is Python’s implementation of a hash table (a type of associative array), and consists of tuples (pairs) of keys and values.
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {"grant_type": "client_credentials", "client_id": "**YOUR CLEINT ID***", "scope": "https://securitycenter.microsoft.com/mtp/.default",
"client_secret": "***YOUR CLIENT SECRET***"}
The URL you need to send your request to is what you need to add you Tenant ID to. One of the advantages of the requests module is that we can parse the JSON response with the .json() method, so we can create our bearer token all in one line.
authKey = "Bearer " + \
requests.post("https://login.microsoftonline.com/***YOUR TENANT ID*** oauth2/v2.0/token",
headers=headers, data=data).json()["access_token"]
Now that we have our authentication token, we can craft our request that will actually run our query. Yet again we will create our headers, then we will add our time range to our previously written query, we will take this query and add it to the data dict and finally we can send our query on its way to MDATP.
headers = {"Content-Type": "application/json", "authorization": authKey}
query = "DeviceAlertEvents | where Timestamp between(datetime(" + \
queryFrom.strftime("%Y-%m-%dT%H:%M:%SZ") + ") .. datetime(" + queryUntil.strftime("%Y-%m-%dT%H:%M:%SZ") + "))"
data = {"Query": query}
[/vc_column_text][vc_empty_space][vc_single_image image=”30567″ img_size=”full”][vc_empty_space][vc_column_text]
result = requests.post("https://api-eu.securitycenter.microsoft.com/api/advancedqueries/run", headers=headers,
data=json.dumps(data)).json()
This is for the investigation and reporting, but if you want to create real time alerts regarding shares, you can create a policy from these labels.
To do this, create a new file policy, where you can set up the different AIP labels and the actions in the connected applications.
[/vc_column_text][vc_empty_space][vc_single_image image=”30568″ img_size=”full”][vc_empty_space][vc_column_text]As you can see from the above, it’s really easy to have another layer of protection around your organization, especially if you have AIP already set up and running. Just tick a box and new features are coming.
It’s a really nice and easy set up, but it’s a lot harder fight to ensure that, the employees are using these labels as intended and marking the documents as they are needed. It’s wise to create some trainings and supervise the users carefully in the first time, as every chain is as strong as its weakest link.
[/vc_column_text][vc_empty_space][vc_column_text]Voilà, our query has run and our response will be in JSON format and should look something like the following.[/vc_column_text][vc_empty_space][vc_single_image image=”30597″ img_size=”full”][vc_empty_space][vc_column_text]The interesting stuff is in the tuple with the key “Results”, and contains a list of our alerts.[/vc_column_text][vc_empty_space][vc_single_image image=”30598″ img_size=”full”][vc_empty_space][vc_column_text]For the purposes of our script we can just ignore the rest of the response.
result = result["Results"]
Now that we have our data, we can get onto creating our Excel report. To do this, we first need to transform our dict containing the API response into a from that will play nice with Excel. Hopefully the following visual representation adequetly describes what we are trying to do.
[/vc_column_text][vc_empty_space][vc_single_image image=”30600″ img_size=”full”][vc_empty_space][vc_column_text]
Step 1 involves merging all the dicts into one. To do this we will create a new dict, loop through the existing dicts in our response and append the values to our new dict.
mergedDict = {}
for dictionary in result:
for key, item in dictionary.items():
mergedDict.setdefault(key, []).append(item)
Now we can get onto actually creating our Excel file. For this we’ll declare some variables containing the report name (needs to be unique, each time a report is generated), the workbook instance, worksheet instance, some formatting and some counters for when we are iterating through the rows and columns.
workbookName = "Report " + queryUntil.strftime("%Y-%m-%d %H.%M") + ".xlsx"
workbook = xlsxwriter.Workbook(workbookName)
worksheet = workbook.add_worksheet()
bold = workbook.add_format({'bold': True})
row = 0
col = 0
Moving on to Step 2 of transforming our data, we will loop through each key in our dict, write it in the first row, write the values in the corresponding list under it and move onto the next column.
worksheet.write(row, col, key, bold)
for item in mergedDict[key]:
worksheet.write(row + 1, col, str(item))
row += 1
row = 0
col += 1
Now all we have to do is close the workbook and wait until our next report is needed
workbook.close()
time.sleep(60 * runEvery)
And there we go. We have now made a simple script that leverages the MDATP API and manipulates the received data. Writing scripts like this is a simple yet an incredibly important skill to have, when working with cloud-based security solutions.
[/vc_column_text][vc_empty_space][vc_single_image image=”30602″ img_size=”full”][vc_empty_space][vc_column_text]The final script:
import datetime
import json
import time
import requests
import xlsxwriter
runEvery = 60
while True:
queryUntil = datetime.datetime.utcnow()
queryFrom = queryUntil - datetime.timedelta(minutes=runEvery)
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {"grant_type": "client_credentials", "client_id": "**YOUR CLEINT ID***", "scope": "https://securitycenter.microsoft.com/mtp/.default",
"client_secret": "***YOUR CLIENT SECRET***"}
authKey = "Bearer " + \
requests.post("https://login.microsoftonline.com/***YOUR TENANT ID*** oauth2/v2.0/token",
headers=headers, data=data).json()["access_token"]
headers = {"Content-Type": "application/json", "authorization": authKey}
query = "DeviceAlertEvents | where Timestamp between(datetime(" + \
queryFrom.strftime("%Y-%m-%dT%H:%M:%SZ") + ") .. datetime(" + queryUntil.strftime("%Y-%m-%dT%H:%M:%SZ") + "))"
data = {"Query": query}
result = requests.post("https://api-eu.securitycenter.microsoft.com/api/advancedqueries/run", headers=headers,
data=json.dumps(data)).json()
result = result["Results"]
mergedDict = {}
for dictionary in result:
for key, item in dictionary.items():
mergedDict.setdefault(key, []).append(item)
workbookName = "Report " + queryUntil.strftime("%Y-%m-%d %H.%M") + ".xlsx"
workbook = xlsxwriter.Workbook(workbookName)
worksheet = workbook.add_worksheet()
bold = workbook.add_format({'bold': True})
row = 0
col = 0
for key in mergedDict:
worksheet.write(row, col, key, bold)
for item in mergedDict[key]:
worksheet.write(row + 1, col, str(item))
row += 1
row = 0
col += 1
[/vc_column_text][/vc_column][vc_column width=”1/3″][/vc_column][/vc_row]
workbook.close()
time.sleep(60 * runEvery)</code>