AWS makes it remarkably easy to deploy infrastructure. It makes it equally easy to do so insecurely. In cloud security assessments across financial services, SaaS, and enterprise clients, the same misconfigurations appear again and again — not because engineers are careless, but because AWS defaults optimise for ease of use, not security. Our AWS security hardening service addresses all of these gaps systematically.
This guide covers the 10 most critical AWS security misconfigurations we encounter, why they matter, and exactly what to do to fix them.
1. Overly Permissive IAM Policies
The Problem
IAM is the foundation of AWS security. When it’s misconfigured, everything else is compromised. The most common mistakes:
- Using
"Action": "*"or"Resource": "*"in policies - Attaching
AdministratorAccessto non-admin roles - IAM users with long-lived access keys that never rotate
- Roles with trust policies that allow any AWS account to assume them
The Impact
A compromised IAM credential with AdministratorAccess gives an attacker complete control over your AWS account — compute, databases, S3 buckets, DNS, and your ability to see the intrusion.
The Fix
Apply the principle of least privilege:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-specific-bucket/*"
}
]
}
Operational checklist:
- Use AWS IAM Access Analyzer to find overly permissive policies
- Enable IAM credential reports weekly (
aws iam generate-credential-report) - Enforce access key rotation at 90 days maximum
- Delete unused IAM users and roles (use last-accessed data to identify them)
- Never use the root account for day-to-day operations — lock it down with MFA and hardware key
2. Public S3 Buckets with Sensitive Data
The Problem
S3 has been at the centre of some of the largest data breaches in history — Capital One (2019), GoDaddy, and dozens of others all had S3 exposure as a contributing factor. The issue: developers create buckets for static hosting or file sharing, grant public access, and forget about them. Those buckets accumulate sensitive data over time.
The Impact
Customer PII, internal documents, database backups, API keys in config files, and source code are all commonly found in misconfigured public S3 buckets. Attackers use automated scanners to find them.
The Fix
Block public access at the account level:
aws s3control put-public-access-block \
--account-id YOUR_ACCOUNT_ID \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
Then enforce it per-bucket and via SCP (Service Control Policy) across your organisation.
Additional controls:
- Enable S3 server-side encryption (SSE-S3 or SSE-KMS) on all buckets
- Enable S3 access logging to track who’s accessing what
- Use Macie to automatically detect sensitive data in S3
- Set up GuardDuty S3 protection for anomaly detection
3. No MFA on Privileged IAM Users
The Problem
IAM users with console access and no MFA are a single credential leak away from full account compromise. Access key leaks from GitHub repositories, Slack messages, and CI/CD pipeline logs are extremely common.
The Fix
Enforce MFA via an IAM policy that denies all actions if MFA is not present:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:GetUser",
"iam:ListMFADevices",
"iam:ListVirtualMFADevices",
"iam:ResyncMFADevice",
"sts:GetSessionToken"
],
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}
}
]
}
For production environments, move entirely to IAM Identity Center (SSO) with your identity provider (Okta, Azure AD) — this eliminates long-lived IAM user credentials entirely.
4. Security Groups with Unrestricted Inbound Access
The Problem
Security groups acting as firewalls with 0.0.0.0/0 on sensitive ports:
- Port 22 (SSH) open to the world
- Port 3389 (RDP) open to the world
- Database ports (3306 MySQL, 5432 PostgreSQL, 27017 MongoDB) open to the world
- Port 8080, 8443 admin interfaces with no IP restriction
The Impact
These are scanned and found within minutes of being exposed. Brute-force attacks start immediately. Ransomware groups specifically target exposed RDP.
The Fix
Never allow 0.0.0.0/0 inbound to management ports. For SSH:
# Only allow SSH from your office IP or VPN CIDR
aws ec2 authorize-security-group-ingress \
--group-id sg-xxxx \
--protocol tcp \
--port 22 \
--cidr 203.0.113.0/24
Better approach: eliminate SSH entirely. Use AWS Systems Manager Session Manager for instance access — no open ports, no key management, full audit trail:
aws ssm start-session --target i-1234567890abcdef0
Use AWS Config Rules to detect and alert on overly permissive security groups:
restricted-sshrestricted-common-portsvpc-sg-open-only-to-authorized-ports
5. CloudTrail Not Enabled or Incomplete
The Problem
CloudTrail is AWS’s audit log — every API call, every console action, every configuration change. We regularly find AWS accounts with:
- CloudTrail disabled in multiple regions
- Only management events logged (data events — S3 reads/writes, Lambda invocations — not captured)
- CloudTrail logs stored in the same account (an attacker can delete them)
- No log file integrity validation
The Impact
Without CloudTrail, you cannot investigate a breach. You don’t know what an attacker accessed, what they changed, or how they escalated privileges. It also means you can’t meet compliance requirements for ISO 27001, SOC 2, PCI DSS, or GDPR.
The Fix
Enable CloudTrail in all regions with a multi-region trail:
aws cloudtrail create-trail \
--name organisation-audit-trail \
--s3-bucket-name your-cloudtrail-bucket \
--is-multi-region-trail \
--enable-log-file-validation \
--include-global-service-events
Enable data events for S3 and Lambda:
aws cloudtrail put-event-selectors \
--trail-name organisation-audit-trail \
--event-selectors '[{"ReadWriteType":"All","IncludeManagementEvents":true,"DataResources":[{"Type":"AWS::S3::Object","Values":["arn:aws:s3"]}]}]'
Send CloudTrail logs to a separate, locked-down account (logging/security account) so they can’t be tampered with from a compromised workload account.
6. No VPC Flow Logs
The Problem
VPC Flow Logs capture network traffic metadata — source/destination IPs, ports, protocols, byte counts — for all traffic in your VPC. Most accounts don’t enable them, or only enable them on specific subnets.
The Impact
Without flow logs, you cannot detect lateral movement, data exfiltration, or C2 (command-and-control) communication in your network. They’re essential for both incident response and threat hunting.
The Fix
Enable VPC Flow Logs for all VPCs, sending to CloudWatch Logs or S3:
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-xxxx \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /aws/vpc/flowlogs \
--deliver-logs-permission-arn arn:aws:iam::xxxx:role/flowlogs-role
Use GuardDuty on top of flow logs for automated anomaly detection — it ingests flow logs and DNS logs and surfaces potential threats without requiring you to write detection queries.
7. EC2 Instances with Hardcoded Credentials
The Problem
Applications running on EC2 often have AWS access keys hardcoded in:
- Application configuration files
.envfiles on the filesystem- Environment variables set at instance launch
- Docker container images pushed to ECR or Docker Hub
These credentials are often over-permissioned (developers gave them admin access to avoid debugging IAM issues).
The Fix
Use IAM Instance Profiles — the correct way for EC2 instances to authenticate to AWS services:
- Create an IAM role with least-privilege permissions
- Attach the role to the EC2 instance as an instance profile
- The application calls AWS services using the instance metadata service (IMDS) — no credentials needed
# Attach an IAM role to an existing instance
aws ec2 associate-iam-instance-profile \
--instance-id i-xxxx \
--iam-instance-profile Name=MyAppRole
Also enable IMDSv2 (Instance Metadata Service v2) to prevent SSRF attacks from using the metadata endpoint to steal credentials:
aws ec2 modify-instance-metadata-options \
--instance-id i-xxxx \
--http-tokens required \
--http-endpoint enabled
Enforce IMDSv2 across your entire account via SCP or instance launch templates.
8. RDS Databases Publicly Accessible
The Problem
RDS instances with PubliclyAccessible: true are reachable from the internet. Combined with a weak password or a known vulnerability in the database engine, this is a direct path to data breach.
The Impact
Database exfiltration is typically the end-goal of most attacks. Publicly accessible RDS instances also expose you to automated credential stuffing and vulnerability scanning.
The Fix
All RDS instances should be in private subnets with PubliclyAccessible: false:
aws rds modify-db-instance \
--db-instance-identifier my-database \
--no-publicly-accessible \
--apply-immediately
Access patterns:
- Application servers → RDS via security group rules (specific SG, not IP range)
- DBA access → via AWS Session Manager port forwarding or a bastion host in a private subnet
- Never via direct internet exposure
Also enable:
- Encryption at rest for all RDS instances (KMS)
- Automated backups with appropriate retention period
- Enhanced Monitoring and Performance Insights
- RDS Deletion Protection to prevent accidental or malicious deletion
9. No GuardDuty or Security Hub
The Problem
Many AWS accounts have no threat detection. Without GuardDuty, attackers can operate for months without triggering any alert. Without Security Hub, there’s no centralised view of security findings across the account.
The Fix
Enable GuardDuty in every region, in every account. It ingests CloudTrail, VPC Flow Logs, and DNS logs automatically:
aws guardduty create-detector --enable --finding-publishing-frequency FIFTEEN_MINUTES
GuardDuty detects:
- Cryptocurrency mining
- Credential exfiltration
- Communication with known malicious IPs/domains
- Unusual API call patterns (compromised credentials)
- Port scanning from EC2 instances
Enable Security Hub for a consolidated security score and integration with GuardDuty, Inspector, Macie, and third-party tools:
aws securityhub enable-security-hub --enable-default-standards
Set up EventBridge rules to route HIGH and CRITICAL GuardDuty findings to SNS → PagerDuty / Slack for immediate alerting.
10. Missing Preventive Controls at the Org Level (SCPs)
The Problem
In multi-account AWS organisations, individual account-level controls can be overridden by account admins. Without Service Control Policies (SCPs) at the Organisation level, a single compromised account can affect the entire organisation.
The Fix
Apply SCPs to prevent the most dangerous actions across all accounts:
Deny root account usage:
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringLike": {
"aws:PrincipalArn": "arn:aws:iam::*:root"
}
}
}
Deny disabling security services:
{
"Effect": "Deny",
"Action": [
"guardduty:DeleteDetector",
"guardduty:DisassociateFromMasterAccount",
"cloudtrail:DeleteTrail",
"cloudtrail:StopLogging",
"config:DeleteConfigurationRecorder",
"securityhub:DisableSecurityHub"
],
"Resource": "*"
}
Deny region usage (if you only operate in specific regions):
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": ["ap-south-1", "ap-southeast-1", "us-east-1"]
}
}
}
The Hardening Checklist
| Category | Control | Priority |
|---|---|---|
| IAM | Least privilege policies | Critical |
| IAM | MFA enforcement / SSO | Critical |
| IAM | No long-lived access keys | Critical |
| S3 | Block public access (account level) | Critical |
| S3 | Encryption at rest | High |
| Networking | No 0.0.0.0/0 on management ports | Critical |
| Networking | VPC Flow Logs enabled | High |
| Compute | IMDSv2 enforced | High |
| Compute | No hardcoded credentials | Critical |
| Database | RDS not publicly accessible | Critical |
| Database | Encryption at rest | High |
| Logging | CloudTrail all regions + data events | Critical |
| Detection | GuardDuty all regions | Critical |
| Detection | Security Hub enabled | High |
| Org | SCPs blocking security service deletion | Critical |
How to Prioritise
If you’re starting from scratch, address controls in this order:
- Root account — disable access keys, enable MFA, lock it away
- CloudTrail — you need logs before you can investigate anything
- GuardDuty — automated detection starts immediately
- S3 public access block — prevents the most common data exposure
- Security group audit — close any ports open to 0.0.0.0/0
- IAM audit — remove
AdministratorAccessfrom non-admin roles - MFA enforcement — protect console access
- IMDSv2 — prevent SSRF-to-credential-theft
- RDS — move databases to private subnets
- SCPs — lock down the entire organisation
Getting an Expert Assessment
Automated tools like AWS Trusted Advisor, Security Hub’s Foundational Security Best Practices, and third-party CSPM tools (Wiz, Prisma Cloud) catch many of these issues. But they don’t catch everything — particularly complex IAM privilege escalation paths, application-level vulnerabilities, or custom misconfigurations that don’t match a known rule.
A cloud security assessment by an experienced team will find what automated tools miss, demonstrate the actual business impact, and give you a prioritised remediation plan tailored to your environment.
CyberneticsPlus conducts AWS, Azure, and GCP security assessments for organisations across financial services, SaaS, and enterprise. Our cloud security engineers hold AWS Security Specialty and other advanced certifications. Contact us to schedule an assessment.