Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 202 additions & 0 deletions content/aws/exploitation/obfuscated_admin_policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
---
author_name: Raajhesh Kannaa Chidambaram
title: Obfuscated Admin IAM Policy
description: Using IAM action wildcards to create policies that grant admin-equivalent access while evading name-based detections.
---

# Obfuscated Admin IAM Policy

<div class="grid cards" markdown>
- :material-book:{ .lg .middle } __Additional Resources__

---

- [IAM JSON Policy Elements: Action](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_action.html)
- [IAM Policy Simulator](https://policysim.aws.amazon.com/)
- [Access Analyzer Policy Validation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-policy-validation.html)
</div>

When an attacker gains the ability to create or modify IAM policies (e.g., via `iam:CreatePolicy`, `iam:CreatePolicyVersion`, or `iam:PutUserPolicy`), the obvious move is to attach `AdministratorAccess` or create a policy with `"Action": "*"`. Both are trivially detected by security tooling that matches on known policy ARNs or exact string comparisons.

A subtler approach is to use IAM's built-in wildcard matching to construct policies that are functionally equivalent to admin access but don't match simple detection patterns.

## How IAM Wildcard Matching Works

IAM supports two wildcard characters in the `Action` element of policy statements:

- `*` matches any combination of characters (including none)
- `?` matches any single character

These are evaluated at request time by the IAM policy engine. This means `s3:Get*` matches `s3:GetObject`, `s3:GetBucketPolicy`, and every other `s3:Get` action. The `?` wildcard matches exactly one character, so `?am:*` matches both `iam:*` and `ram:*`.

## Obfuscation Techniques

### Technique 1: Service-Action Wildcard Split

Instead of `"Action": "*"`, use `"Action": "*:*"`. This is functionally identical. The `*` before the colon matches any service prefix, and the `*` after the colon matches any action. Most pattern-matching detections look for the literal string `"*"` as a standalone action, not `"*:*"`.

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*:*",
"Resource": "*"
}
]
}
```

### Technique 2: Single-Character Wildcards on Service Names

The `?` wildcard lets you target specific services without spelling them out. This bypasses detections that look for exact service prefixes.

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"?am:*",
"s?s:*",
"?t?:*",
"??2:*",
"?3:*",
"???bda:*",
"???s:*"
],
"Resource": "*"
}
]
}
```

Breakdown of what these match:

| Pattern | Matches |
|---------|---------|
| `?am:*` | `iam:*`, `ram:*` |
| `s?s:*` | `sqs:*`, `sns:*`, `sms:*` |
| `?t?:*` | `sts:*`, `sts:*` |
| `??2:*` | `ec2:*`, `ss2:*` |
| `?3:*` | `s3:*` |
| `???bda:*` | `lambda:*` |
| `???s:*` | `logs:*`, `ecs:*`, `eks:*`, `sqs:*`, `sns:*`, `kms:*` |

This approach is noisier (it may match unintended services) but that is a feature, not a bug, from an attacker's perspective. More permissions make it harder to pinpoint the intent.

### Technique 3: Partial Action Wildcards

Rather than granting `*` on entire services, you can use wildcards within action names to cover critical operations while looking innocuous.

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:Creat*",
"iam:Attac*",
"iam:Put*",
"iam:Pass*",
"iam:Delet*",
"iam:Updat*",
"iam:List*",
"iam:Get*",
"sts:As*",
"s3:*bject*",
"ec2:Run*",
"ec2:Describe*",
"lambda:Creat*",
"lambda:Invok*",
"lambda:Updat*"
],
"Resource": "*"
}
]
}
```

This covers the most impactful IAM, STS, S3, EC2, and Lambda operations without using a single bare `*` action. Detections that only flag `"Action": "*"` or `AdministratorAccess` miss this entirely.

### Technique 4: Multiple Statements with Broad Wildcards

Split the policy across multiple statements. Some tools only evaluate individual statements rather than the aggregate effect of the full policy.

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadOnly",
"Effect": "Allow",
"Action": [
"*:Get*",
"*:List*",
"*:Describe*"
],
"Resource": "*"
},
{
"Sid": "Operations",
"Effect": "Allow",
"Action": [
"*:Create*",
"*:Delete*",
"*:Update*",
"*:Put*",
"*:Attach*",
"*:Detach*"
],
"Resource": "*"
},
{
"Sid": "Invoke",
"Effect": "Allow",
"Action": [
"*:Run*",
"*:Start*",
"*:Stop*",
"*:Invoke*",
"*:Execute*"
],
"Resource": "*"
}
]
}
```

Each statement looks like it grants a specific category of operations. Together, they cover nearly all AWS actions across all services.

## Combining with Inline Policies

Managed policies (including `AdministratorAccess`) show up in `iam:ListAttachedUserPolicies` and `iam:ListAttachedRolePolicies`. Inline policies are stored differently and require `iam:GetUserPolicy` or `iam:GetRolePolicy` to retrieve. Placing the obfuscated policy as an inline policy on a user or role adds another layer of evasion.

```bash
aws iam put-user-policy \
--user-name target-user \
--policy-name AmazonPersonalizeReadOnly \
--policy-document file://obfuscated-admin.json
```

Note the deliberately misleading policy name. Inline policy names are freeform strings with no validation against their actual contents.

## Detection Guidance

Detecting these patterns requires going beyond simple string matching:

1. **Use IAM Access Analyzer Policy Validation.** The [`ValidatePolicy`](https://docs.aws.amazon.com/access-analyzer/latest/APIReference/API_ValidatePolicy.html) API flags overly permissive policies, including those using wildcards. Run this against all policies periodically.

2. **Expand wildcards before evaluation.** Tools like [Parliament](https://github.com/duo-labs/parliament) and [AWS IAM Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html) can resolve wildcard patterns against the full list of known AWS actions and determine the effective permission set.

3. **Monitor policy creation and modification events in CloudTrail.** Key events to watch:
- `CreatePolicy` / `CreatePolicyVersion`
- `PutUserPolicy` / `PutRolePolicy` / `PutGroupPolicy`
- Look for `?` or `*:*` patterns in the policy document within the CloudTrail event.

4. **Flag any policy granting `Resource: "*"` with broad action patterns.** A policy that uses wildcards in the service prefix portion of the action (e.g., `*:*`, `?am:*`) should be treated as high severity regardless of the action specifics.

5. **Compare effective permissions.** Use `iam:SimulatePrincipalPolicy` to test what a principal can actually do, rather than relying on policy document parsing alone.
Loading