Skip to main content
emnode
Compliance Low severity

AWS Security Hub · RDS

RDS.23: RDS runs on a well-known default port

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub RDS.23 check?

RDS.23 checks whether an RDS instance (resource type AWS::RDS::DBInstance) listens on its engine's well-known default port: 3306 for MySQL/MariaDB, 5432 for PostgreSQL, 1433 for SQL Server, 1521 for Oracle. It reports FAILED for any instance still on the factory default. This control doesn't apply to RDS instances that are part of a cluster.

Why does RDS.23 matter?

Changing a port is not encryption or isolation; it is a single layer of friction. But at internet scale that friction matters: automated botnets sweep IPv4 looking for 3306, not 53306, and most move on the moment the default fails. An attacker who finds your endpoint will try the engine default first because it is right the overwhelming majority of the time. A non-standard port removes that free first guess.

How do I fix RDS.23?

  1. Inventory instances still on the engine default port.
  2. Pick a non-standard port and apply it with modify-db-instance --db-port-number (this triggers a restart, so schedule a maintenance window).
  3. Update every client in lockstep (connection strings in Secrets Manager, IaC, and Lambda environment variables), then roll out in stages to avoid connection outages.
  4. Bake the non-default port into provisioning templates so new instances inherit it.

Remediation script · bash

# Revoke an over-open admin rule, covering both IPv4 and IPv6 in one call.
aws ec2 revoke-security-group-ingress --group-id sg-0a1b2c3d \
  --ip-permissions 'IpProtocol=tcp,FromPort=22,ToPort=22,IpRanges=[{CidrIp=0.0.0.0/0}],Ipv6Ranges=[{CidrIpv6=::/0}]'

# Where access is genuinely needed, re-add it scoped to a source security group, not a CIDR.
aws ec2 authorize-security-group-ingress --group-id sg-0a1b2c3d \
  --ip-permissions 'IpProtocol=tcp,FromPort=6379,ToPort=6379,UserIdGroupPairs=[{GroupId=sg-0app1234,Description=app-tier}]'

# Strip a default security group to empty by feeding its current rules back into revoke.
INGRESS=$(aws ec2 describe-security-groups --group-ids sg-0default01 \
  --query 'SecurityGroups[0].IpPermissions')
[ "$INGRESS" != "[]" ] && aws ec2 revoke-security-group-ingress \
  --group-id sg-0default01 --ip-permissions "$INGRESS"

Full walkthrough (console steps, edge cases and verification) in the lesson Harden security groups and restrict ingress.

Is RDS.23 a false positive?

Plenty of teams run a managed third-party or vendor product whose driver, agent, or appliance hard-codes the engine default port and offers no way to change it: a packaged monitoring tool, a legacy ERP, or a SaaS connector that only speaks 3306 or 5432. Forcing a non-default port there breaks the integration for a control that is only a thin layer of obscurity to begin with, especially on an instance that is already private and tightly scoped by security group. When the endpoint isn't internet-reachable and the port is dictated by a client you don't control, suppress RDS.23 with a documented exception recording the dependency rather than chasing a connection outage.

Part of the learning path Lock down access
  • RDS.1 An RDS snapshot is shared publicly
  • RDS.2 An RDS instance is publicly accessible from the internet
  • RDS.3 RDS DB instances should be encrypted at rest
  • RDS.4 RDS snapshots should be encrypted at rest
  • RDS.5 RDS DB instances should use multiple AZs
  • RDS.6 RDS lacks enhanced monitoring
  • RDS.7 RDS clusters should have deletion protection
  • RDS.8 RDS DB instances should have deletion protection
  • RDS.9 RDS engine logs are not shipped to CloudWatch
  • RDS.10 RDS relies on long-lived database passwords
  • RDS.11 RDS instances should have automatic backups
  • RDS.12 IAM auth should be configured for RDS clusters