Back to Checks
Network security group does not allow inbound RDP (TCP 3389) from the Internet
network_rdp_internet_access_restricted
Service: networkSeverity: high
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:microsoft.network/networksecuritygroups
Azure NSG inbound rules are evaluated for public RDP exposure. The finding flags rules that Allow TCP traffic to port 3389 from broad sources like 0.0.0.0/0, Internet, or *, including ranges that cover 3389.
Risk
Exposed RDP enables Internet-wide brute force and credential stuffing, risking unauthorized console access.
Compromise can cause data theft (confidentiality), tampering or malware deployment (integrity), VM lockout or disruption (availability), and lateral movement within the VNet.
Run this check with Prowler
Run in Prowler CloudRun
prowler azure --checks network_rdp_internet_access_restrictedRecommendation
Enforce least privilege for remote admin:
- Remove
Allowto3389from0.0.0.0/0 - Limit access to fixed IPs or private networks
- Prefer Azure Bastion, JIT, or VPN/ExpressRoute
- Harden auth (strong keys, MFA) and monitor
Adopt zero trust and defense in depth.
Remediation
CLI
az network nsg rule delete --resource-group <RESOURCE_GROUP> --nsg-name <example_resource_name> --name <RDP_RULE_NAME>Terraform
# NSG with RDP allowed only from a restricted CIDR (not Internet)
resource "azurerm_network_security_group" "<example_resource_name>" {
name = "<example_resource_name>"
location = "<region>"
resource_group_name = "<example_resource_name>"
security_rule {
name = "Allow-RDP-Restricted"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "3389"
destination_address_prefix = "*"
source_address_prefix = "<AUTHORIZED_CIDR>" # CRITICAL: restrict source; not "*", "Internet", or "0.0.0.0/0" so the check passes
}
}NativeIaC
// NSG with RDP allowed only from a restricted CIDR (not Internet)
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-09-01' = {
name: '<example_resource_name>'
location: '<region>'
properties: {
securityRules: [
{
name: 'Allow-RDP-Restricted'
properties: {
priority: 100
direction: 'Inbound'
access: 'Allow'
protocol: 'Tcp'
sourcePortRange: '*'
destinationPortRange: '3389'
destinationAddressPrefix: '*'
sourceAddressPrefix: '<AUTHORIZED_CIDR>' // CRITICAL: restrict source; not "Internet", "*", or "0.0.0.0/0" to pass the check
}
}
]
}
}Other
1In Azure Portal, go to Network Security Groups and open the NSG attached to the resource
2Select Inbound security rules
3Find any rule that allows TCP 3389 with Source set to Any/Internet/*/0.0.0.0/0
4Delete the rule, or edit it and set Source to a specific IP/CIDR (e.g., <AUTHORIZED_CIDR>)
5Save
Check Code
from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.network.network_client import network_client
class network_rdp_internet_access_restricted(Check):
def execute(self) -> Check_Report_Azure:
findings = []
for subscription, security_groups in network_client.security_groups.items():
subscription_name = network_client.subscriptions.get(
subscription, subscription
)
for security_group in security_groups:
report = Check_Report_Azure(
metadata=self.metadata(), resource=security_group
)
report.subscription = subscription
report.status = "PASS"
report.status_extended = f"Security Group {security_group.name} from subscription {subscription_name} ({subscription}) has RDP internet access restricted."
rule_fail_condition = any(
(
rule.destination_port_range == "3389"
or (
(
rule.destination_port_range
and "-" in rule.destination_port_range
)
and int(rule.destination_port_range.split("-")[0]) <= 3389
and int(rule.destination_port_range.split("-")[1]) >= 3389
)
)
and rule.protocol in ["TCP", "Tcp", "*"]
and rule.source_address_prefix in ["Internet", "*", "0.0.0.0/0"]
and rule.access == "Allow"
and rule.direction == "Inbound"
for rule in security_group.security_rules
)
if rule_fail_condition:
report.status = "FAIL"
report.status_extended = f"Security Group {security_group.name} from subscription {subscription_name} ({subscription}) has RDP internet access allowed."
findings.append(report)
return findingsReferences
- https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/Network/unrestricted-rdp-access.html
- https://learn.microsoft.com/en-za/answers/questions/1374791/policy-to-block-the-creation-of-nsgs-with-rules-th
- https://learn.microsoft.com/en-us/azure/security/fundamentals/network-best-practices#disable-rdpssh-access-to-azure-virtual-machines
- https://learn.microsoft.com/en-us/security/benchmark/azure/security-controls-v3-network-security#ns-1-establish-network-segmentation-boundaries