This report documents a hands‑on offensive security lab conducted in an AWS Free Tier account using console‑only access. The objective was to simulate a real-world attacker who gains access to a low‑privileged IAM user and attempts to escalate privileges through IAM trust and permission misconfigurations.
The lab successfully demonstrated a critical privilege-escalation path using the iam:PassRole permission combined with minimal EC2 permissions. Although the attacker identity never became an IAM administrator, they were able to cause AWS services to execute with full administrative privileges, representing a complete compromise in practice.
attacker-useriam:Get*, iam:List*, iam:PassRole, minimal EC2 permissions (RunInstances, required Describe*)AdminEC2Role with AdministratorAccess trusted by EC2AdminEC2Role as a high-value target.AdminEC2Role in the IAM instance profile dropdown and launched an instance with administrative privileges.ec2:DescribeInstances denied) but impact was still achieved.AdministratorAccess can be launchediam:PassRole without conditionsiam:PassRole Usage"Condition": {
"StringEquals": {
"iam:PassedToService": "ec2.amazonaws.com"
}
}
Only allow roles to be passed to specific services that require them. Audit all users and policies with iam:PassRole privileges.
Apply IAM permission boundaries to high-privilege roles to prevent roles from exceeding intended access even if PassRole is abused.
Restrict service principals to only what is necessary. Avoid overly broad * trust relationships.
Enable CloudTrail logging for all iam:PassRole, RunInstances, and sensitive actions. Set up alerts for unusual role attachment or privilege escalation patterns.
Regularly analyze combined permissions across users, roles, and services. Identify risky compositions before they are exploited.
This lab demonstrates that least-privilege enforcement must consider cross-service interactions, not just individual IAM policies. Even when visibility and console actions are restricted, iam:PassRole can be exploited for full administrative compromise. Implementing the remediation checklist above will significantly reduce the risk of privilege escalation.
Lab Outcome:
This section translates the offensive lab into actionable defensive controls. The goal is not to patch a single bug, but to eliminate the entire class of IAM privilege‑escalation failures.
iam:PassRoleAction: Inventory all principals with iam:PassRole. Remove wildcard role resources.
Secure Pattern:
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam:::role/SpecificRole",
"Condition": {
"StringEquals": {
"iam:PassedToService": "ecs-tasks.amazonaws.com"
}
}
}
Security Lesson: iam:PassRole without iam:PassedToService is equivalent to administrator access by proxy.
Action: Detach admin policies temporarily. Review CloudTrail for recent AssumeRole.
Why: STS credentials remain valid after abuse unless explicitly mitigated.
Insecure:
{"Principal": {"Service": "ec2.amazonaws.com"}}
Hardened:
{
"Principal": {"Service": "ec2.amazonaws.com"},
"Condition": {
"StringEquals": {
"aws:SourceAccount": ""
}
}
}
Rule: Humans assume roles. Services execute roles. Never both. This blocks lateral trust abuse.
Apply permission boundaries to all execution roles.
{
"Effect": "Deny",
"Action": ["iam:*", "organizations:*"],
"Resource": "*"
}
Even if a role is misused, IAM remains protected.
Replace:
"iam:Get*", "iam:List*"
With resource‑scoped reads where possible.
Ask: What happens if this identity gains one more permission?
IAM failures occur at policy intersections.
Alert on:
iam:PassRoleRunInstancesCorrelate events — not single actions.
AWS services will faithfully execute whatever IAM allows. Security failures happen when trust boundaries blur — not when attackers are clever.