> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        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):
             ```bash theme={null}
             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.
      </Accordion>

      <Accordion title="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:

        ```bash theme={null}
        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:

        ```bash theme={null}
        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:

        ```bash theme={null}
        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):

        ```bash theme={null}
        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.

        ```bash theme={null}
        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`:

        ```bash theme={null}
        aws rds describe-db-instances \
          --db-instance-identifier <DB_INSTANCE_ID> \
          --query 'DBInstances[0].DBInstanceStatus' \
          --output text
        ```

        Confirm new port:

        ```bash theme={null}
        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:

        ```bash theme={null}
        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:

        ```bash theme={null}
        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:

        ```bash theme={null}
        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.
      </Accordion>

      <Accordion title="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):

        ```python theme={null}
        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):

        ```python theme={null}
        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

        ```python theme={null}
        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.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        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.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* \[[https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/RDS/rds-default-port.html](https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/RDS/rds-default-port.html)]
