|
| 1 | +--- |
| 2 | +author_name: Raajhesh Kannaa Chidambaram |
| 3 | +title: Enumerate AWS Metadata via IAM Condition Keys |
| 4 | +description: Abuse IAM policy condition keys to enumerate account IDs, organization IDs, and resource tag values from accessible AWS resources. |
| 5 | +--- |
| 6 | + |
| 7 | +# Enumerate AWS Metadata via IAM Condition Keys |
| 8 | + |
| 9 | +<div class="grid cards" markdown> |
| 10 | + |
| 11 | +- :material-account:{ .lg .middle } __Original Research__ |
| 12 | + |
| 13 | + --- |
| 14 | + |
| 15 | + <aside style="display:flex"> |
| 16 | + <p><a href="https://cloudar.be/awsblog/finding-the-account-id-of-any-public-s3-bucket/">Finding the Account ID of any public S3 bucket</a> by <a href="https://twitter.com/benbridts">Ben Bridts</a></p> |
| 17 | + </aside> |
| 18 | + |
| 19 | + <aside style="display:flex"> |
| 20 | + <p><a href="https://www.plerion.com/blog/conditional-love-for-aws-metadata-enumeration">Conditional Love for AWS Metadata Enumeration</a> by <a href="https://github.com/dagrz">Daniel Grzelak</a> (Plerion)</p> |
| 21 | + </aside> |
| 22 | + |
| 23 | +- :material-tools:{ .lg .middle } __Tools mentioned in this article__ |
| 24 | + |
| 25 | + --- |
| 26 | + |
| 27 | + [conditional-love](https://github.com/plerionhq/conditional-love) |
| 28 | + |
| 29 | +</div> |
| 30 | + |
| 31 | +## Overview |
| 32 | + |
| 33 | +AWS IAM policies support condition keys that are evaluated at request time. Some of these condition keys reference resource metadata like account IDs, organization IDs, and tag values. By crafting IAM policies with wildcard conditions and observing whether API calls succeed or fail, an attacker can extract this metadata character by character. |
| 34 | + |
| 35 | +This technique was first demonstrated by [Ben Bridts](https://cloudar.be/awsblog/finding-the-account-id-of-any-public-s3-bucket/) in 2021 for extracting account IDs from public S3 buckets using the `s3:ResourceAccount` condition key. [Daniel Grzelak](https://www.plerion.com/blog/conditional-love-for-aws-metadata-enumeration) at Plerion generalized this approach and released [conditional-love](https://github.com/plerionhq/conditional-love), a tool that applies it across multiple AWS services and condition types. |
| 36 | + |
| 37 | +## How It Works |
| 38 | + |
| 39 | +The attack uses IAM policy evaluation as an oracle. The attacker controls their own IAM principal and can create or modify policies attached to it. |
| 40 | + |
| 41 | +**Step 1:** The attacker creates a policy that allows access to a target resource, but only if a condition key matches a wildcard pattern: |
| 42 | + |
| 43 | +```json |
| 44 | +{ |
| 45 | + "Version": "2012-10-17", |
| 46 | + "Statement": [{ |
| 47 | + "Effect": "Allow", |
| 48 | + "Action": "s3:GetObject", |
| 49 | + "Resource": "arn:aws:s3:::target-bucket/*", |
| 50 | + "Condition": { |
| 51 | + "StringLike": { |
| 52 | + "s3:ResourceAccount": "9*" |
| 53 | + } |
| 54 | + } |
| 55 | + }] |
| 56 | +} |
| 57 | +``` |
| 58 | + |
| 59 | +**Step 2:** The attacker makes an API call against the target resource. If the call succeeds, the account ID starts with `9`. If it fails with `AccessDenied`, it does not. |
| 60 | + |
| 61 | +**Step 3:** Repeat with `90*`, `91*`, `92*`... narrowing down one character at a time until the full 12-digit account ID is recovered. This takes at most ~120 API calls (12 digits x 10 possibilities each). |
| 62 | + |
| 63 | +The same approach works for any condition key that supports `StringLike` with wildcards. |
| 64 | + |
| 65 | +## What Can Be Enumerated |
| 66 | + |
| 67 | +| Condition Key | What It Reveals | |
| 68 | +|---|---| |
| 69 | +| `aws:ResourceAccount` / `s3:ResourceAccount` | Account ID of the resource owner | |
| 70 | +| `aws:ResourceOrgID` | AWS Organization ID | |
| 71 | +| `aws:ResourceOrgPaths` | Full organizational unit path | |
| 72 | +| `aws:ResourceTag/{key}` | Tag values (if you know the tag key name) | |
| 73 | +| `lambda:FunctionArn` | Lambda function ARN components | |
| 74 | + |
| 75 | +## Supported Services |
| 76 | + |
| 77 | +The [conditional-love](https://github.com/plerionhq/conditional-love) tool supports enumeration through: |
| 78 | + |
| 79 | +- **S3** via `HeadObject` |
| 80 | +- **Lambda Function URLs** (when using `AWS_IAM` auth mode) |
| 81 | +- **API Gateway** (when using `AWS_IAM` auth mode) |
| 82 | +- **STS** via `AssumeRole` |
| 83 | +- **SQS** via `ReceiveMessage` |
| 84 | +- **AWS Data Exchange** via `GetDataSet` |
| 85 | + |
| 86 | +Any service where the attacker's principal has some access to the target resource and AWS evaluates condition keys can potentially be used. |
| 87 | + |
| 88 | +## Using conditional-love |
| 89 | + |
| 90 | +Install and run the tool: |
| 91 | + |
| 92 | +```bash |
| 93 | +git clone https://github.com/plerionhq/conditional-love.git |
| 94 | +cd conditional-love |
| 95 | +pip install -r requirements.txt |
| 96 | +python conditional_love.py \ |
| 97 | + --target-type s3 \ |
| 98 | + --target-value my-target-bucket \ |
| 99 | + --condition-key s3:ResourceAccount |
| 100 | +``` |
| 101 | + |
| 102 | +The tool handles the binary search automatically and outputs the discovered value. |
| 103 | + |
| 104 | +## Security Implications |
| 105 | + |
| 106 | +The most dangerous application is **tag value exfiltration**. Organizations often store meaningful data in resource tags: cost center codes, owner email addresses, environment names, or project identifiers. If an attacker knows (or guesses) the tag key name, they can extract the value from any resource they can access. |
| 107 | + |
| 108 | +Account IDs and organization IDs are also valuable for reconnaissance. Knowing the account ID enables further attacks like [enumerating IAM principals](../enumeration/enum_iam_user_role.md) or crafting targeted phishing with knowledge of the internal org structure. |
| 109 | + |
| 110 | +## Mitigations |
| 111 | + |
| 112 | +- **Never store sensitive information in resource tags.** AWS [explicitly discourages](https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html) using tags for confidential data. |
| 113 | +- **Publish shared resources from isolated accounts.** If you share AMIs, Lambda layers, or S3 buckets publicly, use a purpose-built account separate from production. |
| 114 | +- **Restrict resource policies to authorized principals.** The technique requires the attacker to have some level of access to the target resource. |
| 115 | +- **Monitor for unusual IAM policy modifications.** Policies with `StringLike` conditions using wildcards against `ResourceAccount` or `ResourceTag` keys may indicate enumeration attempts. |
0 commit comments