IAM Over-Permission Discovery

Find privilege escalation paths and data exfiltration risks in IAM policies.

Introduction

30 Second Summary

In most AWS accounts, someone was given admin access "just to get things working" and that permission was never revoked. Cloud pentesters find these over-permissions before attackers do.

In this project, you will build a deliberately over-permissioned IAM lab in your own AWS account, then systematically discover those over-permissions using manual CLI enumeration and a professional automated scan with Cloudsplaining.

What You'll Build

You run a full cloud pentester's IAM assessment workflow against your own vulnerable lab, watch your manual review catch the obvious wildcards, then see Cloudsplaining's automated scan expose the privilege escalation paths you missed entirely.

By the end of this project, you'll have:

  • A manual enumeration workflow that pulls every policy attached to any IAM identity and validates exploitability using the IAM Policy Simulator without actually executing dangerous actions.
  • A professional risk-prioritized HTML report generated by Cloudsplaining that flags privilege escalation, data exfiltration, and resource exposure risks across your entire account.
  • A clear understanding of the gap between what a policy allows and what an identity actually needs, which is the core of the least privilege principle.
  • Secret Mission: Write and apply a least-privilege remediation policy, then re-scan to prove your fix reduced the risk surface.

Are there any prerequisites?

You need an active AWS Free Tier account with the AWS CLI installed and configured. You also need Python 3.10+ with pip available on your machine.

Before We Start

Before we dive in, let's lock in what you're about to build and why it matters for cloud security.

Install Cloudsplaining

A cloud pentester's toolkit has two sides: manual CLI commands that give you direct, hands-on control over what you examine, and automated scanners that catch subtle combinations human eyes miss.

In this step, you will install Cloudsplaining (your automated scanner) and confirm your AWS environment has the permissions needed to build and assess a vulnerable IAM lab.

In this step, get ready to:
  • Install Cloudsplaining for automated IAM policy analysis.
  • Verify your AWS CLI configuration and IAM permissions are ready for the lab.
Install Cloudsplaining via pip

Cloudsplaining is an open-source IAM policy analysis tool built by Salesforce. It scans every policy in an AWS account and flags over-permissions that violate least privilege across four risk categories: privilege escalation, data exfiltration, resource exposure, and infrastructure modification.

  • Install Cloudsplaining by running this command:
pip3 install --user cloudsplaining

What does --user do?

The --user flag installs the package into your user-level directory instead of system-wide. This avoids permission issues without needing sudo.

Before you run the next command, what do you expect to see if the install succeeded?

  • Confirm the installation succeeded by running:
cloudsplaining --help

You should see Cloudsplaining's help text listing available commands including download, scan, create-exclusions-file, and scan-policy-file.

Command not found?

If you see command not found, your shell may not include the pip user bin directory in your PATH. Try running python3 -m cloudsplaining --help instead.

If that works, add ~/.local/bin to your PATH by adding export PATH="$HOME/.local/bin:$PATH" to your shell profile (~/.bashrc or ~/.zshrc), then restart your terminal.

help me fix cloudsplaining command not found after pip3 install --user

  • Confirm your AWS CLI is configured and can authenticate by running:
aws sts get-caller-identity

You should see JSON output with your AWS account ID, user ARN, and user ID. This confirms the CLI can authenticate with your account.

Seeing 'Unable to locate credentials'?

This means your AWS CLI is not configured with access keys. Run aws configure and enter your access key ID, secret access key, and preferred region when prompted.

help me configure the AWS CLI so aws sts get-caller-identity works

Verify your IAM permissions are sufficient for the lab

The lab requires creating IAM users and policies. The automated scan later needs the iam:GetAccountAuthorizationDetails permission. Your root or admin user on a Free Tier account already has these permissions.

Do you think this command will succeed or return an access denied error for your account?

  • Confirm you have IAM read access by running this command:
aws iam get-account-authorization-details --filter User --query "UserDetailList[].UserName"

You should see a JSON list of IAM usernames in your account. If you are on a fresh Free Tier account, this might be just your admin user.

What does this command do?

The get-account-authorization-details command retrieves information about all IAM users, groups, roles, and policies in the account. The --filter User flag narrows the output to user details only.

The --query flag extracts just the usernames for a cleaner view. You will use this same underlying API call later when Cloudsplaining downloads your full account snapshot.

Seeing AccessDenied?

Your IAM user does not have sufficient permissions. Attach the arn:aws:iam::aws:policy/SecurityAudit managed policy to your user, which includes iam:GetAccountAuthorizationDetails and other read-only security permissions.

help me fix AccessDenied on get-account-authorization-details

Your tools are ready and your permissions are confirmed. Next up, you will build three deliberately over-permissioned IAM entities that represent the most common misconfigurations found in real AWS accounts.

Build the Vulnerable IAM Lab

Your tools are installed and configured. Now you need something real to test them against.

A penetration tester never assesses permissions in a vacuum. In this step, you will create three deliberately over-permissioned IAM users that represent the most common misconfigurations found in production AWS accounts.

In this step, get ready to:
  • Create an admin user with full wildcard permissions.
  • Create a developer user with a privilege escalation path.
  • Create an analyst user with data exfiltration risk.
Create the over-permissioned admin user

The first pattern is the most common misconfiguration in AWS. A developer gets full AdministratorAccess "just to get things working" and the permissions are never scoped down.

  • Create the IAM user by running this command:
aws iam create-user --user-name overperm-admin

You should see JSON output confirming the user was created, including the UserName and Arn fields.

  • Attach the full administrator policy by running:
aws iam attach-user-policy --user-name overperm-admin --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
  • Confirm the policy is attached by running:
aws iam list-attached-user-policies --user-name overperm-admin

You should see AdministratorAccess listed in the AttachedPolicies array.

Why is this dangerous?

This user can do anything in the account. Create resources, delete resources, modify IAM itself, access every secret. In a real engagement, finding this pattern is an immediate critical finding.

Seeing an access denied error?

Your own IAM identity needs permission to create users and attach policies. If you are using the root account or an admin user as confirmed in Step 1, this should work. If not, check that your credentials are correctly configured with aws sts get-caller-identity.

Help me fix my AWS CLI permissions

Create a user with privilege escalation permissions

The second pattern is subtler and more dangerous. This user cannot directly access data, but they can modify IAM itself. That means they can grant themselves any permission they want.

  • First, note your AWS account ID. You can find it in the output of aws sts get-caller-identity from Step 1 (the 12-digit number in the Account field).
  • Create the privilege escalation policy file by running:
cat << 'EOF' > privesc-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:CreatePolicy",
        "iam:AttachUserPolicy",
        "iam:CreateUser",
        "sts:AssumeRole"
      ],
      "Resource": "*"
    }
  ]
}
EOF

What does this policy allow?

Each action here is a building block for privilege escalation. iam:CreatePolicy lets the user write any new policy. iam:AttachUserPolicy lets them attach that new policy to themselves.

Combined, these two actions mean: create an admin policy, attach it to yourself, and you now have full admin access. This is a classic privilege escalation path that automated tools flag but human reviewers often miss.

  • Verify the file was created by running:
cat privesc-policy.json

You should see the JSON policy document printed to your terminal with four actions listed.

  • Create the IAM policy from this file by running:
aws iam create-policy --policy-name PrivEscPolicy --policy-document file://privesc-policy.json

You should see JSON output including the policy Arn. It follows the pattern arn:aws:iam::<your-account-id>:policy/PrivEscPolicy.

  • Create the developer user by running:
aws iam create-user --user-name overperm-developer
  • Attach the privilege escalation policy to this user by running:
aws iam attach-user-policy --user-name overperm-developer --policy-arn arn:aws:iam::[[ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/PrivEscPolicy
  • Confirm the policy is attached by running:
aws iam list-attached-user-policies --user-name overperm-developer

You should see PrivEscPolicy listed in the AttachedPolicies array.

Seeing a MalformedPolicyDocument error?

Make sure you ran the cat << 'EOF' command exactly as shown, including the single quotes around EOF. The quotes prevent the shell from interpreting special characters in the JSON. Run cat privesc-policy.json to check the file contents match the policy above.

Help me fix my policy document

Create a user with data exfiltration permissions

The third pattern represents a user with read access that is far too broad. They can pull data from every S3 bucket and read every secret in the account.

  • Create the data exfiltration policy file by running:
cat << 'EOF' > dataexfil-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:*",
        "secretsmanager:GetSecretValue"
      ],
      "Resource": "*"
    }
  ]
}
EOF

Why is wildcard S3 access a data exfiltration risk?

The action s3:* grants every possible S3 operation on every bucket. An attacker with this permission can list all buckets, download everything, and even copy data to their own external bucket.

Combined with secretsmanager:GetSecretValue, they can also read database passwords, API keys, and any other credentials stored as secrets.

  • Verify the file was created by running:
cat dataexfil-policy.json

You should see the JSON policy with s3:* and secretsmanager:GetSecretValue actions listed.

  • Create the IAM policy from this file by running:
aws iam create-policy --policy-name DataExfilPolicy --policy-document file://dataexfil-policy.json
  • Create the analyst user by running:
aws iam create-user --user-name overperm-analyst
  • Attach the data exfiltration policy to this user by running:
aws iam attach-user-policy --user-name overperm-analyst --policy-arn arn:aws:iam::[[ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/DataExfilPolicy
  • Confirm the policy is attached by running:
aws iam list-attached-user-policies --user-name overperm-analyst

You should see DataExfilPolicy listed in the AttachedPolicies array.

Policy ARN not found?

Make sure you use your own 12-digit account ID in the policy ARN. You can find it by running aws sts get-caller-identity and looking at the Account field. The ARN should look like arn:aws:iam::123456789012:policy/DataExfilPolicy with your real account number.

Help me find the correct policy ARN

Before you move on, do you think listing the attached policies for overperm-admin will show AdministratorAccess? Run the check to confirm.

  • Verify your full lab setup by running:
aws iam list-attached-user-policies --user-name overperm-admin

You should see AdministratorAccess with the ARN arn:aws:iam::aws:policy/AdministratorAccess in the output. Your vulnerable lab is now fully built with all three over-permission patterns in place.

Your lab now contains three distinct real-world over-permission patterns. Next up, you will put on your pentester hat and manually enumerate these permissions using CLI commands to build the intuition that no automated tool can replace.

Manually Enumerate IAM Policies

Your vulnerable IAM lab is live. Three over-permissioned users are now sitting in your AWS account, each representing a common real-world misconfiguration.

Before running automated tools, a pentester always starts with manual reconnaissance. You need to pull the raw policy documents and read them with your own eyes. This is where you build the intuition that automated scanning cannot replace.

In this step, get ready to:
  • Enumerate all IAM users and their attached policies using CLI commands.
  • Pull full policy documents and identify red flags like wildcards and dangerous IAM actions.
  • Validate exploitability using the IAM Policy Simulator without executing any real actions.
Enumerate all users and their attached policies

The first phase of manual IAM reconnaissance is listing what exists. You need to know which users are in the account and what policies grant them access.

  • List all IAM users in your account by running:
aws iam list-users --query "Users[].UserName"

You should see your three lab users in the output: overperm-admin, overperm-developer, and overperm-analyst.

  • Check what policies are attached to overperm-admin by running:
aws iam list-attached-user-policies --user-name overperm-admin

You should see AdministratorAccess in the AttachedPolicies array. Full admin access on any user is the first major red flag.

  • Check the other two lab users by running these commands one at a time:
aws iam list-attached-user-policies --user-name overperm-developer
aws iam list-attached-user-policies --user-name overperm-analyst

You should see PrivEscPolicy attached to overperm-developer and DataExfilPolicy attached to overperm-analyst.

  • List all customer-managed policies (the ones you created, not AWS-managed) by running:
aws iam list-policies --scope Local --query "Policies[].PolicyName"

You should see PrivEscPolicy and DataExfilPolicy listed. These are your custom policies that need deeper inspection.

What is manual IAM enumeration?

In a real cloud penetration test, this enumeration phase maps the attack surface. You now know every identity in the account, what policies they hold, and which policies are custom (and therefore more likely to be misconfigured).

AWS-managed policies like AdministratorAccess are well-documented risks. Custom policies are where the subtle, hard-to-spot misconfigurations live.

Pull and read the actual policy documents

Knowing a policy is attached tells you nothing about what it allows. You need to read the full policy document to identify the specific dangerous permissions.

  • Retrieve the full PrivEscPolicy document by running:
aws iam get-policy-version --policy-arn arn:aws:iam::[[ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/PrivEscPolicy --version-id v1

Where do I find my account ID?

Run aws sts get-caller-identity to see your 12-digit account ID in the Account field. You used this command in Step 1.

You should see the full policy JSON in the output. Look for these red flags in the Statement block:

  • Actions including iam:CreatePolicy, iam:AttachUserPolicy, iam:CreateUser, and sts:AssumeRole. These are IAM-modifying actions that let the identity change permissions.
  • Resource set to "*". This means the actions apply to every resource in the account with no constraint.
  • Now retrieve the DataExfilPolicy document by running:
aws iam get-policy-version --policy-arn arn:aws:iam::[[ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/DataExfilPolicy --version-id v1

You should see the policy JSON with these red flags:

  • A wildcard action s3:* granting every possible S3 operation (read, write, delete, change permissions).
  • The action secretsmanager:GetSecretValue allowing retrieval of any secret in the account.
  • Resource set to "*" meaning no bucket or secret is off-limits.

What makes these permissions dangerous?

The root cause of over-permission is the combination of broad actions with unrestricted resources. A policy that grants s3:GetObject on a single bucket ARN is fine. A policy that grants s3:* on "*" means the identity can read, delete, or exfiltrate data from every bucket in the account.

This is the gap between what the policy allows and what the identity actually needs. Least privilege means granting only the exact permissions required for the job, nothing more.

Seeing an error about NoSuchEntity?

Make sure the policy ARN matches exactly. The format is arn:aws:iam::<account-id>:policy/<PolicyName>. Double check your 12-digit account ID has no spaces or dashes.

Also confirm you used v1 for the --version-id flag. Policy versions always start with a lowercase v.

help me troubleshoot the NoSuchEntity error when running get-policy-version

Validate findings with the IAM Policy Simulator

You have identified the dangerous permissions on paper. Now you need to prove they are actually exploitable. The IAM Policy Simulator lets you test whether a principal can perform specific actions without actually executing them.

Why is the Policy Simulator safe to use?

The simulation does not perform the API operations. It only checks the authorization to determine if the simulated policies allow or deny the operations. You can safely test dangerous actions like iam:AttachUserPolicy without any real changes to your account.

Before you run the next command, make a prediction. Do you think overperm-developer will be allowed or denied the ability to attach policies to other users?

  • Test if overperm-developer can escalate privileges by running:
aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::[[ACCOUNT_ID="your 12-digit AWS account ID"]]:user/overperm-developer --action-names iam:AttachUserPolicy iam:CreatePolicy

Check the EvalDecision field in the output for each action. You should see allowed for both iam:AttachUserPolicy and iam:CreatePolicy. This confirms the policy is exploitable.

  • Now test the data exfiltration risk for overperm-analyst by running:
aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::[[ACCOUNT_ID="your 12-digit AWS account ID"]]:user/overperm-analyst --action-names s3:GetObject secretsmanager:GetSecretValue

You should see EvalDecision showing allowed for both actions. This confirms that overperm-analyst can read any S3 object and retrieve any secret in the account.

What did your manual review uncover?

You have confirmed three categories of over-permission: full admin access (overperm-admin), IAM self-modification capabilities (overperm-developer), and unrestricted data access (overperm-analyst).

You spotted the obvious red flags: wildcard actions, wildcard resources, and dangerous IAM-modifying permissions. In the next step, you will see what an automated scanner finds that your manual review did not catch.

Seeing implicitDeny instead of allowed?

Check that the --policy-source-arn points to the correct user. The format is arn:aws:iam::<account-id>:user/<username>. Make sure the username matches exactly (overperm-developer not overperm_developer).

Also verify that the policy was attached successfully in Step 2 by re-running aws iam list-attached-user-policies --user-name overperm-developer.

help me debug why simulate-principal-policy shows implicitDeny

Your manual enumeration is complete. You have confirmed that these policies are exploitable. Next up, you will run an automated scan with Cloudsplaining to discover what your manual review missed.

Run Automated Scan with Cloudsplaining

Your manual review caught the obvious wildcards and confirmed exploitability with the Policy Simulator. But privilege escalation paths that hide across multiple permissions are easy to miss when you are reading JSON by eye.

Cloudsplaining analyzes every policy in the account and flags combinations that enable escalation, data exfiltration, and resource exposure. This is where you see what you missed.

In this step, get ready to:
  • Download a full IAM snapshot of your account for offline analysis.
  • Run Cloudsplaining's automated scan and generate a risk-prioritized report.
  • Interpret the HTML report and compare automated findings against your manual review.
Download the account authorization details

Cloudsplaining works by analyzing a local JSON snapshot of all IAM entities in your account. This snapshot is downloaded via the iam:GetAccountAuthorizationDetails API call, which returns every user, group, role, and policy in one dump.

  • Download the full IAM snapshot by running this command:
cloudsplaining download --profile default --output account-details.json

What does this command do?

  • cloudsplaining download calls the GetAccountAuthorizationDetails API behind the scenes.
  • --profile default tells it which AWS credentials profile to use.
  • --output account-details.json saves the full IAM snapshot to a local JSON file you can analyze offline.
  • Confirm the file was created by running:
ls account-details.json

You should see account-details.json listed in the output.

Seeing an access denied error?

The download requires the iam:GetAccountAuthorizationDetails permission. If you are using an admin user or root account on Free Tier, this permission is already included.

Verify your identity is correct by running aws sts get-caller-identity and confirming it shows the admin user you configured in Step 1.

Help me troubleshoot the Cloudsplaining download error.

Generate an exclusions file and run the scan

Cloudsplaining uses an exclusions file to filter out false positives that are context-dependent. For this lab, you will use the default template without modifications so nothing is excluded from the scan.

  • Create the exclusions template by running:
cloudsplaining create-exclusions-file --output-file exclusions.yml
  • Confirm the file exists:
ls exclusions.yml

You should see exclusions.yml in the output.

Before you run the scan, what do you think Cloudsplaining will find that your manual review missed?

  • Run the full scan against your account snapshot by running:
cloudsplaining scan --input-file account-details.json --exclusions-file exclusions.yml --output ./report

What does this command do?

  • --input-file account-details.json points Cloudsplaining at the IAM snapshot you downloaded.
  • --exclusions-file exclusions.yml tells it which policies or actions to skip (none in your case, since you kept the defaults).
  • --output ./report saves the three output files into a report directory: an HTML report, a triage CSV worksheet, and raw JSON findings.
  • Confirm the report was generated by running:
ls ./report

You should see at least an HTML file, a JSON file, and a CSV file inside the report directory.

Scan fails or no output appears?

Make sure account-details.json is in your current directory. Run ls account-details.json to confirm.

If you see a Python error about missing modules, confirm Cloudsplaining is installed by running cloudsplaining --help. If that fails, revisit the install step.

Help me troubleshoot why my Cloudsplaining scan is failing.

Interpret the Cloudsplaining report

The HTML report is where automated analysis pays off. Cloudsplaining categorizes every finding into risk types so you can prioritize remediation.

  • Open the HTML report in your browser. On macOS, run:
open ./report/*.html

On Linux, use xdg-open ./report/*.html instead. On Windows WSL, use explorer.exe ./report/*.html.

  • Look for findings organized by these risk categories:
  • Privilege Escalation - identifies policies that allow IAM self-modification (your PrivEscPolicy).
  • Data Exfiltration - identifies unrestricted access to data stores like S3 and Secrets Manager (your DataExfilPolicy).
  • Resource Exposure - identifies the ability to modify resource-based policies.
  • Infrastructure Modification - identifies unrestricted ability to change infrastructure.

What did Cloudsplaining find that you missed?

Your manual review likely flagged the wildcard Resource: "*" as dangerous. Cloudsplaining goes further. It recognizes that the combination of iam:CreatePolicy and iam:AttachUserPolicy together means a user can grant themselves any permission, including full admin access.

This is a privilege escalation path. Each action alone looks suspicious. Together, they are exploitable. Cloudsplaining identifies IAM actions that do not leverage resource constraints, which is the root cause of over-permission.

  • In the report, confirm you see findings under Privilege Escalation that reference PrivEscPolicy.
  • Confirm you see findings under Data Exfiltration that reference DataExfilPolicy.

Why pentesters use both manual and automated approaches

Manual review builds intuition. You learn to spot patterns and understand why a policy is dangerous. Automated tools like Cloudsplaining catch the combinatorial risks that humans overlook when reading individual policy documents.

A professional engagement uses both. The manual pass gives you confidence in the context. The automated scan ensures nothing slips through the cracks.

Report is blank or missing findings?

Check that your three lab users (overperm-admin, overperm-developer, overperm-analyst) still exist with their policies attached. Run aws iam list-users --query "Users[].UserName" to verify.

If users are missing, re-create them from Step 2 before re-running the download and scan.

Help me figure out why my Cloudsplaining report is empty.

You now have a professional, risk-prioritized report that documents every over-permission in your account. Next up, you will clean up the deliberately vulnerable lab entities so they do not remain a security risk.

Clean Up the Lab

Your Cloudsplaining report exposed privilege escalation paths and data exfiltration risks that manual review missed. The automated scan is complete, and you now have a full picture of the lab's over-permissions.

These are deliberately vulnerable IAM entities. Leaving them in your account is a real security risk, even in a Free Tier lab. In this step, you will tear down every lab resource to restore your account to a clean state.

In this step, get ready to:
  • Detach all policies from the lab users and delete them.
  • Delete the custom IAM policies.
  • Verify a clean account state and remove local files.
Detach policies and delete users

IAM requires you to detach all managed policies from a user before you can delete that user. You will work through each lab user, detach its policy, then delete it.

  • Detach policies from all three lab users and delete them by running these commands:
# Detach the AWS managed admin policy and delete overperm-admin
aws iam detach-user-policy --user-name overperm-admin --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
aws iam delete-user --user-name overperm-admin

# Detach custom policy and delete overperm-developer
aws iam detach-user-policy --user-name overperm-developer --policy-arn arn:aws:iam::[[AWS_ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/PrivEscPolicy
aws iam delete-user --user-name overperm-developer

# Detach custom policy and delete overperm-analyst
aws iam detach-user-policy --user-name overperm-analyst --policy-arn arn:aws:iam::[[AWS_ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/DataExfilPolicy
aws iam delete-user --user-name overperm-analyst

What do these commands do?

Each pair follows the same pattern: first detach the managed policy (using its ARN), then delete the now-empty user. These commands produce no output on success. Silence means it worked.

You must detach before deleting because IAM will reject a delete-user call if the user still has attached policies.

  • Confirm all three lab users are gone by running:
aws iam list-users --query "Users[].UserName"

Your output should not contain overperm-admin, overperm-developer, or overperm-analyst. You may see your own admin user listed. That is expected.

Seeing a NoSuchEntity error?

This means the user or policy was already deleted or the name was misspelled. Double-check the exact user names: overperm-admin, overperm-developer, overperm-analyst.

If you see a DeleteConflict error, it means a policy is still attached. Re-run the matching detach-user-policy command first, then retry the delete.

Help me troubleshoot my IAM user deletion errors

  • Now delete the custom policies by running:
aws iam delete-policy --policy-arn arn:aws:iam::[[AWS_ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/PrivEscPolicy
aws iam delete-policy --policy-arn arn:aws:iam::[[AWS_ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/DataExfilPolicy

Why can you delete these policies now?

You already detached both policies from their users in the previous commands. A managed policy can only be deleted once it is detached from all IAM entities. These commands also produce no output on success.

Verify clean state
  • Confirm no lab policies remain by running:
aws iam list-policies --scope Local --query "Policies[].PolicyName"

This lists only customer-managed policies. You should see an empty list or no mention of PrivEscPolicy or DataExfilPolicy.

  • Remove the local policy JSON files and downloaded data by running:
rm -f account-details.json exclusions.yml privesc-policy.json dataexfil-policy.json
  • Remove the Cloudsplaining report directory by running:
rm -rf ./report

Before you run the final check, what do you expect to see when you list your IAM users?

  • Run the final verification to confirm all lab users are gone:
aws iam list-users --query "Users[].UserName"

None of the lab users (overperm-admin, overperm-developer, overperm-analyst) appear. Your account is back to a clean state.

Still seeing a lab user in the list?

If a lab user still appears, scroll up and re-run the matching detach-user-policy and delete-user commands for that specific user. Check for typos in the user name.

Help me figure out why my lab user still exists after deletion

Secret mission

Remediate and Re-Scan

Discovery without remediation is just a vulnerability report gathering dust. Can you design a least-privilege replacement policy from scratch, apply it, and prove the fix works by re-scanning with Cloudsplaining?

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. IAM entities are free, so there are no ongoing costs. However, these are deliberately over-permissioned entities that pose a real security risk if left in your account.

Security risk

The lab entities remaining in your account (particularly overperm-developer) have permissions that could be exploited if an attacker gains access to your AWS account. Deleting them is strongly recommended.

Resources you used:

  • IAM user: overperm-developer (with LeastPrivPolicy attached).
  • Customer-managed IAM policy: LeastPrivPolicy.
  • Local files: account-details.json, least-priv-policy.json.
  • Local directory: ./report-remediated/.
  • Installed tool: Cloudsplaining (pip package).

Keep everything running

Not recommended. These are deliberately vulnerable IAM entities that could be exploited if an attacker gains access to your account. Only choose this if you plan to continue experimenting in the next few minutes.

  • No action needed, but revisit this section soon to delete everything.

Pause - I'll come back to this later

IAM entities have no running cost and cannot be "paused" in the traditional sense. They either exist or they don't.

  • If you want to return to this project later, keep the entities but understand the security implications.
  • Consider deleting now and re-creating the lab from scratch when you return. The project steps are repeatable.

Delete - I don't want to use this again

Remove all project resources and start fresh. This is the recommended path.

Detach the policy from overperm-developer and delete the user:

  • Detach LeastPrivPolicy from overperm-developer by running:
aws iam detach-user-policy --user-name overperm-developer --policy-arn arn:aws:iam::[[ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/LeastPrivPolicy
  • Delete the user by running:
aws iam delete-user --user-name overperm-developer
  • Delete the LeastPrivPolicy by running:
aws iam delete-policy --policy-arn arn:aws:iam::[[ACCOUNT_ID="your 12-digit AWS account ID"]]:policy/LeastPrivPolicy

Verify the IAM cleanup:

  • Confirm no lab users remain by running:
aws iam list-users --query "Users[].UserName"
  • Confirm no lab policies remain by running:
aws iam list-policies --scope Local --query "Policies[].PolicyName"

Remove local files and directories:

  • Delete all local project files by running:
rm -f account-details.json least-priv-policy.json
rm -rf ./report-remediated/

Uninstall Cloudsplaining (optional):

  • Remove the Cloudsplaining package by running:
pip3 uninstall cloudsplaining -y

What about overperm-admin and overperm-analyst?

If you completed Step 5, those users and their policies (PrivEscPolicy, DataExfilPolicy) were already deleted. If you skipped Step 5, return to that step and follow its cleanup instructions to remove them as well.

Nice Work!

Nice Work!

You just completed a full cloud pentester's IAM over-permission discovery workflow. From building a vulnerable lab to generating a professional risk report, you now have a repeatable methodology for finding the permissions that should not exist.

You've learned how to:

  • Build a deliberately over-permissioned IAM lab with three common real-world patterns: full admin access, privilege escalation paths, and data exfiltration risk.
  • Execute manual CLI-based IAM enumeration and validate exploitability using the IAM Policy Simulator without actually performing dangerous actions.
  • Run a professional Cloudsplaining automated scan to generate a risk-prioritized HTML report and identify privilege escalation paths that manual review missed.
  • Secret Mission: Write and apply a least-privilege remediation policy, re-scan to prove the fix works, and document the risk reduction.

Ready to quiz yourself?