SIEM With Azure Sentinal
Description
This is a project done on mapping failed event login attempts(or a bruteforce attempts) on a windows machine which is open to the internet. we either turn firewall off or put ICMP requests to allow. After catching the logs, we run a powershell script inside the machine and by using Workspace Analytics, Log Analytics, Cloud Defender and Azure Sentinal; we pull these log out and maps it to the worldmap and see how many attempts have generated from all around the world
Languages and Utilities Used
- PowerShell - Microsoft Azure - Azure Sentinal, Workspace Analytics and Virtual Machine
Environments Used
- Windows 10 (21H2) - Azure
Procedure:
- Creating a VM in Azure – open to attackers, (disable firewall/enable icmp to be accessed to ping req)
- Add the powershell script to the VM and run in powershell ise
# Get API key from here: https://ipgeolocation.io/
$API_KEY = "d4600b4efdef42b39828f5155041a457"
$LOGFILE_NAME = "failed_rdp.log"
$LOGFILE_PATH = "C:\ProgramData\$($LOGFILE_NAME)"
# This filter will be used to filter failed RDP events from Windows Event Viewer
$XMLFilter = @'
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[System[(EventID='4625')]]
</Select>
</Query>
</QueryList>
'@
<#
This function creates a bunch of sample log files that will be used to train the
Extract feature in Log Analytics workspace. If you don't have enough log files to
"train" it, it will fail to extract certain fields for some reason -_-.
We can avoid including these fake records on our map by filtering out all logs with
a destination host of "samplehost"
#>
Function write-Sample-Log() {
"latitude:47.91542,longitude:-120.60306,destinationhost:samplehost,username:fakeuser,sourcehost:24.16.97.222,state:Washington,country:United States,label:United States - 24.16.97.222,timestamp:2021-10-26 03:28:29" | Out-File $LOGFILE_PATH -Append -Encoding utf8
}
# This block of code will create the log file if it doesn't already exist
if ((Test-Path $LOGFILE_PATH) -eq $false) {
New-Item -ItemType File -Path $LOGFILE_PATH
write-Sample-Log
}
# Infinite Loop that keeps checking the Event Viewer logs.
while ($true)
{
Start-Sleep -Seconds 1
# This retrieves events from Windows EVent Viewer based on the filter
$events = Get-WinEvent -FilterXml $XMLFilter -ErrorAction SilentlyContinue
if ($Error) {
#Write-Host "No Failed Logons found. Re-run script when a login has failed."
}
# Step through each event collected, get geolocation
# for the IP Address, and add new events to the custom log
foreach ($event in $events) {
# $event.properties[19] is the source IP address of the failed logon
# This if-statement will proceed if the IP address exists (>= 5 is arbitrary, just saying if it's not empty)
if ($event.properties[19].Value.Length -ge 5) {
# Pick out fields from the event. These will be inserted into our new custom log
$timestamp = $event.TimeCreated
$year = $event.TimeCreated.Year
$month = $event.TimeCreated.Month
if ("$($event.TimeCreated.Month)".Length -eq 1) {
$month = "0$($event.TimeCreated.Month)"
}
$day = $event.TimeCreated.Day
if ("$($event.TimeCreated.Day)".Length -eq 1) {
$day = "0$($event.TimeCreated.Day)"
}
$hour = $event.TimeCreated.Hour
if ("$($event.TimeCreated.Hour)".Length -eq 1) {
$hour = "0$($event.TimeCreated.Hour)"
}
$minute = $event.TimeCreated.Minute
if ("$($event.TimeCreated.Minute)".Length -eq 1) {
$minute = "0$($event.TimeCreated.Minute)"
}
$second = $event.TimeCreated.Second
if ("$($event.TimeCreated.Second)".Length -eq 1) {
$second = "0$($event.TimeCreated.Second)"
}
$timestamp = "$($year)-$($month)-$($day) $($hour):$($minute):$($second)"
$eventId = $event.Id
$destinationHost = $event.MachineName# Workstation Name (Destination)
$username = $event.properties[5].Value # Account Name (Attempted Logon)
$sourceHost = $event.properties[11].Value # Workstation Name (Source)
$sourceIp = $event.properties[19].Value # IP Address
# Get the current contents of the Log file!
$log_contents = Get-Content -Path $LOGFILE_PATH
# Do not write to the log file if the log already exists.
if (-Not ($log_contents -match "$($timestamp)") -or ($log_contents.Length -eq 0)) {
# Announce the gathering of geolocation data and pause for a second as to not rate-limit the API
#Write-Host "Getting Latitude and Longitude from IP Address and writing to log" -ForegroundColor Yellow -BackgroundColor Black
Start-Sleep -Seconds 1
# Make web request to the geolocation API
# For more info: https://ipgeolocation.io/documentation/ip-geolocation-api.html
$API_ENDPOINT = "https://api.ipgeolocation.io/ipgeo?apiKey=$($API_KEY)&ip=$($sourceIp)"
$response = Invoke-WebRequest -UseBasicParsing -Uri $API_ENDPOINT
# Pull Data from the API response, and store them in variables
$responseData = $response.Content | ConvertFrom-Json
$latitude = $responseData.latitude
$longitude = $responseData.longitude
$state_prov = $responseData.state_prov
if ($state_prov -eq "") { $state_prov = "null" }
$country = $responseData.country_name
if ($country -eq "") {$country -eq "null"}
# Write all gathered data to the custom log file. It will look something like this:
#
"latitude:$($latitude),longitude:$($longitude),destinationhost:$($destinationHost),username:$($username),sourcehost:$($sourceIp),state:$($state_prov), country:$($country),label:$($country) - $($sourceIp),timestamp:$($timestamp)" | Out-File $LOGFILE_PATH -Append -Encoding utf8
Write-Host -BackgroundColor Black -ForegroundColor Magenta "latitude:$($latitude),longitude:$($longitude),destinationhost:$($destinationHost),username:$($username),sourcehost:$($sourceIp),state:$($state_prov),label:$($country) - $($sourceIp),timestamp:$($timestamp)"
}
else {
# Entry already exists in custom log file. Do nothing, optionally, remove the # from the line below for output
# Write-Host "Event already exists in the custom log. Skipping." -ForegroundColor Gray -BackgroundColor Black
}
}
}
}
- Create a Log Analytics workspace and add the VM to that so that it can ingest the logs from it
- We use the IP from the failed login and programmatically (using PowerShell) maps out the country, place from IP geolocation
- Create an Azure Sentinel (SIEM) - Microsoft cloud native SIEM—and it create a map that maps all the different attacker data
Process Walkthrough:
- Created a new resource group named HoneyPots in Azure
- Created a Workspace analytics with the same resource group
- Go to cloud security center and turn on defender and put all events to data collection
- Connect VM to log analytics workspace
-Setting up sentinel – (Sentinal helps to visualize the attack data) Select the required log analytics workspace in sentinel Select the required log analytics workspace in sentinel Start the VM and login using SSH or RDP In this project we are using audit logs from windows event viewer
- Go to Event Viewer> Windows Logs> Security Create a custom log inside log analytics workspace to insert our custom log into log analytics and add the created log file as sample and put the file path in the VM under collection path
Run a Smple query of the custom log and wait for it to reflect (Might take more than 15 minutes)
Add extra fields like Langitude, Longitude etc.. from the log by rightclicking one sample
Right click on field value of the log and add field titles
Check all the fields and save extraction (This is the use of sample log)
If highlighted incorrectly, modify each target and extraxt value
Custom Field Values
After setting up do a failed login and test whether the log is coming in and sorting itself out
Setting Up Sentinel for Geo mapping:
Go to workbooks inside Microsoft Sentinal
Edit and remove the existing template and click add on the new workbook
Click on add query and run it
We would be able to see the logs coming in
Click visualization and select Map
On Map settings select the appropriate custom field values in Lattitude, Longitude, Country and so on
Click appy and wait for some hours, we would be able to see the Brute force Attacks being mapped in the World Map