This issue has been assessed as high severity. Review affected configurations immediately.
The PubliclyAccessible flag on an AWS RDS instance is one of the most consistently flagged misconfigurations in cloud security assessments, and it keeps reappearing. Set it to true and your database gets a publicly resolvable DNS endpoint. Combine that with a security group that permits inbound traffic from 0.0.0.0/0, and your database is directly reachable from the internet.
That’s the primary exposure vector. A second one that receives less attention: RDS snapshots shared publicly or copied across accounts with insufficient controls. A single publicly accessible snapshot of a production database can expose schema, credentials stored in the database, and application data even if the live instance is properly locked down.
This guide covers how to identify both exposures, how to remediate them, and how to prevent recurrence using AWS-native controls.
Understanding the Two Exposure Paths
Instance-level exposure requires three things to align: PubliclyAccessible set to true, the instance in a VPC subnet with an internet gateway route, and a security group rule permitting inbound access on the database port from a broad CIDR range. All three need to be present for a remote attacker to connect directly. In practice, misconfigurations that set PubliclyAccessible are often accompanied by permissive security group rules — the same operator who enabled public access often didn’t restrict the security group.
Snapshot-level exposure is different and subtler. RDS manual snapshots can be shared with specific AWS accounts or made public. A public snapshot is downloadable by anyone who knows the snapshot ID — and snapshot IDs follow a predictable prefix format, making enumeration via the AWS CLI straightforward. The data inside the snapshot is a point-in-time copy of the database volume, fully readable once restored.
Automated snapshots also pose a risk when an account has overly permissive cross-account sharing or when snapshots are copied to accounts with weaker security postures. Encryption at rest using customer-managed KMS keys prevents an unauthorized party from reading snapshot data even if they access the snapshot, because they won’t have the KMS key — this is the primary control for snapshot exposure.
Identifying Exposed Instances
Via AWS CLI:
# List all RDS instances with PubliclyAccessible = true
aws rds describe-db-instances \
--query 'DBInstances[?PubliclyAccessible==`true`].[DBInstanceIdentifier,DBInstanceClass,Engine,Endpoint.Address]' \
--output table
# Check specific instance security group rules
aws ec2 describe-security-groups \
--group-ids sg-xxxxxxxxx \
--query 'SecurityGroups[*].IpPermissions[?FromPort<=`5432` && ToPort>=`5432`]'
Via AWS Config:
AWS Config managed rule rds-instance-public-access-check flags instances with PubliclyAccessible set to true. Enable it in your Config rules if it isn’t already. The rule evaluates continuously and marks non-compliant resources automatically.
For snapshot exposure:
# List RDS snapshots shared publicly
aws rds describe-db-snapshots \
--include-public \
--query 'DBSnapshots[?SnapshotType==`public`].[DBSnapshotIdentifier,DBInstanceIdentifier,SnapshotCreateTime]' \
--output table
# Check sharing permissions for a specific snapshot
aws rds describe-db-snapshot-attributes \
--db-snapshot-identifier snap-xxxxxxxxx
Remediation Steps
Disabling public accessibility on a running instance:
aws rds modify-db-instance \
--db-instance-identifier your-db-identifier \
--no-publicly-accessible \
--apply-immediately
This takes effect during the next maintenance window unless --apply-immediately is specified. Applying immediately may cause a brief connectivity interruption. Test in non-production first.
Restricting security group rules:
Remove any inbound rules permitting 0.0.0.0/0 or ::/0 on database ports. Replace them with rules scoped to specific security groups (preferred) or CIDRs limited to your application tier.
# Remove overly broad ingress rule (example for PostgreSQL on 5432)
aws ec2 revoke-security-group-ingress \
--group-id sg-xxxxxxxxx \
--protocol tcp \
--port 5432 \
--cidr 0.0.0.0/0
# Add restricted ingress from application security group only
aws ec2 authorize-security-group-ingress \
--group-id sg-xxxxxxxxx \
--protocol tcp \
--port 5432 \
--source-group sg-yyyyyyyyy
Removing public snapshot sharing:
aws rds modify-db-snapshot-attribute \
--db-snapshot-identifier snap-xxxxxxxxx \
--attribute-name restore \
--values-to-remove all
For snapshots that should be shared with specific accounts only:
aws rds modify-db-snapshot-attribute \
--db-snapshot-identifier snap-xxxxxxxxx \
--attribute-name restore \
--values-to-add 123456789012
Preventive Controls
Remediating existing exposure is the immediate step. Preventing recurrence requires guardrails that catch misconfigurations before they persist.
AWS Config rules to enable:
rds-instance-public-access-check— flagsPubliclyAccessible = truerds-snapshots-public-prohibited— flags publicly shared snapshotsrds-storage-encrypted— flags unencrypted instances (also prevents usable snapshot exfiltration)rds-no-default-port— reduces discoverability
Service Control Policy (SCP) to block public RDS in production accounts:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyRDSPublicAccess",
"Effect": "Deny",
"Action": [
"rds:CreateDBInstance",
"rds:ModifyDBInstance",
"rds:RestoreDBInstanceFromDBSnapshot",
"rds:RestoreDBInstanceToPointInTime"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"rds:PubliclyAccessible": "true"
}
}
},
{
"Sid": "DenyPublicSnapshotSharing",
"Effect": "Deny",
"Action": "rds:ModifyDBSnapshotAttribute",
"Resource": "*",
"Condition": {
"StringEquals": {
"rds:AttributeName": "restore",
"rds:AttributeValue": "all"
}
}
}
]
}
Apply this SCP to production OUs. Development accounts may need the PubliclyAccessible block relaxed, but snapshot public sharing should be denied everywhere.
KMS encryption for all RDS instances:
Encrypted instances using customer-managed KMS keys mean that even if a snapshot is accessed, it can’t be decrypted without the key. Set a KMS key as the default for RDS in your account and enforce encryption via Config rule rds-storage-encrypted.
VPC placement review:
Database instances should sit in private subnets with no route to an internet gateway. Validate subnet route tables as part of any RDS deployment checklist. A private subnet makes PubliclyAccessible = true ineffective even if it’s accidentally set, because there’s no routing path to deliver the connection.
Monitoring and Alerting
Once controls are in place, monitor for drift. A CloudWatch Events rule on AWS Config non-compliance notifications for the above rules gives you near-real-time alerting when any new instance or snapshot violates policy.
For snapshot activity specifically, CloudTrail logs ModifyDBSnapshotAttribute calls. Alert on calls where valuesToAdd contains all — that’s the action that makes a snapshot public.
# CloudTrail query for public snapshot sharing events (Athena)
SELECT eventTime, userIdentity.arn, requestParameters
FROM cloudtrail_logs
WHERE eventName = 'ModifyDBSnapshotAttribute'
AND requestParameters LIKE '%"valuesToAdd":["all"]%'
ORDER BY eventTime DESC
LIMIT 50;
The combination of SCPs that prevent the action, Config rules that detect it if prevention fails, and CloudTrail alerting that notifies on the attempt gives you defence in depth against this class of exposure.