# Azure NSG Open to Internet

> Flags NSGs with inbound allow rules from 0.0.0.0/0; critical when SSH 22 or RDP 3389 is exposed, high for other ports.

Source: https://zop.dev/integrations/azure/recommendations/azure-nsg-open-to-internet

---

## What an any-source rule really opens

A network security group filters traffic to subnets and network interfaces by rules processed
in priority order, from 100 to 4096, with Azure's default rules at 65000 and above. In the
[NSG rule reference](https://learn.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview),
`0.0.0.0/0` in the source column represents all IP addresses. An inbound allow rule with that
source hands the port to every scanner on the internet.

On a management port the consequence is immediate: SSH and RDP are the first services
automated brute-force tools try. On a data port such as SQL Server 1433, MongoDB 27017 or Redis
6379, the database is one weak password or unpatched flaw from exposure.

## Listing internet-facing inbound rules

```bash
az network nsg rule list --resource-group my-rg --nsg-name my-nsg \
  --query "[?direction=='Inbound' && access=='Allow' && (sourceAddressPrefix=='*' || sourceAddressPrefix=='0.0.0.0/0' || sourceAddressPrefix=='Internet')].{name:name, port:destinationPortRange, priority:priority}" \
  -o table
```

Rules that use `sourceAddressPrefixes` (plural) or ranges of ports need a second look, since
the query above checks only the single-value fields.

## Two severities from one check

ZopNight derives two exposure signals from the NSG's inbound rules when it inventories the
NSG. If a
management port (SSH 22, RDP 3389 or another administrative port) is reachable from any source,
the finding is raised at critical severity. If only other ports are open to any source, it is
raised at high. A management-port exposure is reported once, at critical, not twice.

## When no finding appears

A signal counts only when it is explicitly true. If the exposure analysis is missing for an NSG, ZopNight
raises nothing rather than assume the worst, and a customer tag claiming the NSG is open is not
enough on its own to trigger a finding. An NSG whose inbound allow rules all name specific source ranges does not trigger it.

## An attack surface, not an invoice

There is no saving on this finding. The exposure is direct: remote code execution and lateral
movement on management ports, data theft on database ports.

## Narrowing the rules without locking yourself out

1. Set up another way in first: [Azure Bastion](https://learn.microsoft.com/en-us/azure/bastion/bastion-overview)
   gives RDP and SSH over TLS on port 443 without exposing the VM's own ports, and
   <a href="https://zop.dev/integrations/azure/recommendations/azure-vm-jit-access-not-enabled">just-in-time VM access</a>
   opens a port only on request and only for a set time.
2. Restrict each rule's source to known ranges:
   `az network nsg rule update --resource-group my-rg --nsg-name my-nsg --name allow-ssh --source-address-prefixes 203.0.113.0/24`.
3. Delete management-port rules that Bastion or JIT now replaces with `az network nsg rule delete`.
4. For data services, prefer Private Link or service endpoints over any public rule.

**Warning**
Changing or deleting an inbound rule takes effect immediately. Confirm your alternative
access path works before removing the rule you are connected through.
