Skip to main content
Back to the Azure Footguns Database
SecurityCriticalCommonAZF-0097

RDP, SSH, or a database port open to the internet: the misconfiguration bots find in minutes

An NSG inbound Allow rule from 0.0.0.0/0 on RDP, SSH, or a database port is the most exploited misconfiguration class in Azure. Automated scanners find it in minutes, not weeks.

Footgun ID
AZF-0097 (Azure Footgun No. 97)
Azure service
Azure Network Security Groups
Resource type
Microsoft.Network/networkSecurityGroups
Updated
July 9, 2026

What it is

A Network Security Group with an inbound Allow rule from the whole internet (*, 0.0.0.0/0, or the Internet service tag) on an admin or database port: RDP (3389), SSH (22), a database engine (SQL Server 1433, MySQL 3306, PostgreSQL 5432, Redis 6379, MongoDB 27017, Elasticsearch 9200, and friends), or a management protocol like WinRM or SMB. These are the ports internet-wide scanners probe continuously, and the protocols behind them authenticate with passwords or nothing at all: no Entra ID, no MFA, no conditional access. This is the specific, critical tier of the broader any-source NSG problem (AZF-0006 covers the generic pattern).

Impact (security)
Brute-force and known-CVE exposure on identity-less protocols; internet-wide scanners find a newly opened port within minutes
Basis: Azure behavior (authored assessment). Figures are estimates, not measurements.

Why it happens

The paths into this state are all mundane. The portal's VM-create flow offers "Allow selected ports" for RDP and SSH, and taking it opens the port from any source, with only a small warning. A vendor needs database access "for the migration weekend", so 1433 gets opened and the weekend never ends. Someone can't get a connection working, widens the rule to * to rule out networking, and it works, so it ships.

The exposure also hides well. A rule doesn't have to say 3389 to open RDP: a port range like 1400-1500 quietly covers SQL Server's 1433, a comma list buries the sensitive port in the middle, and a * destination covers everything. Subnet-level NSGs make it worse by inheritance, since a permissive rule applies to every VM dropped into that subnet later. Eyeballing rule lists doesn't catch this; the port arithmetic has to actually be evaluated.

What it costs / blast radius

This is a blast radius, not a bill. A newly exposed RDP or SSH port starts receiving automated login attempts within minutes of appearing, because scanning the entire IPv4 space for these ports is cheap and continuous. From there the attacks are brute force and credential stuffing against protocols with no MFA, plus known CVEs (RDP has had wormable, pre-auth remote-code-execution vulnerabilities). Database ports are worse: Redis and Memcached historically ship with no authentication at all, and internet-exposed MongoDB instances have been mass-wiped for ransom repeatedly. (Azure behavior and public attack history; authored assessment.) The blast radius is the machine, its data, and everything reachable from it on a flat network.

See it

Footgun: admin and database ports open to the entire internet, one obvious and one hidden
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-09-01' = {
  name: 'nsg-app'
  location: location
  properties: {
    securityRules: [
      {
        name: 'allow-rdp'                    // "temporary", two years ago
        properties: {
          priority: 100
          direction: 'Inbound'
          access: 'Allow'
          protocol: 'Tcp'
          sourceAddressPrefix: '*'           // the entire internet
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '3389'       // RDP
        }
      }
      {
        name: 'allow-vendor-range'
        properties: {
          priority: 110
          direction: 'Inbound'
          access: 'Allow'
          protocol: 'Tcp'
          sourceAddressPrefix: 'Internet'    // same exposure, different spelling
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '1400-1500'  // quietly covers SQL Server (1433)
        }
      }
    ]
  }
}
Fix: delete the rules and reach machines through Bastion; databases get private endpoints, not ports
// 1) Remove every inbound Allow from the internet on admin/DB ports.
//    Don't scope it to an office IP "for now" (see AZF-0094) — take the
//    port off the internet entirely.

// 2) RDP/SSH goes through Azure Bastion: TLS, Entra ID sign-in, audit
//    trail, and zero public ports on the VMs themselves.
resource bastion 'Microsoft.Network/bastionHosts@2023-09-01' = {
  name: 'bas-prod'
  location: location
  sku: { name: 'Standard' }
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig'
        properties: {
          subnet: { id: bastionSubnet.id }   // the AzureBastionSubnet
          publicIPAddress: { id: bastionPip.id }
        }
      }
    ]
  }
}

// 3) Databases are never internet-facing: private endpoints inside the
//    VNet, or at minimum the service firewall with public access off.

How StratoLens helps

StratoLens evaluates every NSG rule across every subscription, does the port arithmetic (ranges, comma lists, and * included), and flags internet-facing admin and database ports as critical findings inside your own tenant. Its change history shows the day the "temporary" rule appeared, so exposure gets caught as a finding, not as an incident.

Start Your 28-Day Free Trial

Every feature unlocked. Deploys to your Azure tenant. No data leaves your tenant.

Available now on the Azure Marketplace.

Not ready to install anything? Browse the Azure Footguns Database: 55+ documented ways Azure quietly costs money or creates risk.

Request a demo

StratoLens catches the cost waste, access risk, and config drift across your whole Azure estate, from inside your own tenant, so your data never leaves it.