AWS Security Best Practices: A Complete Checklist for 2026

aws security best practices
aws security best practices
By HOC Team  |  Last updated: August 2026  |  Read time: ~25 min

In June 2023, a misconfigured S3 bucket exposed 3.35 terabytes of data belonging to a major US government contractor — including sensitive personnel records, private encryption keys, and internal documentation.

The misconfiguration was simple: the bucket's block public access settings had been disabled during a development sprint and never re-enabled in production. No attacker exploited a vulnerability. No credential was stolen. The data was simply visible to anyone who knew the bucket name, which is not difficult to discover.

This incident is not unusual. Misconfiguration is consistently the leading cause of cloud security breaches — responsible for 80% of cloud data exposures according to the Gartner Cloud Security Report. AWS provides hundreds of security controls, natively integrated services, and detailed documentation.

The challenge is not that security tools are unavailable — it is that the default configuration of many AWS services prioritises ease of use over security, and teams under delivery pressure do not always harden every control. The result is an attack surface built incrementally from shortcuts that each seemed reasonable at the time.

This guide provides a complete, actionable AWS security checklist for 2026 — covering IAM, S3, VPC networking, encryption, logging, detection services, and compliance tooling. Every item includes the specific AWS service or CLI command to implement it, and why it matters. Work through it systematically against your own account using AWS Security Hub's Foundational Security Best Practices standard as a complementary automated check.

📊 AWS Security in 2026 AWS holds 31% of global cloud market share · 80% of cloud breaches caused by misconfiguration, not exploits · Average cost of a cloud data breach: $4.75M · S3 misconfiguration remains the #1 cloud breach vector · 94% of organisations have at least one critical IAM misconfiguration · AWS Security Hub free tier covers 60-day trial of all security standards · Shared responsibility model: AWS secures the cloud infrastructure; you secure everything deployed in it
1. Shared responsibility model — what AWS secures vs what you secure

The most important conceptual foundation for AWS security is understanding the shared responsibility model. AWS and the customer each own different parts of the security stack, and confusing these responsibilities is where most cloud security failures begin.

AWS shared responsibility model — AWS secures the cloud infrastructure; customers secure everything deployed inside it
AWS Shared Responsibility Model CUSTOMER RESPONSIBILITY — "Security IN the cloud" Customer Data Encryption · DLP Classification IAM Users · Roles Policies · MFA OS & Apps Patching · Config Hardening Network Config Security Groups NACLs · VPC Encryption KMS · S3 SSE TLS in transit Logging & Monitoring CloudTrail · GuardDuty Security Hub · Config AWS RESPONSIBILITY — "Security OF the cloud" Physical DCs Guards · Fences Access control Network Infra DDoS protection Backbone network Hardware Servers · Storage Networking gear Hypervisor VM isolation Nitro system Managed Services RDS · Lambda S3 durability Global Infrastructure 33 Regions · 105 AZs Edge locations
⚠ The most common shared responsibility misunderstanding AWS secures the underlying infrastructure. You are responsible for everything deployed on top of it — your IAM configuration, your S3 bucket policies, your security group rules, your EC2 instance patching, your data encryption choices. A misconfigured S3 bucket is not AWS's failure — it is yours. AWS provides the tools to configure it securely; the responsibility for doing so is the customer's. This distinction matters especially for compliance audits, where "AWS is responsible for that" is rarely an accepted answer.
2. IAM security — identity is the new perimeter

IAM (Identity and Access Management) is the most critical AWS security domain. Compromised IAM credentials are the starting point for the vast majority of AWS breaches — once an attacker has valid IAM credentials with sufficient permissions, every other AWS security control can be circumvented. IAM hardening is therefore the highest-priority AWS security investment.

🔑
IAM security — critical controls
Highest priority — implement before everything else
Root account hardening

The AWS root account has unrestricted access to everything in the account and cannot be restricted by IAM policies. It must be protected as if its compromise means total account loss — because it does.

# Audit root account status via AWS CLI aws iam get-account-summary # Check: AccountMFAEnabled should be 1 # Check: AccountAccessKeysPresent should be 0 (no root access keys) # Root account best practices: # ✓ Enable MFA on root account — hardware MFA key (YubiKey) strongly preferred # ✓ Delete all root account access keys — use IAM roles for programmatic access # ✓ Use root account ONLY for: billing, account closure, IAM support cases # ✓ Store root credentials in a physical safe — offline, not in a password manager # ✓ Create a CloudWatch alarm for any root account login # CloudWatch alarm for root login (critical alert) aws cloudwatch put-metric-alarm \ --alarm-name "RootAccountLogin" \ --alarm-description "Alert on any root account activity" \ --metric-name "RootAccountUsage" \ --namespace "CloudTrailMetrics" \ --statistic Sum --period 300 --threshold 1 \ --comparison-operator GreaterThanOrEqualToThreshold \ --evaluation-periods 1 \ --alarm-actions arn:aws:sns:us-east-1:123456789012:SecurityAlerts
Least privilege — the core IAM principle

Every IAM entity (user, role, group) should have only the permissions required to perform its specific function — nothing more. In practice, teams frequently attach AdministratorAccess or *:* wildcard policies because they are convenient. This means any compromise of that identity gives the attacker full account control. Use IAM Access Analyzer and the IAM policy simulator to identify and reduce over-permissive policies.

# Find users with AdministratorAccess — should be near zero aws iam list-entities-for-policy \ --policy-arn arn:aws:iam::aws:policy/AdministratorAccess # Generate a least-privilege policy based on CloudTrail activity # IAM Access Analyzer will suggest the minimum policy needed aws accessanalyzer start-policy-generation \ --policy-generation-details '{"principalArn":"arn:aws:iam::123456789012:role/MyRole"}' \ --cloud-trail-details '{"accessRole":"arn:aws:iam::123456789012:role/AccessAnalyzerRole", "trailArn":"arn:aws:cloudtrail:us-east-1:123456789012:trail/management-trail", "startTime":"2026-01-01T00:00:00Z"}' # Bad policy pattern — NEVER use this in production { "Effect": "Allow", "Action": "*", "Resource": "*" } # Good pattern — specific actions, specific resources, conditions { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::my-app-bucket/*", "Condition": { "StringEquals": { "aws:RequestedRegion": "us-east-1" } } }
Eliminate long-lived access keys

IAM access keys (access key ID + secret access key) are long-lived credentials that are frequently committed to source code repositories, stored in plaintext configuration files, or left in developer laptops. They are the most commonly stolen credential type in AWS breaches. Replace them with short-lived credentials from IAM roles wherever possible.

# Audit access keys — find old and unused keys aws iam generate-credential-report aws iam get-credential-report --query 'Content' --output text | base64 -d # Review: access_key_last_used_date — disable keys unused for 90+ days # Review: password_last_used — disable users who haven't logged in for 90+ days # List all access keys and their ages aws iam list-users --query 'Users[*].UserName' --output text | \ xargs -I {} aws iam list-access-keys --user-name {} \ --query 'AccessKeyMetadata[*].{User:`{}`,KeyId:AccessKeyId,Created:CreateDate,Status:Status}' # For EC2 instances: use instance profiles (IAM roles) instead of access keys # For Lambda: use execution roles # For ECS/EKS: use task roles and IRSA (IAM Roles for Service Accounts) # For on-premises: use IAM Roles Anywhere with X.509 certificates # Secret detection — find exposed keys in code repositories git secrets --install # Prevents committing AWS credentials trufflehog git https://github.com/org/repo # Scans git history for secrets
IAM roles and permission boundaries
# Permission boundaries — set a maximum permissions ceiling for roles # Even if an IAM policy grants more, the boundary caps what is actually allowed # Critical for delegated administration: prevents privilege escalation # Create a permission boundary that allows only specific services aws iam create-policy \ --policy-name "DeveloperBoundary" \ --policy-document '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:*","ec2:Describe*","lambda:*"], "Resource": "*" }] }' # Attach boundary when creating developer roles # Developer can only do what is in BOTH their policy AND the boundary # Prevents developers from granting themselves AdministratorAccess # Service Control Policies (SCPs) at the AWS Organizations level # Prevent ANY account in the organization from doing specific things # Example SCP: prevent disabling CloudTrail in any account { "Effect": "Deny", "Action": [ "cloudtrail:StopLogging", "cloudtrail:DeleteTrail", "cloudtrail:UpdateTrail" ], "Resource": "*" }
MFA enforcement
# IAM policy to enforce MFA for all human users (attach to all user groups) { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyAllExceptMFASetupIfNoMFA", "Effect": "Deny", "NotAction": [ "iam:CreateVirtualMFADevice", "iam:EnableMFADevice", "iam:GetUser", "iam:ListMFADevices", "iam:ListVirtualMFADevices", "iam:ResyncMFADevice", "sts:GetSessionToken" ], "Resource": "*", "Condition": { "BoolIfExists": { "aws:MultiFactorAuthPresent": "false" } } } ] } # Check which users do NOT have MFA enabled aws iam get-credential-report --query 'Content' --output text | \ base64 -d | awk -F',' '$NF=="false" {print $1, "NO MFA"}'
3. S3 security — hardening object storage

S3 misconfigurations are the single most common cause of cloud data breaches. The consequences of a public S3 bucket are severe and immediate — data is exposed to the entire internet without authentication. AWS has added account-level and bucket-level public access blocking, but these controls must be explicitly enabled and verified.

🪣
S3 security hardening — complete configuration
Check every bucket — even "internal" ones
Block Public Access — account level and bucket level
# Enable Block Public Access at the ACCOUNT level (covers all current and future buckets) aws s3control put-public-access-block \ --account-id 123456789012 \ --public-access-block-configuration \ BlockPublicAcls=true,\ IgnorePublicAcls=true,\ BlockPublicPolicy=true,\ RestrictPublicBuckets=true # Verify account-level BPA is enabled aws s3control get-public-access-block --account-id 123456789012 # Check individual bucket BPA (should also be enabled per bucket as defence in depth) aws s3api get-public-access-block --bucket my-bucket-name # Find ALL buckets in account and check their public access status aws s3api list-buckets --query 'Buckets[*].Name' --output text | \ tr '\t' '\n' | while read bucket; do status=$(aws s3api get-public-access-block --bucket "$bucket" 2>/dev/null) echo "Bucket: $bucket | BPA: $status" done # Check for publicly accessible buckets via S3 Access Analyzer aws accessanalyzer list-findings \ --analyzer-name my-analyzer \ --filter '{"resourceType":{"eq":["AWS::S3::Bucket"]},"status":{"eq":["ACTIVE"]}}'
Bucket policies — enforce security controls
# Enforce HTTPS-only access to a bucket (deny HTTP) { "Version": "2012-10-17", "Statement": [ { "Sid": "DenyHTTP", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": [ "arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*" ], "Condition": { "Bool": { "aws:SecureTransport": "false" } } } ] } # Enforce server-side encryption on all PutObject calls { "Sid": "DenyUnencryptedObjectUploads", "Effect": "Deny", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::my-bucket/*", "Condition": { "StringNotEquals": { "s3:x-amz-server-side-encryption": "aws:kms" } } }
S3 encryption, versioning, and MFA delete
# Enable default encryption with KMS customer-managed key aws s3api put-bucket-encryption \ --bucket my-bucket \ --server-side-encryption-configuration '{ "Rules": [{ "ApplyServerSideEncryptionByDefault": { "SSEAlgorithm": "aws:kms", "KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:key/key-id" }, "BucketKeyEnabled": true }] }' # Enable versioning (required for MFA delete and ransomware recovery) aws s3api put-bucket-versioning \ --bucket my-bucket \ --versioning-configuration Status=Enabled # Enable MFA delete (requires root account credentials to enable) # Prevents deletion of object versions without MFA confirmation # Critical for ransomware-resistant backups stored in S3 aws s3api put-bucket-versioning \ --bucket my-bucket \ --versioning-configuration '{"MFADelete":"Enabled","Status":"Enabled"}' \ --mfa "arn:aws:iam::123456789012:mfa/root-account-mfa-device 123456" # Enable S3 Object Lock (WORM — immutable backups) # Objects cannot be deleted or overwritten for the retention period aws s3api put-object-lock-configuration \ --bucket my-backup-bucket \ --object-lock-configuration '{ "ObjectLockEnabled": "Enabled", "Rule": { "DefaultRetention": { "Mode": "COMPLIANCE", "Days": 90 } } }' # Enable S3 server access logging — record every request to the bucket aws s3api put-bucket-logging \ --bucket my-bucket \ --bucket-logging-status '{ "LoggingEnabled": { "TargetBucket": "my-access-logs-bucket", "TargetPrefix": "s3-logs/" } }'
Use S3 Object Lock in COMPLIANCE mode for backup buckets. COMPLIANCE mode means not even the root account can delete or shorten the retention period during the retention window. GOVERNANCE mode allows root to override. For ransomware-resistant backups, COMPLIANCE mode with 90+ day retention is the correct configuration — it is the cloud equivalent of air-gapped immutable backup storage.
4. VPC and network security
🌐
VPC security — defence-in-depth network architecture
Design for least privilege at the network layer
VPC design principles

A well-designed VPC separates resources into subnets by tier and access level. Public subnets (internet-accessible) contain only load balancers and NAT gateways — never application servers or databases. Private subnets contain application servers that access the internet via NAT gateway but are not directly reachable from the internet. Isolated subnets contain databases and sensitive workloads with no internet route at all.

# Recommended VPC subnet layout VPC CIDR: 10.0.0.0/16 Public subnets (one per AZ): 10.0.0.0/24 us-east-1a — Internet-facing ALB, NAT Gateway only 10.0.1.0/24 us-east-1b — Internet-facing ALB, NAT Gateway only Private subnets (one per AZ): 10.0.10.0/24 us-east-1a — Application servers (EC2, ECS, Lambda in VPC) 10.0.11.0/24 us-east-1b — Application servers Isolated subnets (one per AZ, no internet route): 10.0.20.0/24 us-east-1a — RDS, ElastiCache, internal APIs 10.0.21.0/24 us-east-1b — RDS, ElastiCache, internal APIs Management/security subnet: 10.0.100.0/24 — Bastion hosts, Security tooling, VPN endpoints
Security Groups — stateful instance-level firewall
# Security Group best practices # Security Groups are stateful — return traffic is automatically allowed # Default SG: deny all inbound, allow all outbound — NEVER modify the default SG # Find security groups with port 22 (SSH) or 3389 (RDP) open to 0.0.0.0/0 aws ec2 describe-security-groups \ --filters Name=ip-permission.from-port,Values=22 \ Name=ip-permission.cidr,Values='0.0.0.0/0' \ --query 'SecurityGroups[*].{ID:GroupId,Name:GroupName}' # Find security groups with ALL ports open to the world aws ec2 describe-security-groups \ --filters Name=ip-permission.from-port,Values=0 \ Name=ip-permission.to-port,Values=65535 \ Name=ip-permission.cidr,Values='0.0.0.0/0' # Good: application tier security group # Only allows HTTPS from the load balancer security group — not from the internet Inbound rules for app-server-sg: Port 443 | Source: alb-sg (security group ID) ← from load balancer only Port 22 | Source: bastion-sg (security group ID) ← SSH from bastion only Outbound rules: Port 5432 | Destination: database-sg ← to RDS only Port 443 | Destination: 0.0.0.0/0 ← HTTPS out for package updates via NAT
Network ACLs and VPC Flow Logs
# Enable VPC Flow Logs — captures ALL traffic metadata (not content) # Essential for network forensics, anomaly detection, and compliance aws ec2 create-flow-logs \ --resource-type VPC \ --resource-ids vpc-12345678 \ --traffic-type ALL \ --log-destination-type cloud-watch-logs \ --log-destination arn:aws:logs:us-east-1:123456789012:log-group:vpc-flow-logs \ --deliver-logs-permission-arn arn:aws:iam::123456789012:role/flowlogsRole # Flow log format includes: srcaddr, dstaddr, srcport, dstport, protocol, # packets, bytes, action (ACCEPT/REJECT) — enables detection of: # - Port scanning (many REJECT events from single source) # - Lateral movement (unexpected internal connections) # - Data exfiltration (large outbound byte counts to external IPs) # - Denied connection attempts (potential attacker reconnaissance) # Use AWS PrivateLink / VPC Endpoints to access AWS services without internet # Traffic stays within the AWS network — never traverses the internet aws ec2 create-vpc-endpoint \ --vpc-id vpc-12345678 \ --service-name com.amazonaws.us-east-1.s3 \ --route-table-ids rtb-12345678 # Now S3 access from private subnets goes through the endpoint, not the internet # Add a bucket policy restricting access to requests via the endpoint only
5. Encryption at rest and in transit
🔐
AWS KMS and encryption — complete configuration
Customer-managed keys for sensitive workloads
AWS KMS — key hierarchy
Key typeWho manages itUse caseRotationCost
AWS managed keyAWS manages lifecycle automaticallyDefault encryption for S3, EBS, RDS — no customer involvement neededAutomatic annualFree
Customer managed key (CMK)You create and manage key policiesSensitive workloads requiring audit, cross-account access, or custom rotation policiesConfigurable (annual recommended)$1/month per key + API calls
Customer provided key (SSE-C)You generate and provide keys per requestS3 only — highest control, you hold the key materialYour responsibilityNo AWS charge for the key
CloudHSMYou control dedicated HSM hardwareFIPS 140-2 Level 3 compliance, financial services, governmentYour responsibility$1.60/hour per HSM
# Create a customer managed key with rotation enabled aws kms create-key \ --description "Production data encryption key" \ --key-usage ENCRYPT_DECRYPT \ --origin AWS_KMS # Enable automatic annual key rotation aws kms enable-key-rotation --key-id key-id-here # KMS key policy — restrict who can use and manage the key # Separate key administrators (can manage) from key users (can encrypt/decrypt) { "Statement": [ { "Sid": "KeyAdministrators", "Effect": "Allow", "Principal": {"AWS": "arn:aws:iam::123456789012:role/KeyAdminRole"}, "Action": ["kms:Create*","kms:Describe*","kms:Enable*","kms:Delete*","kms:PutKeyPolicy"], "Resource": "*" }, { "Sid": "KeyUsers", "Effect": "Allow", "Principal": {"AWS": "arn:aws:iam::123456789012:role/AppRole"}, "Action": ["kms:Decrypt","kms:GenerateDataKey"], "Resource": "*" } ] } # Enforce encryption in transit — disable HTTP on load balancers aws elbv2 modify-listener \ --listener-arn arn:aws:elasticloadbalancing:... \ --protocol HTTPS \ --ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06 # Enforce TLS 1.2+ minimum — deny older protocol versions # Use ELBSecurityPolicy-TLS13-1-2-2021-06 for TLS 1.2+ with TLS 1.3 support # Avoid ELBSecurityPolicy-2016-08 (allows TLS 1.0 — deprecated and insecure) # Check for unencrypted EBS volumes aws ec2 describe-volumes \ --filters Name=encrypted,Values=false \ --query 'Volumes[*].{ID:VolumeId,Size:Size,State:State}' # Enable default EBS encryption for all NEW volumes in the account aws ec2 enable-ebs-encryption-by-default aws ec2 get-ebs-encryption-by-default # Verify: "EbsEncryptionByDefault": true # Check for unencrypted RDS instances aws rds describe-db-instances \ --query 'DBInstances[?StorageEncrypted==`false`].{ID:DBInstanceIdentifier,Engine:Engine}'
6. Logging and audit trail — CloudTrail, VPC Flow Logs, Config

Logging is the foundation of security visibility in AWS. Without it, you cannot detect attacks, investigate incidents, demonstrate compliance, or understand what is happening in your account. AWS provides several complementary logging services — each capturing a different category of events.

📋
AWS logging services — what each one captures
CloudTrail
AWS API call audit log
Every API call made to AWS — who called what, when, from where, and with what result. The forensic record of all control plane activity. Enable in all regions, deliver to S3, protect with MFA delete. Management Events (free), Data Events (charged) for S3 and Lambda.
VPC Flow Logs
Network traffic metadata
Source/destination IP, port, protocol, bytes, action (ACCEPT/REJECT) for all traffic in/out of VPC network interfaces. Essential for lateral movement detection, port scan detection, and data exfiltration analysis. Stored in CloudWatch Logs or S3.
AWS Config
Resource configuration history
Continuous recording of AWS resource configurations and changes. Answers "what did this security group look like 30 days ago?" Config Rules evaluate resources against your security policies and flag non-compliant resources automatically.
CloudWatch Logs
Application and service logs
Centralised log aggregation for EC2 application logs, Lambda execution logs, ECS container logs, and RDS database logs. Create metric filters to trigger CloudWatch Alarms on specific log patterns (root login, security group changes, failed auth).
S3 Access Logs
Object-level access records
Every request made to S3 buckets — requester, bucket, key, action, response code, bytes. Separate from CloudTrail. Essential for detecting data exfiltration from S3 and investigating access to sensitive objects.
ELB Access Logs
Load balancer request log
Detailed records of all requests processed by Application and Network Load Balancers — source IP, target, request path, response code, SSL cipher. Useful for detecting web application attacks and identifying scrapers.
# Enable CloudTrail in all regions with log file validation aws cloudtrail create-trail \ --name management-trail \ --s3-bucket-name my-cloudtrail-logs \ --is-multi-region-trail \ --enable-log-file-validation \ --include-global-service-events aws cloudtrail start-logging --name management-trail # Enable S3 Data Events in CloudTrail (records GetObject, PutObject, DeleteObject) # Essential for detecting data exfiltration and investigating S3 breaches # Note: this generates significant volume — filter to sensitive buckets only aws cloudtrail put-event-selectors \ --trail-name management-trail \ --event-selectors '[{ "ReadWriteType": "All", "IncludeManagementEvents": true, "DataResources": [{ "Type": "AWS::S3::Object", "Values": ["arn:aws:s3:::sensitive-data-bucket/"] }] }]' # Create CloudWatch metric filter and alarm for: unauthorized API calls aws logs put-metric-filter \ --log-group-name cloudtrail-logs \ --filter-name UnauthorizedApiCalls \ --filter-pattern '{ ($.errorCode = "*UnauthorizedAccess") || ($.errorCode = "AccessDenied") }' \ --metric-transformations metricName=UnauthorizedApiCalls,metricNamespace=CloudTrailMetrics,metricValue=1 # Essential CloudWatch alarms to create (CIS AWS Foundations Benchmark): # - Root account usage # - Unauthorized API calls # - IAM policy changes # - CloudTrail configuration changes # - Security group changes # - Network ACL changes # - VPC changes # - Console sign-in failures # - MFA console sign-in without MFA
7. Threat detection — GuardDuty, Security Hub, Inspector
🛡
AWS native threat detection services
Enable all three — they complement each other
Amazon GuardDuty — intelligent threat detection

GuardDuty analyses CloudTrail logs, VPC Flow Logs, DNS logs, and S3 data events using machine learning and threat intelligence to detect malicious behaviour. It requires no agents and no configuration of what to look for — it generates findings automatically. Enable it in every region and every AWS account in your organization.

# Enable GuardDuty (takes 30 seconds, 30-day free trial) aws guardduty create-detector \ --enable \ --finding-publishing-frequency FIFTEEN_MINUTES # Enable S3 Protection (detects malicious access to S3) aws guardduty update-detector \ --detector-id detector-id-here \ --data-sources '{"S3Logs":{"Enable":true}}' # GuardDuty finding types relevant to ransomware and account compromise: # Backdoor:EC2/C&CActivity.B — EC2 communicating with known C2 server # CryptoCurrency:EC2/BitcoinTool.B — Crypto mining on EC2 # Trojan:EC2/DropPoint — EC2 dropping malware # UnauthorizedAccess:IAMUser/TorIPCaller — API calls via Tor (attacker anonymisation) # Recon:IAMUser/MaliciousIPCaller — API calls from known malicious IPs # PenTest:IAMUser/KaliLinux — API calls from Kali Linux user agent # Policy:IAMUser/RootCredentialUsage — root account in use # Stealth:S3/ServerAccessLoggingDisabled — attacker disabling S3 logging # Impact:S3/MaliciousIPCaller.Write — malicious IP writing to S3 # Forward findings to EventBridge → SNS → PagerDuty/Slack for real-time alerting aws events put-rule \ --name "GuardDutyHighFindings" \ --event-pattern '{"source":["aws.guardduty"],"detail-type":["GuardDuty Finding"],"detail":{"severity":[{"numeric":[">=",7]}]}}'
AWS Security Hub — centralised security posture

Security Hub aggregates findings from GuardDuty, Inspector, Macie, IAM Access Analyzer, and third-party tools into a single dashboard. It also runs automated compliance checks against security standards — CIS AWS Foundations Benchmark, AWS Foundational Security Best Practices, and PCI DSS. Run these checks against your account immediately to get a prioritised remediation list.

# Enable Security Hub with all standards aws securityhub enable-security-hub \ --enable-default-standards # Enable specific security standards aws securityhub batch-enable-standards \ --standards-subscription-requests \ '[{"StandardsArn":"arn:aws:securityhub:us-east-1::standards/aws-foundational-security-best-practices/v/1.0.0"}, {"StandardsArn":"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0"}]' # Get Security Hub findings by severity aws securityhub get-findings \ --filters '{"SeverityLabel":[{"Value":"CRITICAL","Comparison":"EQUALS"}],"RecordState":[{"Value":"ACTIVE","Comparison":"EQUALS"}]}' \ --sort-criteria '[{"Field":"SeverityNormalized","SortOrder":"desc"}]'
Amazon Inspector — vulnerability scanning

Inspector v2 automatically discovers and scans EC2 instances, Lambda functions, and container images in ECR for OS-level CVEs and software vulnerabilities. It prioritises findings by exploitability and context — a critical CVE in a public-facing EC2 instance scores higher than the same CVE in an internal development instance. Enable it with a single API call; no agents needed for EC2 (uses SSM Agent).

# Enable Inspector v2 for EC2, ECR images, and Lambda aws inspector2 enable \ --resource-types EC2 ECR LAMBDA # Get critical findings (CVSS score 9.0+) aws inspector2 list-findings \ --filter-criteria '{"severity":[{"comparison":"EQUALS","value":"CRITICAL"}]}' \ --sort-criteria '{"field":"INSPECTOR_SCORE","sortOrder":"DESC"}' # Amazon Macie — discovers and classifies sensitive data in S3 # Automatically identifies PII, financial data, and credentials in S3 objects aws macie2 enable-macie aws macie2 create-classification-job \ --job-type ONE_TIME \ --s3-job-definition '{"bucketDefinitions":[{"accountId":"123456789012","buckets":["sensitive-bucket"]}]}'
8. EC2 and compute security
🖥
EC2 security hardening
Eliminate direct SSH/RDP — use Systems Manager
# Use AWS Systems Manager Session Manager instead of SSH/RDP # No inbound ports required on security groups # All sessions logged to CloudWatch/S3 — full audit trail # MFA enforced via IAM role assumption aws ssm start-session --target i-1234567890abcdef0 # Requires: SSM Agent on EC2, IAM role with ssm:StartSession permission # No SSH key pairs needed — eliminates key management risk entirely # IMDSv2 — enforce metadata service v2 to prevent SSRF attacks # IMDSv1 allowed any code running on the instance to get IAM credentials via HTTP # IMDSv2 requires a token — a PUT request before GET — blocking SSRF exploitation aws ec2 modify-instance-metadata-options \ --instance-id i-1234567890abcdef0 \ --http-tokens required \ --http-endpoint enabled # Enforce IMDSv2 for ALL new instances in the account aws ec2 modify-instance-metadata-defaults \ --http-tokens required # Find instances still using IMDSv1 aws ec2 describe-instances \ --filters Name=metadata-options.http-tokens,Values=optional \ --query 'Reservations[*].Instances[*].{ID:InstanceId,State:State.Name}' # Patch management via SSM Patch Manager # Automatically apply security patches on a schedule aws ssm create-patch-baseline \ --name "LinuxSecurityBaseline" \ --operating-system AMAZON_LINUX_2023 \ --approval-rules '{"PatchRules":[{"PatchFilterGroup":{"PatchFilters":[{"Key":"CLASSIFICATION","Values":["Security"]}]},"ApproveAfterDays":3}]}' # Use AMI hardening — start from hardened base images # CIS Hardened Images available in AWS Marketplace # Or use EC2 Image Builder to apply hardening automatically during AMI creation # Disable detailed monitoring if not needed (reduces cost) # But enable it for instances running sensitive workloads: aws ec2 monitor-instances --instance-ids i-1234567890abcdef0 # User data script security — NEVER include secrets in user data # User data is retrievable by anyone who can call ec2:DescribeInstanceAttribute # Use Secrets Manager or Parameter Store for secrets instead: aws secretsmanager get-secret-value --secret-id prod/database/password
9. Multi-account strategy and AWS Organizations

Using a single AWS account for all workloads is the most common structural mistake in AWS security. A single account gives any compromised role or user access to every resource in the account — development, staging, production, and security tooling. AWS Organizations allows you to organise workloads into separate accounts with centralised governance.

🏢
AWS Organizations — recommended account structure
Isolate by environment and workload sensitivity
# Recommended AWS Organizations structure Root (Management Account — billing and Organizations only, no workloads) ├── Security OU │ ├── Security Tooling Account (GuardDuty delegated admin, Security Hub aggregator) │ ├── Log Archive Account (CloudTrail, Flow Logs, Config — centralised, immutable) │ └── Audit Account (read-only access to all accounts for compliance) ├── Infrastructure OU │ ├── Shared Services Account (DNS, AD connector, Transit Gateway) │ └── Network Account (VPCs, Transit Gateway hub, egress VPC) ├── Workloads OU │ ├── Production OU │ │ ├── Production Account A (one account per production application or team) │ │ └── Production Account B │ ├── Staging OU │ │ └── Staging Account │ └── Dev OU │ └── Dev Account (relaxed controls, sandboxed, cannot reach production) └── Sandbox OU └── Individual developer sandbox accounts (full permissions, no production data) # Service Control Policies (SCPs) — apply across entire OUs or accounts # These restrictions apply even to AdministratorAccess IAM roles # SCP: Prevent disabling security services in production accounts { "Sid": "DenyDisablingSecurityServices", "Effect": "Deny", "Action": [ "cloudtrail:StopLogging", "cloudtrail:DeleteTrail", "guardduty:DeleteDetector", "guardduty:DisassociateFromMasterAccount", "securityhub:DisableSecurityHub", "config:StopConfigurationRecorder", "config:DeleteDeliveryChannel" ], "Resource": "*" } # SCP: Restrict workloads to approved regions (data sovereignty) { "Sid": "DenyNonApprovedRegions", "Effect": "Deny", "NotAction": [ "iam:*","sts:*","route53:*","cloudfront:*","waf:*","support:*","budgets:*" ], "Resource": "*", "Condition": { "StringNotEquals": { "aws:RequestedRegion": ["us-east-1","eu-west-1"] } } }
10. Compliance and governance tooling
ServiceWhat it doesCompliance relevanceCost model
AWS ConfigRecords resource configurations continuously and evaluates against rules. Non-compliant resources flagged in real time.SOC 2, PCI DSS, HIPAA, ISO 27001 — evidence of configuration control$0.003 per configuration item recorded + rule evaluations
AWS Security HubAggregates findings from GuardDuty, Inspector, Macie. Runs CIS, FSBP, PCI DSS automated checks.CIS AWS Foundations Benchmark, PCI DSS, NIST 800-5330-day free trial; $0.0010 per check after
AWS Audit ManagerContinuously collects evidence mapped to compliance frameworks (PCI DSS, SOC 2, HIPAA, GDPR). Auto-generates audit-ready reports.Reduces manual audit evidence collection by 80%$1.25 per resource per month assessed
AWS ArtifactOn-demand access to AWS compliance reports — SOC 1/2/3, PCI AOC, ISO certificates, HIPAA BAAProvides AWS's own compliance documentation for audit packagesFree
AWS Organizations + SCPsEnforces guardrails across all accounts — prevents violation of security policies even by adminsEvidence of preventive control across the organisationFree (part of Organizations)
Amazon MacieML-based PII and sensitive data discovery in S3GDPR, CCPA, HIPAA — demonstrates data discovery and classification controls$1 per bucket per month + $0.10 per GB assessed
11. Master security checklist — all controls in one place
AWS security checklist 2026 — work through this against your account
Start with CRITICAL items — they prevent the most common breaches
🔴 CRITICAL — Implement immediately
  • Enable MFA on the root account IAM — use hardware MFA, store credentials offlineCRITICAL
  • Delete all root account access keys IAM — zero access keys should exist for rootCRITICAL
  • Enable S3 Block Public Access at account level S3 — prevents any bucket from being accidentally made publicCRITICAL
  • Enable CloudTrail in all regions CloudTrail — with log file validation and delivery to protected S3 bucketCRITICAL
  • Enable GuardDuty in all regions and all accounts GuardDuty — 30-day free trial; $3–$5/month for most accountsCRITICAL
  • Enable MFA for all IAM users with console access IAM — enforce via IAM policyCRITICAL
  • No security groups with 0.0.0.0/0 inbound on port 22 or 3389 EC2 — use Session Manager insteadCRITICAL
  • Enable EBS default encryption EC2 — all new volumes encrypted automaticallyCRITICAL
  • No long-lived IAM access keys IAM — rotate or replace with roles; disable keys unused 90+ daysCRITICAL
  • Enforce IMDSv2 on all EC2 instances EC2 — prevents SSRF credential theftCRITICAL
🟡 HIGH — Implement within 30 days
  • Enable Security Hub with CIS and FSBP standards Security Hub — automated compliance scoring
  • Enable VPC Flow Logs on all VPCs VPC — delivered to CloudWatch Logs or S3
  • Enable AWS Config in all regions Config — record all resource changes
  • Enable S3 versioning and MFA delete on backup buckets S3
  • Enable S3 default encryption with KMS CMK for sensitive buckets KMS S3
  • Enable S3 HTTPS-only bucket policy on all buckets S3 — deny aws:SecureTransport=false
  • Enable Inspector v2 on all EC2 and Lambda Inspector — continuous CVE scanning
  • Enable KMS key rotation on all CMKs KMS — annual automatic rotation
  • Enable RDS encryption for all database instances RDS
  • CloudWatch alarms for all CIS benchmark events CloudWatch — root login, SG changes, IAM changes
  • Implement IAM Access Analyzer IAM — identify external access to your resources
  • Enable AWS Secrets Manager for all application secrets Secrets Manager — no secrets in code, env vars, or user data
  • Enable GuardDuty S3 Protection and EKS Protection GuardDuty
  • Deploy VPC endpoints for S3, SSM, KMS, and EC2 VPC — traffic stays off the internet
  • Enable SSM Patch Manager SSM — automated security patching for all EC2 instances
🔵 MEDIUM — Implement within 90 days
  • Migrate to multi-account structure with AWS Organizations Organizations — separate prod, dev, security, log archive
  • Implement Service Control Policies Organizations — deny disabling security services, restrict regions
  • Enable Amazon Macie on sensitive S3 buckets Macie — PII and credential discovery
  • Configure centralised log archive with immutable retention S3 — Object Lock, separate account
  • Implement permission boundaries on all developer IAM roles IAM
  • Deploy WAF on all internet-facing ALBs WAF — AWS managed rule groups for OWASP Top 10
  • Enable AWS Shield Standard Shield (free) — automatic DDoS protection for all AWS resources
  • Replace IAM access keys with IAM Roles Anywhere or OIDC federation IAM
  • Enable AWS Audit Manager Audit Manager — automate compliance evidence collection
  • Conduct quarterly IAM access reviews — remove unused permissions, users, roles
  • Use S3 Object Lock COMPLIANCE mode for all backup data S3 — ransomware-resistant
  • Deploy AWS Network Firewall or third-party NGFW for deep packet inspection Network Firewall
80%
of cloud breaches caused by misconfiguration — not exploits
94%
of organisations have at least one critical IAM misconfiguration
$0
cost to enable GuardDuty, Security Hub, and Config — 30-day free trial each
30s
to enable GuardDuty — the single highest-ROI AWS security action

⚡ Start here — five actions you can take in the next hour

  1. Enable GuardDuty in every region right now — takes 30 seconds per region, 30-day free trial, and it immediately starts analysing CloudTrail and Flow Logs for malicious behaviour. If you have an AWS Organizations setup, enable it as a delegated admin from your Security account to cover all accounts simultaneously.
  2. Enable S3 Block Public Access at the account level — one CLI command covers all current and future buckets. Then run aws s3control get-public-access-block --account-id YOUR_ACCOUNT_ID to verify all four settings are true. This eliminates the most common AWS breach vector.
  3. Run the IAM credential reportaws iam generate-credential-report && aws iam get-credential-report. Look for: users without MFA, access keys older than 90 days, root access keys existing at all. Remediate each finding in order of severity.
  4. Enable Security Hub with default standardsaws securityhub enable-security-hub --enable-default-standards. Within an hour it will show you every CIS and AWS FSBP control failure in your account, prioritised by severity. This turns the entire checklist above into an automated finding list.
  5. Build toward cloud security maturity — AWS security connects directly to zero trust architecture (IAM is the identity layer), network segmentation (VPC design implements microsegmentation), and incident response (GuardDuty findings feed your SOAR playbooks). Zero trust guide → | IR plan → | IAM guide →
Frequently asked questions
What are the most important AWS security best practices?

The highest-impact AWS security controls in priority order: enable MFA on the root account and delete its access keys; enable S3 Block Public Access at the account level; enable CloudTrail in all regions with log file validation; enable GuardDuty across all accounts and regions; enforce MFA for all IAM users; eliminate long-lived access keys in favour of IAM roles; enforce IMDSv2 on all EC2 instances to prevent SSRF-based credential theft; enable default EBS encryption; and remove all security groups with unrestricted inbound on SSH or RDP ports. These ten controls address the most commonly exploited misconfigurations in AWS breach investigations.

What is the AWS shared responsibility model?

The AWS shared responsibility model divides security responsibilities between AWS and the customer. AWS is responsible for "security of the cloud" — the physical data centres, hardware, hypervisors, network infrastructure, and the software running managed services (S3, RDS, Lambda). Customers are responsible for "security in the cloud" — IAM configuration, data encryption choices, S3 bucket policies, security group rules, EC2 instance patching, application security, and monitoring. A misconfigured S3 bucket, weak IAM policy, or unpatched EC2 instance is the customer's responsibility — AWS cannot see inside your account configurations and does not fix them on your behalf.

What does AWS GuardDuty detect?

Amazon GuardDuty detects malicious and anomalous activity by analysing CloudTrail API logs, VPC Flow Logs, DNS logs, and S3 data events using machine learning and threat intelligence. It generates findings for threats including: EC2 instances communicating with known C2 servers or malicious IPs, cryptocurrency mining activity, compromised IAM credentials making unusual API calls, API calls from Tor exit nodes, S3 data exfiltration, port scanning from EC2 instances, rootkit behaviour, and credential exfiltration attempts. It requires no agents and no configuration of detection rules — enable it with one API call and it generates findings automatically within minutes of enabling.

How do I secure an S3 bucket in AWS?

S3 bucket security requires several layered controls: enable Block Public Access at both the account level and the individual bucket level; attach a bucket policy that denies HTTP access (requiring HTTPS via aws:SecureTransport condition); enable default server-side encryption with KMS; enable versioning to protect against accidental or malicious deletion; enable server access logging to record every request; for backup buckets, enable S3 Object Lock in COMPLIANCE mode to create immutable, ransomware-resistant storage; and use IAM Access Analyzer to identify any external access grants. Regularly audit bucket policies and ACLs, and use AWS Config rules to flag buckets that deviate from your security baseline.

What is the CIS AWS Foundations Benchmark?

The CIS (Center for Internet Security) AWS Foundations Benchmark is a set of security configuration recommendations for AWS accounts, published and maintained by the non-profit CIS. It covers IAM, logging, monitoring, networking, and S3 controls across around 50 specific checks. AWS Security Hub runs automated checks against the CIS benchmark (currently v1.4) and scores your account against each control. Achieving a high CIS score is a common compliance requirement for SOC 2, PCI DSS, and ISO 27001 audits in cloud-hosted environments. The benchmark is freely available at cisecurity.org and is one of the most widely referenced cloud security standards globally.

Should I use one AWS account or multiple accounts?

Multiple accounts via AWS Organizations is strongly recommended for any organisation beyond a single small team. A single account means a compromised IAM role can potentially access all resources — production, development, security tooling, and sensitive data — in the same account. Separate accounts provide hard blast-radius boundaries: a compromise in the development account cannot reach production. The recommended structure separates workloads into production, staging, and development OUs, with dedicated accounts for security tooling, log archiving, and a management account for billing and Organizations governance. AWS provides the multi-account Landing Zone Accelerator as a free starting template for this structure.

About the author Written by the HOC Team at Hackers Online Club — a cybersecurity community trusted by cloud security engineers, DevSecOps practitioners, CISOs, and security students since 2010. 15+ years of practical cybersecurity guides, cloud security tutorials, and enterprise security resources. Learn more about HOC →