Listen to this Post

Introduction:
AWS IAM assigns every user and role a unique ID (e.g., `AIDA…` for users, `AROA…` for roles) that is often considered a dead‑end identifier—unlike the human‑readable ARN. However, an undocumented AWS behavior allows you to resolve these opaque IDs back to full ARNs by leveraging a resource‑based policy, such as an IAM role trust policy. This technique is a goldmine for cloud penetration testers and red teamers performing enumeration or privilege escalation.
Learning Objectives:
- Understand how IAM unique IDs differ from ARNs and why they are typically considered low‑value.
- Learn a practical method to convert an `AIDA` or `AROA` ID into a full ARN using a role trust policy.
- Apply this technique with AWS CLI commands, automation scripts, and detection avoidance strategies.
1. The Hidden Policy Rewrite Behavior
AWS allows you to specify a Principal in a resource‑based policy using the unique ID instead of the ARN. When you save the policy, the AWS console (and API) will warn you that the principal is invalid—but if you proceed and then refresh, AWS automatically rewrites the policy with the resolved ARN.
Step‑by‑step guide – Manual (Console):
- Create a temporary IAM role (or use an existing one you control).
2. Edit its Trust Relationship policy.
- Set the `Principal` to the unique ID you want to resolve, for example:
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "AWS": "AROA1234567890EXAMPLE" }, "Action": "sts:AssumeRole" }] } - Ignore the “Principal is not valid” warning and save.
- Refresh the trust policy page – AWS will replace the unique ID with the full ARN.
Step‑by‑step guide – AWS CLI (automated):
Create a temporary role
aws iam create-role --role-name TempResolveRole --assume-role-policy-document '{"Version":"2012-10-17","Statement":[]}'
Get the unique ID of a target role (example)
TARGET_ID="AROA1234567890EXAMPLE"
Put a trust policy with the unique ID as Principal
aws iam put-role-policy --role-name TempResolveRole --policy-name ResolvePolicy --policy-document '{
"Version":"2012-10-17",
"Statement":[{
"Effect":"Allow",
"Principal":{"AWS":"'$TARGET_ID'"},
"Action":"sts:AssumeRole"
}]
}'
Retrieve the policy and see the rewritten ARN
aws iam get-role-policy --role-name TempResolveRole --policy-name ResolvePolicy --query 'PolicyDocument.Statement[bash].Principal.AWS' --output text
Clean up
aws iam delete-role-policy --role-name TempResolveRole --policy-name ResolvePolicy
aws iam delete-role --role-name TempResolveRole
What this does: The CLI version replicates the console behaviour – when you put-role-policy, AWS validates and stores the policy. On retrieval, the unique ID is automatically transformed into the canonical ARN if the principal exists in the same account.
2. Enumerating Unique IDs from CloudTrail & S3
Before you can resolve an ID, you need to find one. Unique IDs appear in many places: CloudTrail logs (userIdentity.principalId), S3 bucket policies, and even error messages.
Step‑by‑step – Extract IDs from CloudTrail (Linux):
Download CloudTrail logs (JSON) and extract all unique principal IDs
aws s3 cp s3://your-cloudtrail-bucket/ ./trail-logs/ --recursive
grep -rhoE 'principalId":"([A-Z0-9]{21,})' ./trail-logs/ | cut -d'"' -f4 | sort -u
Step‑by‑step – Extract IDs from S3 bucket policies (Windows PowerShell):
List all buckets, get their policies, and extract AIDA/AROA patterns
Get-S3Bucket | ForEach-Object {
try {
$policy = Get-S3BucketPolicy -BucketName $<em>.BucketName -ErrorAction Stop
if ($policy -match 'AIDA\w+|AROA\w+') {
Write-Host "Bucket: $($</em>.BucketName) - Found: $($matches[bash])"
}
} catch { }
}
Using the enumeration result: Feed any extracted `AIDA` or `AROA` into the resolution method from Section 1 to map them to actual ARNs – revealing exactly which IAM user or role performed an action.
- Linux & Windows Commands for Live AWS Enumeration
Here are essential CLI commands to complement the ARN‑resolution trick.
| Operation | Linux / macOS (AWS CLI) | Windows (PowerShell) |
|–|-|-|
| List all IAM users and their unique IDs | `aws iam list-users –query ‘Users[].[UserName,UserId]’ –output table` | `Get-IAMUserList \| Select UserName,UserId` |
| List IAM roles with unique IDs | `aws iam list-roles –query ‘Roles[].[RoleName,RoleId]’ –output table` | `Get-IAMRoleList \| Select RoleName,RoleId` |
| Get a role’s trust policy (post‑resolution) | `aws iam get-role –role-name TargetRole –query ‘Role.AssumeRolePolicyDocument’` | `Get-IAMRole -RoleName TargetRole \| Select AssumeRolePolicyDocument` |
| Check for existing policies that already use unique IDs | `aws iam list-role-policies –role-name TempRole` | `Get-IAMRolePolicyList -RoleName TempRole` |
One‑liner proactive enumeration:
For every role in the account, try to resolve its own unique ID (if it appears as a principal somewhere)
aws iam list-roles --query 'Roles[].RoleId' --output text | tr '\t' '\n' | while read id; do echo "Resolving $id"; aws iam put-role-policy --role-name YourTempRole --policy-name test --policy-document "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"$id\"},\"Action\":\"sts:AssumeRole\"}]}" && aws iam get-role-policy --role-name YourTempRole --policy-name test --query 'PolicyDocument.Statement[bash].Principal.AWS' --output text; aws iam delete-role-policy --role-name YourTempRole --policy-name test; done
4. Automating ARN Resolution (Bash & PowerShell)
Instead of manually creating roles, use these scripts to resolve a list of unique IDs in bulk.
Linux – Bash script:
!/bin/bash
resolve_arn.sh - Takes a file with one unique ID per line, outputs ID -> ARN
TEMP_ROLE="AutoResolveRole_$(date +%s)"
aws iam create-role --role-name $TEMP_ROLE --assume-role-policy-document '{"Version":"2012-10-17","Statement":[]}' > /dev/null
while read id; do
echo -n "$id -> "
aws iam put-role-policy --role-name $TEMP_ROLE --policy-name resolve --policy-document "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"$id\"},\"Action\":\"sts:AssumeRole\"}]}" 2>/dev/null
arn=$(aws iam get-role-policy --role-name $TEMP_ROLE --policy-name resolve --query 'PolicyDocument.Statement[bash].Principal.AWS' --output text 2>/dev/null)
if [ -n "$arn" ]; then echo "$arn"; else echo "NOT RESOLVABLE"; fi
aws iam delete-role-policy --role-name $TEMP_ROLE --policy-name resolve 2>/dev/null
done < "$1"
aws iam delete-role --role-name $TEMP_ROLE > /dev/null
Windows – PowerShell script:
resolve_arn.ps1
param([bash]$IdListFile)
$TempRole = "AutoResolveRole_" + [System.DateTime]::Now.Ticks
New-IAMRole -RoleName $TempRole -AssumeRolePolicyDocument '{"Version":"2012-10-17","Statement":[]}' | Out-Null
Get-Content $IdListFile | ForEach-Object {
$id = $_;
Write-Host -NoNewline "$id -> ";
$policyDoc = @"
{
"Version":"2012-10-17",
"Statement":[{
"Effect":"Allow",
"Principal":{"AWS":"$id"},
"Action":"sts:AssumeRole"
}]
}
"@
try {
Write-IAMRolePolicy -RoleName $TempRole -PolicyName resolve -PolicyDocument $policyDoc -ErrorAction Stop
$arn = (Get-IAMRolePolicy -RoleName $TempRole -PolicyName resolve).PolicyDocument.Statement[bash].Principal.AWS
Write-Host $arn
} catch {
Write-Host "NOT RESOLVABLE"
}
Remove-IAMRolePolicy -RoleName $TempRole -PolicyName resolve -ErrorAction SilentlyContinue
}
Remove-IAMRole -RoleName $TempRole -Force
5. API Security & Cloud Hardening – Mitigations
This ARN resolution trick works because AWS resolves the unique ID at policy evaluation time. To protect your environment:
Detection via CloudTrail:
Look for these `eventName` values with unusual patterns:
– `PutRolePolicy` – especially when the policy document contains `AIDA` or AROA.
– `CreateRole` followed by rapid `PutRolePolicy` and `DeleteRolePolicy` – indicates automated enumeration.
CloudWatch query example:
SELECT userIdentity.arn, eventName, requestParameters.roleName, requestParameters.policyDocument
FROM cloudtrail_logs
WHERE eventName IN ('PutRolePolicy', 'DeleteRolePolicy')
AND requestParameters.policyDocument LIKE '%AIDA%' OR requestParameters.policyDocument LIKE '%AROA%'
Hardening Recommendations:
- Restrict who can create or modify IAM roles – use least‑privilege and MFA‑protected actions.
- Enable SCPs in AWS Organizations to block `iam:PutRolePolicy` for untrusted principals.
- Monitor for repeated `PutRolePolicy` / `DeleteRolePolicy` from the same source IP within short timeframes.
- Use AWS Config rule `iam-role-managed-policy-check` to detect roles with overly permissive trust policies.
What Undercode Say:
- Key Takeaway 1: AWS unique IDs (
AIDA,AROA) are not anonymous – they can be trivially converted to ARNs using built‑in policy resolution, exposing principal identities that attackers may otherwise overlook. - Key Takeaway 2: This behavior is not a vulnerability but an information disclosure feature that becomes a powerful enumeration tool in the wrong hands. Defenders must monitor `PutRolePolicy` events for random unique ID strings.
Analysis: The technique exploits AWS’s internal policy normalization – the same mechanism that allows you to write `Principal: { “AWS”: “123456789012” }` (account ID) instead of a full ARN. AWS tries to be helpful by resolving any identifier that matches an existing principal. For cloud security assessments, this method fills a critical gap: previously, if you only had a CloudTrail principalId, you couldn’t easily map it to an IAM user name. Now, with a few CLI commands, you can. Red teams should incorporate this into their enumeration playbooks; blue teams should audit trust policies for principal entries that look like random strings and implement real‑time alerts.
Prediction: AWS is unlikely to “patch” this because it’s a side effect of a desirable feature (flexible principal specification). Instead, expect future IAM updates to differentiate between “principal exists” and “principal is valid for this action” – but that would break many legitimate cross‑account setups. In the short term, attackers will add this to their standard toolkit, and defenders will shift to detection rather than prevention. Organisations relying on the obscurity of unique IDs for security should consider this a wake‑up call: always use ARN‑based conditions and enable detailed CloudTrail logging.
▶️ Related Video (76% Match):
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: Derive A – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


