Last week a friend asked me if creating or updating a virtual machine where a public IP address was associated with was detectable. This is a very common requirement in cloud security monitoring. Having a workload (aka virtual machine) with Internet exposure is never recommended. Otherwise, that virtual machine plays a security perimeter role.
In this article, let’s see how we can trigger an alert when someone creates or updates a virtual machine that has a public IP address.
Use Case
A virtual machine with Internet exposure is always put at risk. Bad actors can try different vulnerabilities when that virtual machine is accessible from them. Once that virtual machine is compromised bad actors could scan and extract sensitive information on it and try to laterally move across your environment. It would become worse if that virtual machine had its system-assigned managed identity being granted more than just the Reader access in Azure subscription.
As a SecOps analyst you would need to monitor and get notification if someone creates or updates a virtual machine to associate a public IP Address. And this is what this article is about.
Approach
The approach is to use either Azure Monitor Alert or Microsoft Sentinel to monitor and trigger an alert. I would highly recommend you to read the following article to understand more
Detect NSG inbound rule updated to allow All
The query to use for the detection is as follows:
// Find Network Interface Card (NIC) where a Public Ip address is associated with
let NicResourceIds =
AzureActivity
| where OperationNameValue =~ “Microsoft.Network/networkInterfaces/write”
| extend publicIpResourceId = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(Properties).requestbody)).properties)).ipConfigurations))[0].properties)).publicIpAddress)).id)
| where publicIpResourceId != “”
| project _ResourceId;
// Find virtual machines that have Nic associated with
AzureActivity
| where CategoryValue == “Administrative”
| extend Action = tostring(parse_json(Authorization).action),
NicResourceId = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(Properties).responseBody)).properties)).networkProfile)).networkInterfaces))[0].id)
| where Action =~ “Microsoft.Compute/virtualMachines/write” and
ActivityStatusValue =~ ‘Accepted’ and
NicResourceId in~ (NicResourceIds)
| project TimeGenerated,
VmName=Resource,
ResourceGroup,
SubscriptionId,
CallerIpAddress,
ActivityStatusValue,
NicResourceId,
_ResourceId
Below are sample templates:
ARM Template for Azure Monitor Alert
ARM Template for Microsoft Sentinel Analytics Rule
Resource Graph Explorer
The Resource Graph Explorer is another good way to monitor and track virtual machines with Public IP Address. However, it doesn’t give you who created or updated as well as information that Azure Activity Log provides.
If you wish to perform an on-demand assessment, below is the query to find those virtual machines:
Resources
| where type =~ ‘microsoft.compute/virtualmachines’
| extend nics=array_length(properties.networkProfile.networkInterfaces)
| mvexpand nic=properties.networkProfile.networkInterfaces
| extend hostName = properties.osProfile.computerName
| where nics == 1 or nic.properties.primary =~ ‘true’ or isempty(nic)
| project vmId = id,
vmName = name,
nicId = tostring(nic.id),
hostName
| join kind=leftouter (
Resources
| where type =~ ‘microsoft.network/networkinterfaces’
| extend ipConfigsCount=array_length(properties.ipConfigurations)
| mvexpand ipconfig=properties.ipConfigurations
| extend privateIp = ipconfig.properties.privateIPAddress,
publicIpId = tostring(ipconfig.properties.publicIPAddress.id)
| where ipConfigsCount == 1 or ipconfig.properties.primary =~ ‘true’
| project nicId = id,
privateIp,
publicIpId
)
on nicId
| project-away nicId1
| summarize by vmId, vmName, tostring(hostName), nicId, publicIpId, tostring(privateIp)
| join kind=leftouter (
Resources
| where type =~ ‘microsoft.network/publicipaddresses’
| project publicIpId = id, publicIpAddress = properties.ipAddress)
on publicIpId
| where publicIpAddress != “”
| project-away publicIpId1
Read the full article here:https://azsec.azurewebsites.net/2021/12/19/detect-azure-vm-with-a-public-ip-associated/