AWS - Nitro Enum

Supporta HackTricks

Informazioni di base

AWS Nitro è una suite di tecnologie innovative che costituiscono la piattaforma sottostante per le istanze AWS EC2. Introdotto da Amazon per migliorare la sicurezza, le prestazioni e l'affidabilità, Nitro sfrutta componenti hardware personalizzati e un hypervisor leggero. Astrae gran parte della funzionalità di virtualizzazione tradizionale su hardware e software dedicati, minimizzando la superficie di attacco e migliorando l'efficienza delle risorse. Delegando le funzioni di virtualizzazione, Nitro consente alle istanze EC2 di offrire prestazioni quasi bare-metal, rendendolo particolarmente vantaggioso per applicazioni ad alta intensità di risorse. Inoltre, il Nitro Security Chip garantisce specificamente la sicurezza dell'hardware e del firmware, consolidando ulteriormente la sua architettura robusta.

Nitro Enclaves

AWS Nitro Enclaves fornisce un ambiente di calcolo sicuro e isolato all'interno delle istanze Amazon EC2, specificamente progettato per elaborare dati altamente sensibili. Sfruttando il sistema AWS Nitro, questi enclavi garantiscono un'isolamento e sicurezza robusti, ideali per gestire informazioni riservate come PII o registri finanziari. Presentano un ambiente minimalista, riducendo significativamente il rischio di esposizione dei dati. Inoltre, Nitro Enclaves supporta l'attestazione crittografica, consentendo agli utenti di verificare che solo il codice autorizzato sia in esecuzione, cruciale per mantenere standard rigorosi di conformità e protezione dei dati.

Le immagini Nitro Enclave sono eseguite dall'interno delle istanze EC2 e non è possibile vedere dalla console web AWS se un'istanza EC2 sta eseguendo immagini in Nitro Enclave o meno.

Installazione del CLI Nitro Enclave

Segui tutte le istruzioni dalla documentazione. Tuttavia, queste sono le più importanti:

# 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

Nitro Enclave Images

Le immagini che puoi eseguire in Nitro Enclave sono basate su immagini docker, quindi puoi creare le tue immagini Nitro Enclave da immagini docker come:

# 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

Come puoi vedere, le immagini Nitro Enclave usano l'estensione eif (Enclave Image File).

L'output sarà simile a:

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

Eseguire un'Immagine

Secondo la documentazione, per eseguire un'immagine enclave è necessario assegnarle una memoria di almeno 4 volte la dimensione del file eif. È possibile configurare le risorse predefinite da assegnarle nel file

/etc/nitro_enclaves/allocator.yaml

Ricorda sempre che devi riservare alcune risorse anche per l'istanza EC2 principale!

Dopo aver determinato le risorse da assegnare a un'immagine e aver modificato il file di configurazione, è possibile eseguire un'immagine 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

Enumerare Enclavi

Se comprometti un host EC2 è possibile ottenere un elenco delle immagini enclave in esecuzione con:

nitro-cli describe-enclaves

È impossibile ottenere una shell all'interno di un'immagine enclave in esecuzione perché questo è lo scopo principale dell'enclave, tuttavia, se hai utilizzato il parametro --debug-mode, è possibile ottenere il stdout con:

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

Terminate Enclaves

Se un attaccante compromette un'istanza EC2, di default non sarà in grado di ottenere una shell al suo interno, ma sarà in grado di terminarla con:

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

Vsocks

L'unico modo per comunicare con un'immagine in esecuzione in un enclave è utilizzare vsocks.

Virtual Socket (vsock) è una famiglia di socket in Linux specificamente progettata per facilitare la comunicazione tra macchine virtuali (VMs) e i loro hypervisors, o tra le VMs stesse. Vsock consente una comunicazione bidirezionale efficiente senza fare affidamento sullo stack di rete dell'host. Questo rende possibile la comunicazione tra VMs anche senza configurazioni di rete, utilizzando un ID di contesto (CID) a 32 bit e numeri di porta per identificare e gestire le connessioni. L'API vsock supporta sia i tipi di socket stream che datagram, simili a TCP e UDP, fornendo uno strumento versatile per le applicazioni a livello utente negli ambienti virtuali.

Pertanto, un indirizzo vsock appare così: <CID>:<Port>

Per trovare i CIDs delle immagini in esecuzione nell'enclave, è possibile eseguire il seguente comando e ottenere il EnclaveCID:

nitro-cli describe-enclaves

[
{
"EnclaveName": "secure-channel-example",
"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"
}
}
]

Nota che dall'host non c'è modo di sapere se un CID sta esponendo una porta! A meno che non si utilizzi uno scanner di porte vsock come https://github.com/carlospolop/Vsock-scanner.

Vsock Server/Listener

Trova qui un paio di esempi:

Listener Python Semplice

```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!"

Vsock Client

Esempi:

Last updated