Network security group restricts ingress from 0.0.0.0/0 to port 22 (SSH)
Network security groups with ingress from 0.0.0.0/0 exposing SSH are identified. This includes rules that explicitly permit TCP 22, use all protocols, or define TCP port ranges that encompass 22.
Risk
Public SSH access enables Internet-wide probing, brute force, and credential stuffing that can grant shell access. Compromise allows lateral movement, data exfiltration (confidentiality), unauthorized changes or malware (integrity), and service disruption or ransomware-driven lockouts (availability).
Run this check with Prowler
Run in Prowler Cloudprowler oraclecloud --checks network_security_group_ingress_from_internet_to_ssh_portRecommendation
Enforce least privilege: limit SSH in NSG rules to trusted CIDRs or private networks. Prefer bastion access (e.g., OCI Bastion) or VPN/private connectivity over direct Internet exposure. Use key-based auth, disable PasswordAuthentication, log and monitor access, and segment workloads for defense in depth.
Remediation
CLI
oci network nsg rules remove --nsg-id <nsg-ocid> --security-rule-ids '["<rule-ocid>"]'Terraform
# Restrict SSH so it's not from 0.0.0.0/0
resource "oci_core_network_security_group_security_rule" "<example_resource_name>" {
network_security_group_id = "<example_resource_id>"
direction = "INGRESS"
protocol = "6" # TCP
source = "10.0.0.0/8" # CRITICAL: not 0.0.0.0/0; limits SSH to internal range
tcp_options {
destination_port_range {
min = 22 # CRITICAL: explicitly defines SSH port
max = 22
}
}
}Other
Check Code
"""Check if network security groups allow ingress from 0.0.0.0/0 to port 22."""
from prowler.lib.check.models import Check, Check_Report_OCI
from prowler.providers.oraclecloud.services.network.network_client import network_client
class network_security_group_ingress_from_internet_to_ssh_port(Check):
"""Check if network security groups allow ingress from 0.0.0.0/0 to port 22."""
def execute(self) -> Check_Report_OCI:
"""Execute the network_security_group_ingress_from_internet_to_ssh_port check.
Returns:
List of Check_Report_OCI objects with findings
"""
findings = []
for nsg in network_client.network_security_groups:
has_public_ssh_access = False
# Check security rules for public SSH access
for rule in nsg.security_rules:
if (
rule.get("direction") == "INGRESS"
and rule.get("source") == "0.0.0.0/0"
):
protocol = rule.get("protocol")
# Protocol 6 is TCP
if protocol == "6":
tcp_options = rule.get("tcp_options")
# If tcp_options is None, all TCP ports are allowed
if not tcp_options:
has_public_ssh_access = True
break
# If tcp_options exists, check destination port range
dst_port = tcp_options.get("destination_port_range")
if dst_port:
port_min = dst_port.get("min", 0)
port_max = dst_port.get("max", 0)
if port_min <= 22 <= port_max:
has_public_ssh_access = True
break
# If no destination port range specified, all ports are allowed
else:
has_public_ssh_access = True
break
# Protocol "all" or if protocol is not specified
elif protocol == "all" or not protocol:
has_public_ssh_access = True
break
report = Check_Report_OCI(
metadata=self.metadata(),
resource=nsg,
region=nsg.region,
resource_name=nsg.display_name,
resource_id=nsg.id,
compartment_id=nsg.compartment_id,
)
if has_public_ssh_access:
report.status = "FAIL"
report.status_extended = f"Network security group {nsg.display_name} allows ingress from 0.0.0.0/0 to port 22 (SSH)."
else:
report.status = "PASS"
report.status_extended = f"Network security group {nsg.display_name} does not allow ingress from 0.0.0.0/0 to port 22 (SSH)."
findings.append(report)
return findings