Skip to main content

Triage and Remediation

Remediation

Using Console

Below is a practical, console-focused process to find and fix IAM role permissions that allow privilege escalation in AWS.

1. Understand What You’re Looking For

Privilege escalation usually happens when a principal (user/role) can:
  • Attach/Update IAM policies to themselves or to roles they can assume:
    • iam:AttachUserPolicy, iam:AttachRolePolicy, iam:PutUserPolicy, iam:PutRolePolicy, iam:CreatePolicyVersion, iam:SetDefaultPolicyVersion, etc.
  • Assume or pass roles with more privileges:
    • sts:AssumeRole
    • iam:PassRole (combined with other actions)
  • Create or modify access keys / login profiles:
    • iam:CreateAccessKey, iam:UpdateAccessKey, iam:CreateLoginProfile, iam:UpdateLoginProfile
  • Create/Update Lambda, EC2, or other services with privileged roles:
    • lambda:UpdateFunctionCode, lambda:CreateFunction, ec2:RunInstances with a powerful instance profile, etc.
Your goal: Remove or tightly restrict these permissions to least privilege.

2. Inventory IAM Roles and Attached Policies

  1. Sign in to the AWS Management Console with an admin account.
  2. Go to IAM:
    • Top right search bar → type “IAM” → IAM.
  3. In the left navigation, check:
    • Roles
    • Users
    • Policies
You’ll review permissions on:
  • Managed policies (AWS-managed & Customer-managed).
  • Inline policies on users/roles/groups.

3. Identify High-Risk Policies Using IAM Access Analyzer

  1. In IAM console, left menu → Access AnalyzerPolicy analyzer.
  2. Use Policy analyzer to search for policies containing sensitive actions:
    • In Actions filter, enter:
      • iam:*, sts:*, lambda:*, ec2:RunInstances, etc.
  3. For each policy result, open it in a new tab and inspect:
    • Look for statements with Effect: Allow and:
      • Action: "iam:*" or broad wildcards like "*" on Action.
      • Resource: "*".
  4. Prioritize:
    • Policies with Action = "*" and Resource = "*".
    • Policies that allow specific escalation actions (list in section 1).

4. Analyze a Specific Role for Escalation Path

To deep dive into one role:
  1. IAM console → Roles.
  2. Click a role name to inspect it.
  3. Tabs to check:
    • Permissions:
      • Look at each Attached policy and any Inline policies.
      • Click policy name → JSON tab.
    • Trust relationships:
      • Check which principals can assume this role (sts:AssumeRole).
For each attached/inline policy, look for:
  • Problematic Actions: Common privilege-escalation enablers:
    • iam:AttachUserPolicy
    • iam:AttachGroupPolicy
    • iam:AttachRolePolicy
    • iam:PutUserPolicy
    • iam:PutGroupPolicy
    • iam:PutRolePolicy
    • iam:CreatePolicyVersion
    • iam:SetDefaultPolicyVersion
    • iam:PassRole
    • sts:AssumeRole
    • iam:CreateAccessKey
    • iam:UpdateAccessKey
    • iam:CreateLoginProfile
    • iam:UpdateLoginProfile
  • Broad Resources:
    • Resource: "*" on the above actions.
    • Or resources that cover admin roles/policies.
If a role a user has can assume another highly privileged role (via sts:AssumeRole), that is a privilege escalation path.

5. Remediate Policies (Least-Privilege Hardening)

5.1 Remove or Restrict Dangerous IAM Actions

For each risky policy:
  1. IAM → Policies → search for the policy name.
  2. Open policy → Permissions tab → Edit.
  3. In JSON or Visual editor, do the following: a) Remove unneeded IAM-write actions completely
    For example, remove:
    • iam:Attach*
    • iam:Put*
    • iam:CreatePolicyVersion
    • iam:SetDefaultPolicyVersion
    • iam:CreateAccessKey
    • iam:UpdateAccessKey
    • iam:CreateLoginProfile
    • iam:UpdateLoginProfile
    b) Where iam:PassRole is required:
    • Restrict Resource to specific safe roles, not "*".
    • Add conditions like:
    c) Where sts:AssumeRole is required:
    • Restrict to only the specific role ARNs needed.
    • Do not allow "*" for resources.
  4. Click Next, review, then Save changes.
If an AWS-managed policy is risky (you can’t edit it):
  • Detach it from users/roles and replace with a custom, scoped-down customer-managed policy:
    1. PoliciesCreate policy.
    2. Define least-privilege permissions.
    3. Create policy, then Attach it to the target role/user.
    4. Detach the AWS-managed policy from the entity.

5.2 Tighten Trust Policies (Who Can Assume the Role)

  1. IAM → Roles → choose role → Trust relationships tab.
  2. Click Edit trust policy.
  3. Check for:
    • "Principal": "*" or overly broad accounts.
    • Conditions missing on sts:AssumeRole.
  4. Adjust to only allow required principals and, ideally, require conditions. Example (only one account and specific role):
Avoid letting low-privilege roles, wildcards, or external accounts assume highly privileged roles.

6. Use the IAM Policy Simulator to Validate

  1. Go to IAM → Policy Simulator.
  2. Choose User or Role you want to test.
  3. Select services like IAM, STS, Lambda, EC2.
  4. Test specific actions:
    • iam:PassRole, iam:AttachRolePolicy, sts:AssumeRole, iam:CreateAccessKey, etc.
  5. Confirm:
    • Only the minimal, intended actions are allowed.
    • Escalation-enabling combinations are not possible.

7. Add Guardrails: SCPs and Permissions Boundaries (If Using Organizations)

If you use AWS Organizations:
  1. Service Control Policies (SCPs):
    • AWS Organizations console → Policies → Service control policies.
    • Create SCPs that deny dangerous actions for all non-admin accounts, e.g.:
    • Attach SCP to appropriate OUs/accounts.
    • Exclude a tightly-controlled admin account if necessary.
  2. Permissions boundaries (optional, more advanced):
    • Create a boundary policy that excludes privilege-escalation actions.
    • Attach as permission boundary to roles developers can create.

8. Continuous Monitoring

  1. IAM console → Access Analyzer → Analyzer:
    • Enable analyzers to detect broad or external access.
  2. IAM → Credential report:
    • Periodically review user access keys, console access.
  3. Enable CloudTrail and (optionally) CloudTrail Lake / GuardDuty:
    • Monitor for suspicious IAM activity (e.g., new CreatePolicyVersion, SetDefaultPolicyVersion, AttachRolePolicy).

If you share a specific risky role/policy JSON, I can give exact edits line-by-line for remediation.
Below is a practical, CLI‑focused process to identify and fix IAM role permissions that allow privilege escalation in AWS.

1. Know the risky IAM permissions

These actions are commonly used for privilege escalation when overly broad:
  • iam:PassRole
  • iam:PutRolePolicy
  • iam:AttachRolePolicy
  • iam:PutUserPolicy
  • iam:CreatePolicyVersion
  • iam:SetDefaultPolicyVersion
  • iam:UpdateAssumeRolePolicy
  • iam:AddUserToGroup, iam:AttachGroupPolicy
  • sts:AssumeRole
  • sts:AssumeRoleWithWebIdentity
Your goal: find any role that can call these actions in a dangerous way (e.g., unscoped to specific resources, or to Admin policies/roles).

2. Enumerate IAM roles and their policies

For each role (or for ones you suspect):
Look in the policy JSON for Action containing the risky IAM actions above.

3. Identify privilege‑escalation patterns

Flags to look for in the policy JSON:
  1. Wildcard actions:
    • "Action": "iam:*" or "*" on IAM / STS
  2. Unrestricted PassRole:
    • "Action": "iam:PassRole" with "Resource": "*"
  3. Policy modification on high‑privilege policies:
    • iam:AttachRolePolicy, iam:PutRolePolicy, iam:CreatePolicyVersion, iam:SetDefaultPolicyVersion with "Resource": "*"
  4. Trust policies that are too broad:
    • sts:AssumeRole allowed from Principal: "*", or from untrusted accounts/services.
To view a role’s trust policy:

4. Remove or scope dangerous permissions (inline policies)

4.1. Download and edit the inline policy locally

Edit policy.json:
  • Remove unneeded risky actions (e.g., iam:*, iam:PassRole, etc.).
  • Or narrow them:
    • Restrict Resource to only specific ARNs (e.g., just one role that truly needs to be passed).
    • Add Condition (e.g., limit iam:PassRole to certain services).
Example: scope iam:PassRole to a single role:
Re‑apply the edited inline policy:

5. Replace or detach risky managed policies

If a role has broad AWS‑managed or customer‑managed policies (e.g., AdministratorAccess, custom *:* policies):
Create a least‑privilege customer‑managed policy:

6. Lock down trust policies (AssumeRole)

For any role that can lead to higher privilege (e.g., admin roles):
  1. Restrict who can assume it.
  2. Avoid Principal: "*".
  3. Limit to specific AWS accounts, roles, or services.
Get and edit trust policy:
Example safer trust policy (from a specific account/role only):
Apply:

7. Fix dangerous policy versioning rights

If a role can call iam:CreatePolicyVersion or iam:SetDefaultPolicyVersion on sensitive policies, an attacker can swap in an admin version.For customer‑managed policies:
  1. List who can modify them.
  2. Remove those actions, or scope them with conditions (e.g., only to non‑privileged policies, or only a CI/CD role).
To reduce rights, edit the responsible role’s policy as in step 4 and remove:
  • iam:CreatePolicyVersion
  • iam:SetDefaultPolicyVersion
  • iam:DeletePolicyVersion
Then re‑apply with put-role-policy.

8. Validate with the Policy Simulator

Before and after changes, you can check what a role can do:
Verify that high‑risk actions are explicitDeny or not allowed.

9. Optional: enforce org‑wide via SCPs (if using AWS Organizations)

At the org/root or OU level, create SCPs that deny dangerous privilege‑escalation patterns except for tightly controlled admin roles:Example SCP snippet:
Apply with:

If you want, you can paste one specific role’s current policy JSON, and I can show you exactly how to rewrite it to remove the privilege‑escalation paths and give you the exact aws cli commands to apply the fix.
Below is a practical, step‑by‑step remediation approach for AWS IAM privilege‑escalation risks, with Python (boto3) examples.

1. Understand the Common IAM Privilege Escalation Paths

Typical dangerous permissions (especially if a user/principal can call them on themselves or roles they assume):
  • iam:CreatePolicyVersion (with SetAsDefault=true)
  • iam:PutRolePolicy, iam:PutUserPolicy, iam:AttachRolePolicy, iam:AttachUserPolicy, iam:AttachGroupPolicy
  • iam:PassRole (especially combined with EC2, Lambda, Step Functions, etc.)
  • sts:AssumeRole
  • Permissions on Lambda, EC2, Glue, Step Functions, etc., that allow attaching or modifying roles/policies:
    • lambda:UpdateFunctionConfiguration (to change execution role)
    • ec2:RunInstances with instance profile you can control
    • glue:CreateDevEndpoint with role you can pass
  • Wildcards like "Action": "*", "Resource": "*" (especially in combination).
Remediation = remove or restrict these where they are not explicitly needed, and add guardrails (permission boundaries, SCPs, condition keys).

2. Enumerate IAM Roles and Policies (Python/boto3)


3. Identify High‑Risk Permissions in Policies

Define a set of “risky” actions and scan all attached + inline policies.
Usage: loop through roles and attached policies:
This identifies where privilege‑escalation‑prone actions exist.

4. Decide on Remediation Strategy (Per Finding)

Per role/policy combination, you should:
  1. Confirm business need for each risky action.
  2. If not needed:
    • Remove or narrow the statement.
  3. If needed:
    • Restrict resources.
    • Add IAM conditions.
    • Use permission boundaries and/or SCPs.
    • Separate “break‑glass” roles from normal operators.
Below are concrete policy changes and how to apply them via Python.

5. Remediate Excessive iam:PassRole

5.1 Policy Before (too broad)

5.2 Policy After (restricted roles + conditions)

5.3 Update Policy Version via Python

For managed policies:
Typical flow:
  1. Get existing document.
  2. Manually or programmatically modify statements (e.g., change Resource: "*" to specific ARNs; add Condition).
  3. Call create_policy_version with SetAsDefault=True.
  4. Optionally delete old versions later (max 5).

6. Remove or Restrict Delegated Policy Management (iam:*Policy*)

If a role has permissions like iam:CreatePolicyVersion, iam:PutRolePolicy, etc., and it’s not a dedicated IAM admin role:
  1. Create a new, least‑privilege IAM admin role for identity team only.
  2. Remove those actions from operational roles.
Sample adjustment:Before:
After (if minimal is needed):If the role only needs to attach a pre‑approved policy to a specific role:
Apply via same create_policy_version mechanism.For inline policies, update with put_role_policy:

7. Constrain sts:AssumeRole and Trust Policies

Even if role A doesn’t have broad iam:*, it can escalate by assuming a more‑privileged role B.

7.1 Inspect trust policies

7.2 Restrict trust policies

  • Use specific principals, not *.
  • Add conditions like aws:PrincipalTag, aws:SourceAccount, aws:SourceArn.
Before (too open):
After (restricted):
Or with conditions:

8. Guardrails: Permission Boundaries and SCPs (Org‑Level)

8.1 Permission Boundaries (per principal)

Create a boundary policy that forbids escalation actions (or limits them tightly), then attach it as a permission boundary to roles/users that you do not want to be able to escalate.Example permission boundary:
Attach via Python:

8.2 Service Control Policies (SCPs) (Org‑wide)

In AWS Organizations, SCPs can deny dangerous actions account‑wide except for a specific IAM admin role.Example (pseudo; must be applied via Organizations API/console):

9. Special Case: Service‑Based Escalation (Lambda, EC2, etc.)

Even if iam:PassRole is restricted, some combos can still escalate; for each:
  • Lambda: lambda:UpdateFunctionConfiguration to change Role.
  • EC2: ec2:RunInstances with a modifiable instance profile.
  • Step Functions: states:CreateStateMachine with high‑priv role.
Remediation pattern:
  • Constrain Resource to specific functions, instances, state machines.
  • Combine with tight iam:PassRole (only low‑priv roles).
  • Use conditions like iam:PassedToService, ec2:InstanceProfile, or tags.
Example for Lambda:

10. Verification / Regression Checks

After changes:
  1. Use IAM Access Analyzer (console or API) to detect potential privilege escalation.
  2. Re‑run your Python audit script to ensure:
    • No unexpected iam:*Policy* / iam:PassRole / sts:AssumeRole wildcards.
    • No Action: "*" + Resource: "*" for non‑admin roles.
  3. Test critical workflows to confirm business operations continue to function.

If you want, I can:
  • Help you adapt the audit script to automatically suggest a “patched” policy document, or
  • Focus on a specific privileged role’s policies and walk through concrete JSON diffs.
Changing an existing aws_iam_policy in Terraform (rather than editing inline JSON only) forces replacement of the policy resource; any existing attachments will be recreated by Terraform, which may briefly remove and reattach the policy during apply.For verification, terraform plan should show: removal of the old IAM policy resource (with privilege‑escalation actions), creation of the new restricted aws_iam_policy, and updates to aws_iam_role_policy_attachment resources so that the role is attached only to the remediated policy.