TL;DR IaCing an Azure VM and forwarding logs to Sentinel weren’t much on their own, so I’m mashing them together.
Welcome to Part XI of our Back to the Basics Series!
Part I: NTDS.dit vs SAM
Part II: Ownership Matters
Part III: Recovering from a Crash
Part IV: Setting up a Simple Honeypot Account
Part V: Automating DC Deployment
Part VI: Sometimes it’s the dumbest thing
Part VII: Merry Christmas, macros, & Base64
Part VIII: Why old 0 Days make great teaching tools
Part IX: PowerShell & PS1s without PowerShell.exe
Part X: Ownership & so called “effective permissions”
Part XI: Windows Event Forwarding & SACLs
Part XII: Poorly planned honeypots & other Bad Ideas
Part XIII: Setting up a simple honey token
Part XIV: Smartcards and Pass-the-Hash
Part XV: Forwarding logs to Sentinel & basic alerts
Part XVI: Automating VM deployments in Hyper-V
Part XVII: Migrating the lab from ESXi to Hyper-V
Part XVIII: Centrally managing Hyper-V & Live Migrations
Background
I’m in a college class on Azure and the lab environment they gave us was … funky. They also didn’t give us full access to it. Hence I’m using the free $200 credit on my own Azure account for this.
We ran through spinning up & configuring an Azure VM simply by using the Azure AD module in PowerShell.
After that we finally got around to something I’d been meaning to do for months now; forwarding our home lab’s logs to Azure so we can look at them in Microsoft Sentinel.
IaC an Azure VM
This will connect to Azure, create a Resource Group, create a VM, create a public IP address & link it to the VM, and finally allow port 80 through the NSG. By default only ports 3389 and 5985 are allowed, which of course are used by RDP and WinRM for remote management of Windows systems.
Install-Module -Name Az -Repository PSGallery -Force
Update-Module -Name Az -Force
Connect-AzAccount
Install-Module -Name PSReadline
Install-Module -Name Az.Tools.Predictor
Enable-AzPredictor -AllSession
New-AzResourceGroup -Name "Test" -Location "EastUS"
New-AzVM -ResourceGroupName "Test" -Name "TestAZ" -Location "East US" -SecurityType TrustedLaunch -Image Win2022AzureEditionCore -Size "Standard_B1s"
#Stop the VM when you're not using it, start it to run a config via PS1
Stop-AzVM -Name "TestAZ" -ResourceGroupName "Test"
Start-AzVM -Name "TestAZ" -ResourceGroupName "Test"
#Create a public IP
New-AzPublicIpAddress -Name "TestPublicIP" -ResourceGroupName "Test" -AllocationMethod Static -Location "EastUS"
#Get the VM's NIC
#$TestAZNIC = (Get-AzVM -Name TestAZ -ResourceGroupName Test).NetworkProfile.NetworkInterfaces
$NIC = Get-AzNetworkInterface -Name "TestAZ" -ResourceGroupName "Test"
$vnet = Get-AzVirtualNetwork -Name "TestAZ" -ResourceGroupName "Test"
$subnet = Get-AzVirtualNetworkSubnetConfig -Name "TestAZ" -VirtualNetwork $vnet
$TestAZIP = Get-AzPublicIpAddress -Name TestPublicIP
#$NIC | Set-AzNetworkInterfaceIpConfig -Name "TestIPConfig" -PublicIPAddress $TestAZIP -Subnet $subnet
$NIC | Set-AzNetworkInterfaceIpConfig -Name "TestAZ" -PublicIPAddress $TestAZIP -Subnet $subnet
$NIC | Set-AzNetworkInterface
#Set the NSG to allow port 80
$RGname="Test"
$port=80
$rulename="allowAppPort$port"
$nsgname="TestAZ"
# Get the NSG resource
$nsg = Get-AzNetworkSecurityGroup -Name $nsgname -ResourceGroupName $RGname
# Add the inbound security rule.
$nsg | Add-AzNetworkSecurityRuleConfig -Name $rulename -Description "Allow app port" -Access Allow `
-Protocol * -Direction Inbound -Priority 3891 -SourceAddressPrefix "*" -SourcePortRange * `
-DestinationAddressPrefix * -DestinationPortRange $port
# Update the NSG.
$nsg | Set-AzNetworkSecurityGroup
#Random stuff just for the class
#Create an Azure Key Vault
New-AzKeyVault -Name "MiskyKeyVault" -ResourceGroupName "Test" -Location "East US"
#Create a new recovery vault
New-AzRecoveryServicesVault -Name "MishkyRecoveryVault" -ResourceGroupName "Test" -Location "East US"
#Create a storage account
Register-AzResourceProvider –ProviderNamespace Microsoft.Storage
New-AzStorageAccount -Name "mishkyblobstorage" -ResourceGroupName "Test" -Location "East US" -AccessTier Hot -Kind BlobStorage -SkuName Standard_LRS
#Register for Microsoft.Insights to run queries on Key Vault logs
Register-AzResourceProvider –ProviderNamespace Microsoft.Insights
#Azure proves a simple way to configure VMs as one can simply run a PS1 that stored locally:
#Run commands & PS1s on Azure VMs
Set-Location ".\WGU\Cloud Security"
Invoke-AzVMRunCommand -VMName "TestAZ" -ResourceGroupName "Test" -CommandId "RunPowerShellScript" -ScriptPath ".\Test.ps1"
There’s more commands than ‘RunPowerShellScript’ one can do:
+----------------------+---------------------------------------------+
| Name | Description |
+----------------------+---------------------------------------------+
| RunPowerShellScript | Executes a PowerShell script |
| DisableNLA | Disable Network Level Authentication |
| DisableWindowsUpdate | Disable Windows Update Automatic Updates |
| EnableAdminAccount | Enable administrator account |
| EnableEMS | Enable EMS |
| EnableRemotePS | Enable remote PowerShell |
| EnableWindowsUpdate | Enable Windows Update Automatic Updates |
| IPConfig | List IP configuration |
| RDPSettings | Verify RDP Listener Settings |
| ResetRDPCert | Restore RDP Authentication mode to defaults |
| SetRDPPort | Set Remote Desktop port |
+----------------------+---------------------------------------------+
For example one could run
Invoke-AzVMRunCommand -VMName "TestAZ" -ResourceGroupName "Test" -CommandId "DisableNLA"
If NLA is enabled on the VM and stopping you from RDPing in.
Test.ps1 contains the below:
Get-Date | Out-File C:\Users\Mishky\Desktop\test.txt -Append
whoami | Out-File C:\Users\Mishky\Desktop\test.txt -Append
hostname | Out-File C:\Users\Mishky\Desktop\test.txt -Append
Install-WindowsFeature -name Web-Server -IncludeManagementTools
Move-Item "C:\inetpub\wwwroot\iisstart.png" -Destination "C:\inetpub\wwwroot\iisstart.png.bak"
Invoke-WebRequest "https://static.vecteezy.com/system/resources/previews/019/152/779/original/unicorn-graphic-clipart-dedsign-free-png.png" -OutFile "C:\inetpub\wwwroot\iisstart.png"
$File = "C:\inetpub\wwwroot\iisstart.htm"
$LineNumber = 3
$TextToAdd = "<p>Welcome to Mishky's unicorn Azure VM!</p>"
$fileContent = Get-Content $File
$fileContent[$LineNumber-1] += $TextToAdd
$fileContent | Set-Content $File
I just wanted to confirm everything was working and the webserver was reachable.
One can RDP into the VM via:
mstsc /v: $TestAZIP.IpAddress
One can view the website via:
$MishkyIP = $TestAZIP.IpAddress
$MishkyPage = "http://$MishkyIP"
Start-Process MSEdge $MishkyPage
Mishka was amused.
Clean up
It costs money to keep VMs and public IPs around in Azure, so we removed them afterwards.
#Remove the Public IP, VM, and VM disk afterwards
#Detach the public IP
$TestAZIP = Get-AzPublicIpAddress -Name TestPublicIP
$NIC = Get-AzNetworkInterface -Name "TestAZ" -ResourceGroupName "Test"
$vnet = Get-AzVirtualNetwork -Name "TestAZ" -ResourceGroupName "Test"
$subnet = Get-AzVirtualNetworkSubnetConfig -Name "TestAZ" -VirtualNetwork $vnet
$NIC | Set-AzNetworkInterfaceIpConfig -Name "TestAZ" -PublicIPAddress $null -Subnet $subnet
$NIC | Set-AzNetworkInterface
Remove-AzPublicIpAddress -Name "TestPublicIP" -ResourceGroupName Test
Remove-AzVM -Name "TestAZ" -ResourceGroupName Test
Get-AzDisk -ResourceGroupName TestAZ | Remove-AzDisk -Force
Setup log forwarding & Sentinel
This was actually really straightforward. This guide was very helpful as well.
We had previously setup Windows Event Forwarding here. Hence all that was required for Sentinel was
- Setup Azure Arc on TestWEC
- Create a Log Analytics Workspace in Azure
- Deploy Sentinel
- Add the “Windows Forwarded Events” connector to Sentinel
The linked guide already does a great job showing how to set everything up on Azure, so I won’t re-invent the wheel here. Once it’s complete you will see the logs in Azure.
Test it out
I set an alert in Sentinel to trigger on over 100 failed logins in one hour. Just make sure that you are logging failed logins in Group Policy. This is located under
Computer Configuration \ Windows Settings \ Security Settings \ Advanced Audit Policy Configuration \ Audit Policies \ Logon/Logoff -> Set to ‘Configure the following audit events: Success & Failure’
Please note that this will generate Event ID 4625. If you want to verify that failed logins are getting logged then just run this query on your Windows Event Collector (TestWEC in our case):
Get-WinEvent -Path “$env:SystemRoot\System32\Winevt\Logs\ForwardedEvents.evtx” | Where-Object {($_.Id -eq “4625”) -and ($_.TimeCreated -gt (Get-Date).AddHours(-1))}
I then caused the alert to trigger by jumping on our Kali VM and running a brute force attack on the builtin Administrator account.
#crackmapexec
crackmapexec smb 192.168.0.101 -u Administrator -p /home/kali/Downloads/Wordlists/rockyou.txt
#Metasploit
msfconsole
use auxiliary/scanner/smb/smb_login
set RHOST 192.168.0.104
set PASS_FILE /home/kali/Downloads/Wordlists/rockyou.txt
set SMBUser Administrator
set SMBDomain test.local
run
Within minutes Miska got an email alert.
I’m not much of a SIEM Guy, so this is pretty primative. I just wanted to make sure everything worked and could generate alerts. I had been meaning to setup log forwarding to Sentinel for awhile and we finally got around to it.
We went over some things you might want to check logs for and how to check here, how to setup a simple honey token and an alert if anyone accesses it here, and how to setup a honey account that would alert if someone password sprayed here. Those howtos were all done in PowerShell on premise however. We have much to learn still regarding Sentinel. If anyone has good tips & tricks on utilizing Sentinel then please feel fee to put them in the comments!
Summary
I have to finish up the paper for this college class, but Azure has helped quite a bit already. Microsoft helpfully suggests utilizing their builtin capabilities to vulnerability scan your VMs, using Defender to help protect them, deploying a Firewall on your virtual network, deploying health monitoring, leveraging Azure’s backup feature, and so on. These are all good suggestions for the fictional organization in the college assignment. I have been researching them and including them in the suggested course of action.
I just hate college style writing, so it’s been slow going.
References
Steps to deploy Sentinel: https://techcommunity.microsoft.com/t5/core-infrastructure-and-security/forward-on-premises-windows-security-event-logs-to-microsoft/ba-p/3040784
Add a server to Azure Arc: https://portal.azure.com/#view/Microsoft_Azure_HybridCompute/ArcServerCreate.ReactView
Install Azure PowerShell & Connect-AzAccount: https://learn.microsoft.com/en-us/powershell/azure/install-azps-windows?view=azps-11.1.0&tabs=powershell&pivots=windows-psgallery
Add a public IP to AZ VM: https://learn.microsoft.com/en-us/azure/virtual-network/ip-services/associate-public-ip-address-vm?tabs=azure-powershell
Allow a port in NSG: https://learn.microsoft.com/en-us/azure/service-fabric/scripts/service-fabric-powershell-add-nsg-rule
Azure Key Vaults: https://learn.microsoft.com/en-us/azure/key-vault/general/quick-create-powershell
Event Id 4625: https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4625
Querying by date/time, PowerShell: https://devblogs.microsoft.com/scripting/adding-and-subtracting-dates-with-powershell/
Querying by date/time, Sentinel: https://learn.microsoft.com/en-us/azure/sentinel/audit-sentinel-data
Customize Sentinel alerts: https://learn.microsoft.com/en-us/azure/sentinel/customize-alert-details
Easily create ASCII tables: https://ozh.github.io/ascii-tables/