IaaS security groups do not allow unrestricted database access
Security groups should not allow unrestricted access to database ports from the public internet (0.0.0.0/0 or ::/0). This includes MySQL (3306), PostgreSQL (5432), MongoDB (27017), Redis (6379), SQL Server (1433), and CouchDB (5984). Unrestricted database access can lead to data breaches and unauthorized access.
Risk
Allowing unrestricted database access from the internet exposes sensitive data to potential breaches, unauthorized access, data exfiltration, and malicious attacks. Databases often contain critical business data and should never be directly accessible from the public internet.
Run this check with Prowler
Run in Prowler Cloudprowler stackit --checks iaas_security_group_database_unrestrictedRecommendation
Restrict database access to specific application servers or trusted IP ranges. Use private networks for database connectivity and implement additional security layers such as VPNs, private endpoints, or application-level authentication.
Remediation
Other
Check Code
from prowler.lib.check.models import Check, CheckReportStackIT
from prowler.providers.stackit.services.iaas.iaas_client import iaas_client
# Database ports to check
DATABASE_PORTS = {
3306: "MySQL",
5432: "PostgreSQL",
27017: "MongoDB",
6379: "Redis",
1433: "SQL Server",
5984: "CouchDB",
}
class iaas_security_group_database_unrestricted(Check):
"""
Check if IaaS security groups allow unrestricted database access.
This check verifies that security groups do not allow database ports
(MySQL, PostgreSQL, MongoDB, Redis, SQL Server, CouchDB) access
from the public internet (0.0.0.0/0 or ::/0).
"""
def execute(self):
"""
Execute the check for all security groups in the StackIT project.
Returns:
list: A list of CheckReportStackIT findings
"""
findings = []
for security_group in iaas_client.security_groups:
if not (iaas_client.scan_unused_services or security_group.in_use):
continue
exposed_databases = set()
exposing_rule = None
# Check each ingress rule
for rule in security_group.rules:
# Only check ingress TCP rules that are unrestricted
if rule.is_ingress() and rule.is_tcp() and rule.is_unrestricted():
# Check if rule allows any database ports
for port, db_name in DATABASE_PORTS.items():
if rule.includes_port(port):
exposed_databases.add(f"{db_name} (port {port})")
# Track the first exposing rule for the message
if exposed_databases and not exposing_rule:
exposing_rule = rule
# Create a finding report for this security group
report = CheckReportStackIT(
metadata=self.metadata(),
resource=security_group,
)
if exposed_databases:
report.status = "FAIL"
databases_list = ", ".join(sorted(exposed_databases))
report.status_extended = (
f"Security group {security_group.name} allows unrestricted database access "
f"to: {databases_list} from {exposing_rule.get_ip_range_display()} via rule {exposing_rule.get_rule_display_name()}."
)
else:
report.status = "PASS"
report.status_extended = f"Security group {security_group.name} does not allow unrestricted database access."
report.resource_id = security_group.id
report.resource_name = security_group.name
report.location = security_group.region
findings.append(report)
return findings