Skip to content

Instantly share code, notes, and snippets.

@omarmciver
Last active September 16, 2021 22:25
Show Gist options
  • Save omarmciver/8752a6e6048a7445bfea1ddfdf85c4c2 to your computer and use it in GitHub Desktop.
Save omarmciver/8752a6e6048a7445bfea1ddfdf85c4c2 to your computer and use it in GitHub Desktop.
Find Azure Linux Agent OMI Open Ports (CVE-2021-38647)
# Omar McIver
# September 16th 2021
# Subject: Open Management Infrastructure Remote Code Execution Vulnerability (CVE-2021-38647)
# Ref: https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-38647
#######################
# This script will visit each of your Linux VMs and use a run-command to cat the omiserver.conf file and then grep for "port="
# This will return you the httpport=XXX and httpsport=XXX settings. If these are non-Zero then you need to get your OMI agent patched to secure against the vulnerability.
#######################
# We will process the VMs in batches that run as Parrallel Powershell Jobs.
# Don't set this too high as the Ptyhon script behind the az cli can use a lot more memory than you think!!
$pageRequestSize = 10
# If we want to skip an initial number of query results, set that here... (like if your network connection dies and you have to start again, you can resume).
$skipCount = 0
# Define and execute the initial Resource Graph query to get non AKS Linux VMs
$query = "where (type == 'microsoft.compute/virtualmachines' and properties.storageProfile.osDisk.osType == 'Linux' and name !startswith 'aks-') | order by name asc"
$vms = az graph query --graph-query $query --first $pageRequestSize --skip $skipCount | ConvertFrom-Json
# Set some counters
$currentPageSize = $vms.count
$counter = $skipCount
$totalCount = $vms.total_records
# This is the script block that will be executed as a Job for each VM
# It is a run-command that cat's the omiserver.conf file and then greps for port=, which should get you httpport=XXX and httpsport=XXX
$scriptBlock = {
param($sub, $rg, $name)
az vm run-command invoke --subscription $sub -g $rg -n $name --command-id RunShellScript --scripts "sudo cat /etc/opt/omi/conf/omiserver.conf | grep port="
}
# Do > While we have records to process....
do {
# Define an array to store the Jobs in...
$jobs = @()
# Provide some user feedback on page progress...
Write-Output "Processing records $counter to $($counter+$currentPageSize) out of $totalCount..."
# For each VM on this result page, write out it's name, create a Job to execute the config file check, and add to the Jobs array.
foreach ($v in $vms.data) {
Write-Output $v.name
$jobs += Start-Job -ScriptBlock $scriptBlock -Name $v.name -ArgumentList $v.subscriptionId, $v.resourceGroup, $v.name
}
# Assuming we did create Jobs (should you add in some criteria to skip certain VMs above), let's wait until all those Jobs have completed.
if ($jobs.Length -gt 0) {
Wait-Job -Job $jobs #| Out-Null
}
# Revisit each VM on this results page and Recieve the Job result.
foreach ($v in $vms.data) {
# Parse the result message from the run-command. This will include the [stdout] and [stderr]. We only care about those lines we grepped.
# WARNING!: This script does not handle errors from the Job execution, so it is possible this result object processing could thrown an error.
# The lazy way to address this is to check the script after running for any errors
$result = ((Receive-Job -Name $v.name) | ConvertFrom-Json).value[0].message -split '\r?\n'
foreach ($line in $result) {
if ($line.Contains('port=')) {
$output = "$($v.name),$line"
Add-Content -Path .\omiportsfound.csv -Value $output -PassThru
}
}
}
# We're done with this page of results, so increment counters and enecute the next Resource Graph page query.
$counter += $currentPageSize
$vms = az graph query --graph-query $query --first $pageRequestSize --skip $counter | ConvertFrom-Json
$currentPageSize = $vms.count
# WARNING: There is a risk that while waiting for the Jobs to process, the Resource Graph query results may have changed, meaning you could miss some VMs.
# If this is an issue for you, re-write this script to first parse out all VM names, subscriptions and RGs - and process the run command AFTER getting a complete
# picture of the VM inventory.
} while ($currentPageSize -gt 0)
# Have fun! :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment