In July 2019, a former AWS employee exploited a misconfigured web application firewall to make a server-side request forgery (SSRF) call against the EC2 instance metadata service, retrieved temporary credentials from an over-privileged IAM role, and used them to pull data from more than 700 S3 buckets — exposing roughly 106 million Capital One customer records. The breach became the reference case for two controls that are now baseline expectations rather than optional hardening: IMDSv2, which AWS let account owners set as the default for new instances launched from an AMI starting in 2022 and extended to account-wide enforcement for new instance launches in 2024, and least-privilege IAM roles scoped tightly enough that a single stolen credential can't reach hundreds of buckets. Six years later, the underlying failure modes haven't gone away — they've just multiplied across more accounts. AWS Organizations now supports service control policies (SCPs) across an entire multi-account estate, IAM Access Analyzer flags externally shared resources automatically, and Security Hub aggregates findings against the CIS AWS Foundations Benchmark and the AWS Foundational Security Best Practices standard in one dashboard. This post lays out a current, practical checklist of AWS security best practices across four layers — account foundation, IAM, network, and data — that engineering teams can use to close the gaps attackers actually exploit.
What comes first in account-level hardening?
Account-level hardening starts with the root user, because it's the one identity in an AWS account that can never be fully constrained by policy. AWS's own Well-Architected Framework Security Pillar recommends enabling MFA on the root account, removing any root access keys entirely, and reserving root sign-in for a short documented list of tasks — like closing the account or changing support plans — that genuinely require it. Above the single-account level, AWS Organizations lets teams apply SCPs as guardrails that cap what any IAM identity in a member account can do, regardless of how permissive its own policy is, and AWS Control Tower automates a multi-account landing zone with those guardrails pre-wired. For visibility, three native services form the baseline: GuardDuty for threat detection against CloudTrail, DNS, and VPC flow data; Config for continuous configuration-compliance tracking; and Security Hub, which rolls both up alongside CIS and AWS Foundational Security Best Practices scoring into a single account-wide posture view.
What does least-privilege IAM actually require in practice?
Least-privilege IAM requires replacing long-lived credentials with short-lived ones wherever possible, then bounding what those credentials can do even if compromised. That means preferring IAM roles assumed via STS over IAM user access keys for workloads, and using IAM Identity Center (AWS's successor to AWS SSO) for federated human access instead of individual IAM users. Every human identity should have MFA enforced, and permission boundaries should cap the maximum privilege a role or user can ever be granted, even by a future policy change. CloudTrail is the control that turns an intrusion into a traceable one: AWS recommends enabling it account-wide, across all regions, with log file validation on, and delivering logs to a separate, access-restricted logging account. That separation matters because a common step in real intrusions — visible in multiple published cloud-breach post-mortems, including patterns discussed around the Capital One incident — is an attacker disabling or tampering with logging before moving laterally. IAM Access Analyzer, a native AWS service, continuously checks S3 buckets, IAM roles, KMS keys, Lambda functions, and SQS queues for any policy that grants access to a principal outside the account, surfacing exactly the kind of external exposure that turns a single stolen role into a full data breach.
What network controls actually reduce exposure?
Network controls reduce exposure by minimizing what's reachable from the internet in the first place, not just by monitoring what happens after something is reached. Security groups should be scoped to specific source CIDRs and ports rather than left open to 0.0.0.0/0, particularly on management ports like SSH (22) and RDP (3389) — a 0.0.0.0/0 rule on either is one of the most commonly flagged findings in the CIS AWS Foundations Benchmark for exactly this reason. VPC design should place data stores and application backends in private subnets with no direct route to an internet gateway, reachable only through a NAT gateway outbound or a load balancer inbound. VPC Flow Logs give the network-level visibility CloudTrail and application logs don't — they record accepted and rejected traffic at the ENI level, which is often the only record of a scan or lateral-movement attempt that never produced an application log. For internet-facing edges, AWS WAF filters common web exploitation patterns (the same class of AWS WAF misconfiguration implicated in the Capital One SSRF path) and AWS Shield adds DDoS protection at the network and transport layers.
What does correct S3 and RDS hardening look like?
Correct S3 and RDS hardening means encryption and public-access controls are set at creation and enforced account-wide, not left as per-bucket or per-instance opt-ins. For S3, that means enabling S3 Block Public Access at the account level (not just per bucket), turning on default encryption with SSE-S3 or SSE-KMS, and writing bucket policies that explicitly deny uploads missing the s3:x-amz-server-side-encryption condition so an unencrypted object can never land. Versioning plus MFA delete adds a second control against accidental or malicious deletion on buckets holding regulated or otherwise critical data. For RDS, storage encryption has to be enabled at instance creation — AWS does not support enabling it retroactively without a full snapshot-and-restore migration to a new encrypted instance, which makes this a decision that's expensive to get wrong the first time. RDS instances should also be set to not publicly accessible, with access restricted through security groups and, where supported, IAM database authentication instead of long-lived database passwords. Misconfigured public S3 buckets remain one of the most repeatedly documented root causes of cloud data exposure reported by security researchers over the past decade, which is why public-access state is treated as a top-tier finding by virtually every cloud security posture tool, including AWS's own Trusted Advisor.
Why does data security need its own layer beyond IAM and network controls?
Data security needs its own layer because IAM and network controls tell you what's theoretically reachable, not what's actually sensitive and who can practically get to it. A bucket with a locked-down policy and no public access can still be a serious risk if fifteen internal roles have unnecessary read access to a table full of customer PII, or if a security group and an IAM policy each look fine in isolation but together create a reachable path to regulated data. This is the gap data security posture management (DSPM) tooling is built to close: Safeguard's DSPM connects directly to S3 and RDS, reporting each store's encryption status and public-exposure posture, then fuses those findings with effective access permissions (via CIEM) to flag over-privileged or external identities with a path to sensitive data — surfacing exactly the combination of "encrypted but over-shared" or "private but internally over-permissioned" that a checklist alone won't catch. Those findings map to PCI, HIPAA, and GDPR obligations automatically, turning a manual audit exercise into a continuously updated inventory.
How should a team actually operationalize this checklist?
Operationalizing these AWS security best practices means treating the checklist as continuous verification rather than a one-time audit, because AWS accounts drift — new buckets, new roles, and new security groups get created every week, often outside any change-review process. Config rules and Security Hub's standards checks catch configuration drift as it happens rather than at the next quarterly review, and IAM Access Analyzer's continuous scanning catches a newly shared resource within its normal evaluation cycle rather than months later. The practical order of operations for a team starting from zero is: lock down root and enable organization-wide logging first, then IAM least privilege and MFA, then network exposure via security groups and Block Public Access, then data-layer verification of encryption and access fusion on anything holding regulated data. Each layer catches a different class of the Capital One failure mode — and running them as one continuous pipeline, rather than four disconnected audits, is what keeps a single misconfigured control from becoming a 106-million-record breach.