AWS - Nitro Enum

Aprende hacking en AWS desde cero hasta experto con htARTE (Experto en Equipo Rojo de HackTricks en AWS)!

Otras formas de apoyar a HackTricks:

Información Básica

AWS Nitro es un conjunto de tecnologías innovadoras que forman la plataforma subyacente para las instancias de AWS EC2. Introducido por Amazon para mejorar la seguridad, el rendimiento y la confiabilidad, Nitro aprovecha componentes de hardware personalizados y un hipervisor ligero. Abstrae gran parte de la funcionalidad de virtualización tradicional a hardware y software dedicados, minimizando la superficie de ataque y mejorando la eficiencia de recursos. Al descargar funciones de virtualización, Nitro permite a las instancias de EC2 ofrecer un rendimiento casi bare-metal, lo que lo hace particularmente beneficioso para aplicaciones intensivas en recursos. Además, el Chip de Seguridad Nitro garantiza específicamente la seguridad del hardware y firmware, fortaleciendo aún más su arquitectura robusta.

Enclaves Nitro

AWS Nitro Enclaves proporciona un entorno de cálculo seguro e aislado dentro de las instancias de Amazon EC2, diseñado específicamente para procesar datos altamente sensibles. Aprovechando el Sistema AWS Nitro, estos enclaves garantizan un aislamiento y seguridad robustos, ideales para manejar información confidencial como PII o registros financieros. Cuentan con un entorno minimalista, reduciendo significativamente el riesgo de exposición de datos. Además, los Enclaves Nitro admiten la atestación criptográfica, lo que permite a los usuarios verificar que solo se está ejecutando código autorizado, crucial para mantener estrictos estándares de cumplimiento y protección de datos.

Las imágenes de Enclave Nitro se ejecutan desde dentro de las instancias de EC2 y no se puede ver desde la consola web de AWS si una instancia de EC2 está ejecutando imágenes en Enclave Nitro o no.

Instalación de CLI de Enclave Nitro

Sigue todas las instrucciones de la documentación. Sin embargo, estas son las más importantes:

# Install tools
sudo amazon-linux-extras install aws-nitro-enclaves-cli -y
sudo yum install aws-nitro-enclaves-cli-devel -y

# Config perms
sudo usermod -aG ne $USER
sudo usermod -aG docker $USER

# Check installation
nitro-cli --version

# Start and enable the Nitro Enclaves allocator service.
sudo systemctl start nitro-enclaves-allocator.service && sudo systemctl enable nitro-enclaves-allocator.service

Imágenes de Nitro Enclave

Las imágenes que puedes ejecutar en Nitro Enclave están basadas en imágenes de docker, por lo que puedes crear tus propias imágenes de Nitro Enclave a partir de imágenes de docker como:

# You need to have the docker image accesible in your running local registry
# Or indicate the full docker image URL to access the image
nitro-cli build-enclave --docker-uri <docker-img>:<tag> --output-file nitro-img.eif

Como puedes ver, las imágenes de Nitro Enclave utilizan la extensión eif (Enclave Image File).

La salida se verá similar a:

Using the locally available Docker image...
Enclave Image successfully created.
{
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "e199261541a944a93129a52a8909d29435dd89e31299b59c371158fc9ab3017d9c450b0a580a487e330b4ac691943284",
"PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
"PCR2": "2e1fca1dbb84622ec141557dfa971b4f8ea2127031b264136a20278c43d1bba6c75fea286cd4de9f00450b6a8db0e6d3"
}
}

Ejecutar una imagen

Según la documentación, para ejecutar una imagen de enclave necesitas asignarle memoria de al menos 4 veces el tamaño del archivo eif. Es posible configurar los recursos predeterminados para asignarle en el archivo.

/etc/nitro_enclaves/allocator.yaml

¡Siempre recuerda que necesitas reservar algunos recursos para la instancia EC2 principal también!

Después de conocer los recursos para asignar a una imagen e incluso haber modificado el archivo de configuración, es posible ejecutar una imagen de enclave con:

# Restart the service so the new default values apply
sudo systemctl start nitro-enclaves-allocator.service && sudo systemctl enable nitro-enclaves-allocator.service

# Indicate the CPUs and memory to give
nitro-cli run-enclave --cpu-count 2 --memory 3072 --eif-path hello.eif --debug-mode --enclave-cid 16

Enumerar Enclaves

Si comprometes un host de EC2, es posible obtener una lista de imágenes de enclaves en ejecución con:

nitro-cli describe-enclaves

No es posible obtener una shell dentro de una imagen de enclave en ejecución porque ese es el propósito principal del enclave, sin embargo, si usaste el parámetro --debug-mode, es posible obtener su stdout con:

ENCLAVE_ID=$(nitro-cli describe-enclaves | jq -r ".[0].EnclaveID")
nitro-cli console --enclave-id ${ENCLAVE_ID}

Terminar Enclaves

Si un atacante compromete una instancia de EC2, por defecto no podrá obtener una shell dentro de ellas, pero podrá terminarlas con:

nitro-cli terminate-enclave --enclave-id ${ENCLAVE_ID}

Vsock

La única forma de comunicarse con una imagen en ejecución de enclave es usando vsocks.

Socket Virtual (vsock) es una familia de sockets en Linux diseñada específicamente para facilitar la comunicación entre máquinas virtuales (VMs) y sus hipervisores, o entre las propias VMs. Vsock permite una comunicación bidireccional eficiente sin depender de la pila de red del host. Esto hace posible que las VMs se comuniquen incluso sin configuraciones de red, utilizando un ID de Contexto (CID) de 32 bits y números de puerto para identificar y gestionar conexiones. La API de vsock admite tanto tipos de sockets de flujo como de datagramas, similares a TCP y UDP, proporcionando una herramienta versátil para aplicaciones a nivel de usuario en entornos virtuales.

Por lo tanto, una dirección vsock se ve así: <CID>:<Puerto>

Para encontrar los CIDs de las imágenes en ejecución del enclave, simplemente puedes ejecutar el siguiente comando y obtener el EnclaveCID:

nitro-cli describe-enclaves

[
{
"EnclaveName": "ejemplo-canal-seguro",
"EnclaveID": "i-0bc274f83ade02a62-enc18ef3d09c886748",
"ProcessID": 10131,
    "EnclaveCID": 16,
    "NumberOfCPUs": 2,
"CPUIDs": [
1,
3
],
"MemoryMiB": 1024,
"State": "RUNNING",
"Flags": "DEBUG_MODE",
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "e199261541a944a93129a52a8909d29435dd89e31299b59c371158fc9ab3017d9c450b0a580a487e330b4ac691943284",
"PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
"PCR2": "2e1fca1dbb84622ec141557dfa971b4f8ea2127031b264136a20278c43d1bba6c75fea286cd4de9f00450b6a8db0e6d3"
}
}
]

¡Ten en cuenta que desde el host no hay forma de saber si un CID está exponiendo algún puerto! A menos que uses algún escáner de puertos vsock como https://github.com/carlospolop/Vsock-scanner.

Servidor/Listener Vsock

Aquí tienes un par de ejemplos:

Listener Simple en Python

```python #!/usr/bin/env python3

From

https://medium.com/@F.DL/understanding-vsock-684016cf0eb0

import socket

CID = socket.VMADDR_CID_HOST PORT = 9999

s = socket.socket(socket.AF_VSOCK, socket.SOCK_STREAM) s.bind((CID, PORT)) s.listen() (conn, (remote_cid, remote_port)) = s.accept()

print(f"Connection opened by cid={remote_cid} port={remote_port}")

while True: buf = conn.recv(64) if not buf: break

print(f"Received bytes: {buf}")

</details>
```bash
# Using socat
socat VSOCK-LISTEN:<port>,fork EXEC:"echo Hello from server!"

Cliente Vsock

Ejemplos:

Última actualización