Back to Checks
Azure public IP address is not listed in Shodan
network_public_ip_shodan
Service: networkSeverity: high
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:microsoft.network/publicipaddresses
Azure Public IP addresses are detected as indexed by Shodan, indicating Internet-visible services with open ports and service banner metadata.
Risk
Shodan-visible IPs are easy to discover and target, elevating risks to confidentiality and integrity. Adversaries can enumerate banners, probe open ports, brute-force access, and exploit known CVEs, enabling unauthorized entry, data exfiltration, and lateral movement.
Run this check with Prowler
Run in Prowler CloudRun
prowler azure --checks network_public_ip_shodanRecommendation
Minimize public exposure: prefer private endpoints or VPN/bastion, restrict ingress per least privilege (avoid 0.0.0.0/0), close unused ports, patch and harden services, and apply defense-in-depth segmentation. Continuously inventory public IPs and rotate them if sensitive banners were exposed.
Remediation
CLI
az network public-ip delete --resource-group <RESOURCE_GROUP> --name <PUBLIC_IP_NAME>Terraform
# NIC without a public IP association
resource "azurerm_network_interface" "<example_resource_name>" {
name = "<example_resource_name>"
location = "<LOCATION>"
resource_group_name = "<RESOURCE_GROUP>"
ip_configuration {
name = "ipconfig1"
subnet_id = "<example_resource_id>"
private_ip_address_allocation = "Dynamic"
# CRITICAL: Omit public_ip_address_id -> no public IP, preventing Shodan listing
}
}NativeIaC
// Remove public exposure by NOT associating a public IP
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' existing = {
name: '<example_vnet_name>/<example_subnet_name>'
}
resource nic 'Microsoft.Network/networkInterfaces@2023-11-01' = {
name: '<example_resource_name>'
location: resourceGroup().location
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
privateIPAllocationMethod: 'Dynamic'
subnet: { id: subnet.id }
// CRITICAL: No 'publicIPAddress' property -> NIC has no public IP, preventing Shodan listing
}
}
]
}
}Other
1In the Azure portal, go to Public IP addresses and select the affected IP
2Click Dissociate and confirm to remove it from the attached resource
3Click Delete to remove the Public IP from your subscription
Check Code
import shodan
from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.lib.logger import logger
from prowler.providers.azure.services.network.network_client import network_client
class network_public_ip_shodan(Check):
def execute(self):
findings = []
shodan_api_key = network_client.audit_config.get("shodan_api_key")
if shodan_api_key:
api = shodan.Shodan(shodan_api_key)
for subscription, public_ips in network_client.public_ip_addresses.items():
subscription_name = network_client.subscriptions.get(
subscription, subscription
)
for ip in public_ips:
report = Check_Report_Azure(metadata=self.metadata(), resource=ip)
report.subscription = subscription
try:
shodan_info = api.host(ip.ip_address)
report.status = "FAIL"
report.status_extended = f"Public IP {ip.ip_address} from subscription {subscription_name} ({subscription}) listed in Shodan with open ports {str(shodan_info['ports'])} and ISP {shodan_info['isp']} in {shodan_info['country_name']}. More info at https://www.shodan.io/host/{ip.ip_address}."
findings.append(report)
except shodan.APIError as error:
if "No information available for that IP" in error.value:
report.status = "PASS"
report.status_extended = f"Public IP {ip.ip_address} from subscription {subscription_name} ({subscription}) is not listed in Shodan."
findings.append(report)
continue
else:
logger.error(f"Unknown Shodan API Error: {error.value}")
else:
logger.error(
"No Shodan API Key -- Please input a Shodan API Key with -N/--shodan or in config.yaml"
)
return findings