Skip to main content

RDS Database Instances Should Not Use Default Ports

More Info:

Port obfuscation is as an additional layer of defense against non-targeted attacks. In order to leverage this, your Amazon RDS databases instances should not use their default ports (MySQL/Aurora port 3306, SQL Server port 1433, PostgreSQL port 5432)

Risk Level

Low

Address

Security

Compliance Standards

PCIDSS

Remediation

How to ensure RDS Database Instances do not use default ports.

Using AWS Console

  1. Identify the Amazon RDS database instances for which you want to ensure that default ports are not used. (In the Cloudanix Console, navigate to "Misconfig" page and look for Affected Assets for "RDS Database Instances Should Not Use Default Ports" Policy.)
  2. Determine the default ports associated with the database engine you are using. Here are some common default ports:
    • MySQL: 3306
    • PostgreSQL: 5432
    • Oracle Database: 1521
    • SQL Server: 1433
  3. Open the AWS Management Console and navigate to the Amazon RDS service.
  4. Click on the name of the RDS instance for which you want to modify the port.
  5. In the instance details page, click on the "Configuration" tab.
  6. Under the "Connectivity & security" section, locate the "Endpoint & port" information.
  7. Click on the "Modify" button next to the "Endpoint & port" information.
  8. In the "Modify DB instance" window, locate the "Port" field.
  9. Change the value in the "Port" field to a non-default port that you want to use for the RDS instance. Ensure that the new port is not already used by any other service or application.
  10. Click on the "Apply immediately" checkbox to apply the changes immediately. If you don't select this option, the changes will be applied during the next maintenance window for the RDS instance.
  11. Click on the "Modify DB instance" button to save the changes and modify the port.
  12. Repeat these steps for each Amazon RDS database instance that you want to ensure is not using the default port.

Triage and Remediation

Remediation

Using Console

Below are the console-based steps to move an RDS instance off its default port (e.g., 3306 for MySQL, 5432 for PostgreSQL, 1433 for SQL Server, 1521 for Oracle):


1. Plan the New Port

  1. Choose a non-default, unused port in the allowed range for your engine:
    • MySQL/MariaDB/PostgreSQL: 1150–65535 (except ports reserved by AWS)
    • SQL Server: 1150–65535
    • Oracle: 1150–65535
  2. Ensure your network/security team approves the port.

2. Update the RDS Instance Port

  1. Sign in to the AWS Management Console.
  2. Open RDS service.
  3. In the left menu, select Databases.
  4. Click the DB instance you want to change.
  5. Click Modify (top-right).
  6. In the Connectivity or Additional configuration section (varies by engine), find Port.
  7. Change it from the default (e.g., 3306/5432/1433/1521) to your chosen custom port.
  8. At the bottom:
    • Under Scheduling of modifications, choose:
      • Apply immediately (causes a brief downtime)
        or
      • Apply during the next scheduled maintenance window (less disruptive but delayed).
  9. Click Continue, review changes, then click Modify DB instance.

The instance will go into modifying then available status once complete.


3. Update the Security Group Rules

  1. Still in the RDS instance details page, in the Connectivity & security tab, find Security group rules.
  2. Click the linked VPC security group name to open it in the EC2 console.
  3. On the Inbound rules tab:
    • Edit the rule that allowed the old port (e.g., 3306).
    • Either:
      • Change the Port range to the new port, or
      • Add a new rule for the new port and remove the old port rule afterward.
    • Keep the same Source (CIDR, security group, etc.) so the same clients can still connect.
  4. Save the inbound rule changes.

If required, update Outbound rules similarly, though usually outbound is already open.


4. Update Application Configurations

  1. Find all applications, scripts, and tools that connect to this RDS instance.
  2. Update their DB connection strings:
    • Change the port value to the new port.
    • Hostname (endpoint) stays the same; only the port changes (unless you also changed anything else).
  3. Redeploy or restart applications if needed so they use the new configuration.

5. Validate Connectivity

  1. Use a DB client (e.g., psql, mysql, SQL Server Management Studio, etc.) and specify the new port:
    • Example (MySQL):
      mysql -h <rds-endpoint> -P <new-port> -u <user> -p
  2. Confirm that applications can successfully connect and operate.
  3. Once confirmed, verify that the old port is:
    • No longer open in security groups.
    • No longer referenced in any configs or scripts.

6. (Optional) Enforce via Baseline/Standards

  • Document the required non-default port in your internal standards.
  • Use AWS Config or a security tool to:
    • Detect RDS instances using default ports.
    • Alert or block non-compliant deployments.
Using CLI

Below are concise, CLI-focused steps to move RDS off default ports.


1. Identify RDS instances using default ports

Common default ports (AWS RDS engines):

  • MySQL / MariaDB / Aurora MySQL: 3306
  • PostgreSQL / Aurora PostgreSQL: 5432
  • Oracle: 1521
  • SQL Server: 1433

List all DB instances with their ports:

aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,Endpoint.Port]' \
--output table

(Optional) Filter by a specific default port, e.g. MySQL’s 3306:

aws rds describe-db-instances \
--query "DBInstances[?Endpoint.Port==\`3306\`].[DBInstanceIdentifier,Engine,Endpoint.Port]" \
--output table

2. Choose a non-default port

Pick a port that:

  • Is not in use by other services in your environment.
  • Is allowed by your organization’s security policy. Example: 13306 for MySQL, 15432 for PostgreSQL, etc.

3. Update security groups before changing the port

Find the security groups used by the instance:

aws rds describe-db-instances \
--db-instance-identifier <DB_INSTANCE_ID> \
--query 'DBInstances[0].VpcSecurityGroups[*].VpcSecurityGroupId' \
--output text

For each security group, add an inbound rule for the new port (example: 13306/TCP, CIDR 10.0.0.0/16):

aws ec2 authorize-security-group-ingress \
--group-id <SG_ID> \
--protocol tcp \
--port 13306 \
--cidr 10.0.0.0/16

After cutover, you can remove the old-port rule.


4. Change the RDS instance port

Changing --db-port causes a reboot/outage. Schedule a maintenance window.

aws rds modify-db-instance \
--db-instance-identifier <DB_INSTANCE_ID> \
--db-port 13306 \
--apply-immediately

If you prefer to apply during the next maintenance window, omit --apply-immediately.

Check status until it’s available:

aws rds describe-db-instances \
--db-instance-identifier <DB_INSTANCE_ID> \
--query 'DBInstances[0].DBInstanceStatus' \
--output text

Confirm new port:

aws rds describe-db-instances \
--db-instance-identifier <DB_INSTANCE_ID> \
--query 'DBInstances[0].Endpoint.Port' \
--output text

5. For Aurora (cluster) setups

For Aurora, you typically change each instance:

aws rds modify-db-instance \
--db-instance-identifier <AURORA_INSTANCE_ID> \
--db-port 13306 \
--apply-immediately

Repeat for all instances in the cluster.
Verify via:

aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,Endpoint.Port]' \
--output table

6. Update application configurations

Update application connection strings to use the new port:

  • JDBC: jdbc:mysql://host:13306/dbname
  • psql: psql -h host -p 15432 -d dbname -U user
  • Any connection libraries: adjust port field.

Test connectivity from your app environment.


7. Remove old port from security groups

Once apps successfully use the new port, remove the old-port inbound rules:

aws ec2 revoke-security-group-ingress \
--group-id <SG_ID> \
--protocol tcp \
--port 3306 \
--cidr 10.0.0.0/16

Repeat for all affected SGs.

Using Python

Below is one way to do this programmatically using Python and boto3:

1. Decide which ports are “default” and what to change them to

Common default ports (per engine):

DEFAULT_PORTS = {
"mysql": 3306,
"mariadb": 3306,
"aurora": 3306,
"aurora-mysql": 3306,
"postgres": 5432,
"aurora-postgresql": 5432,
"oracle-se2": 1521,
"oracle-se1": 1521,
"oracle-se": 1521,
"oracle-ee": 1521,
"sqlserver-ee": 1433,
"sqlserver-se": 1433,
"sqlserver-ex": 1433,
"sqlserver-web": 1433,
"redshift": 5439, # for Redshift, you'd use redshift client, not rds
}

You also must pick non-default target ports (coordinate with your app & security teams first):

TARGET_PORTS = {
"mysql": 3307,
"mariadb": 3307,
"aurora": 3307,
"aurora-mysql": 3307,
"postgres": 5433,
"aurora-postgresql": 5433,
"oracle-se2": 1522,
"oracle-se1": 1522,
"oracle-se": 1522,
"oracle-ee": 1522,
"sqlserver-ee": 14330,
"sqlserver-se": 14330,
"sqlserver-ex": 14330,
"sqlserver-web": 14330,
}

Adjust the target ports to your standards and ensure corresponding security group rules and client configs will be updated.


2. Python script to find and remediate RDS instances on default ports

import boto3

rds = boto3.client("rds")

DEFAULT_PORTS = {
"mysql": 3306,
"mariadb": 3306,
"aurora": 3306,
"aurora-mysql": 3306,
"postgres": 5432,
"aurora-postgresql": 5432,
"oracle-se2": 1521,
"oracle-se1": 1521,
"oracle-se": 1521,
"oracle-ee": 1521,
"sqlserver-ee": 1433,
"sqlserver-se": 1433,
"sqlserver-ex": 1433,
"sqlserver-web": 1433,
}

TARGET_PORTS = {
"mysql": 3307,
"mariadb": 3307,
"aurora": 3307,
"aurora-mysql": 3307,
"postgres": 5433,
"aurora-postgresql": 5433,
"oracle-se2": 1522,
"oracle-se1": 1522,
"oracle-se": 1522,
"oracle-ee": 1522,
"sqlserver-ee": 14330,
"sqlserver-se": 14330,
"sqlserver-ex": 14330,
"sqlserver-web": 14330,
}

def list_rds_instances():
instances = []
paginator = rds.get_paginator("describe_db_instances")
for page in paginator.paginate():
instances.extend(page["DBInstances"])
return instances

def find_instances_on_default_port():
instances = list_rds_instances()
to_change = []
for inst in instances:
engine = inst["Engine"]
port = inst["Endpoint"]["Port"]
db_id = inst["DBInstanceIdentifier"]

default_port = DEFAULT_PORTS.get(engine)
if default_port is None:
# Engine not in our mapping; skip or handle separately
continue

if port == default_port:
to_change.append({
"DBInstanceIdentifier": db_id,
"Engine": engine,
"CurrentPort": port,
"TargetPort": TARGET_PORTS.get(engine)
})
return to_change

def modify_rds_port(db_identifier, new_port, apply_immediately=False):
print(f"Modifying {db_identifier} to port {new_port} (apply_immediately={apply_immediately})")
resp = rds.modify_db_instance(
DBInstanceIdentifier=db_identifier,
Port=new_port,
ApplyImmediately=apply_immediately
)
return resp

if __name__ == "__main__":
# 1. Find instances using default ports
instances_needing_change = find_instances_on_default_port()

if not instances_needing_change:
print("No RDS instances using a default port (per our mapping).")
exit(0)

print("Instances using default ports:")
for item in instances_needing_change:
print(f"- {item['DBInstanceIdentifier']} | engine={item['Engine']} | "
f"current_port={item['CurrentPort']} -> target_port={item['TargetPort']}")

# 2. Safety step: confirm before changing
confirm = input("Proceed with port modification? (yes/no): ").strip().lower()
if confirm != "yes":
print("Aborting.")
exit(0)

# 3. Modify the instances
for item in instances_needing_change:
if not item["TargetPort"]:
print(f"Skipping {item['DBInstanceIdentifier']} (no target port configured).")
continue

# WARNING: ApplyImmediately=True can cause downtime; set to False to apply in maintenance window
modify_rds_port(
db_identifier=item["DBInstanceIdentifier"],
new_port=item["TargetPort"],
apply_immediately=False, # change to True if you explicitly want immediate change
)

3. Operational steps to follow

  1. Test in non-production first.
  2. Ensure security groups allow the new port:
    • Add inbound rules for the new port before changing RDS.
    • Optionally remove old port after app migration.
  3. Update application connection strings:
    • Most drivers accept host:port or a separate port parameter.
    • Coordinate a maintenance window if ApplyImmediately=False is used or if app restart is required.
  4. Monitor after change:
    • Check RDS instance status until it becomes available.
    • Test app connectivity and logs.

If you want, I can adapt the script to:

  • Only target specific tags/instances.
  • Write changes to a “dry-run” report instead of modifying.
Using Terraform
resource "aws_db_instance" "example" {
identifier = "NON_DEFAULT_PORT_DB_IDENTIFIER" # replace with your DB identifier

engine = "DB_ENGINE" # e.g. "mysql", "postgres", "oracle-ee"
engine_version = "DB_ENGINE_VERSION" # e.g. "15.3"
instance_class = "DB_INSTANCE_CLASS" # e.g. "db.t3.medium"
allocated_storage = 20
username = "DB_USERNAME"
password = "DB_PASSWORD"
db_subnet_group_name = aws_db_subnet_group.example.name
vpc_security_group_ids = [
aws_security_group.db_sg.id,
]

# Remediation: move off the engine default port
# e.g. MySQL default 3306 -> 3307, PostgreSQL default 5432 -> 5433
port = 5433 # set to a non-default port for your engine

# Other required settings as per your environment
skip_final_snapshot = false
final_snapshot_identifier = "FINAL_SNAPSHOT_ID" # choose a snapshot name
}

resource "aws_db_subnet_group" "example" {
name = "DB_SUBNET_GROUP_NAME"
subnet_ids = [SUBNET_ID_1, SUBNET_ID_2] # replace with subnet IDs
}

resource "aws_security_group" "db_sg" {
name = "DB_SG_NAME"
description = "Security group for RDS on non-default port"
vpc_id = VPC_ID # replace with your VPC ID

ingress {
description = "DB access on non-default port"
from_port = 5433 # must match aws_db_instance.port
to_port = 5433 # must match aws_db_instance.port
protocol = "tcp"
cidr_blocks = ["ALLOWED_CIDR_BLOCK"] # replace with allowed CIDR(s)
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

Changing the port on an existing aws_db_instance forces replacement of the database instance, which causes downtime and requires updating all clients to use the new port.

For verification, terraform plan should show the port argument on the aws_db_instance (and matching security group rules) changing from the default (for example, ~ port: "5432" => "5433") and planning to replace the instance if it already exists.

Additional Reading: