# AWS - Nitro Enum

{{#include ../../../../banners/hacktricks-training.md}}

## Informazioni di base

AWS Nitro è una suite di **tecnologie innovative** che formano 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. Offloadando 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**, progettato specificamente per elaborare dati altamente sensibili. Sfruttando il sistema AWS Nitro, questi enclavi garantiscono una robusta **isolamento e sicurezza**, 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 codice autorizzato sia in esecuzione, fondamentale per mantenere rigorosi standard di conformità e protezione dei dati.

> [!CAUTION]
> Le immagini Nitro Enclave sono **eseguite all'interno delle istanze EC2** e non puoi vedere dalla console web AWS se un'istanza EC2 sta eseguendo immagini in Nitro Enclave o meno.

## Installazione del CLI di Nitro Enclave

Segui tutte le istruzioni [**dalla documentazione**](https://catalog.us-east-1.prod.workshops.aws/event/dashboard/en-US/workshop/1-my-first-enclave/1-1-nitro-enclaves-cli#run-connect-and-terminate-the-enclave). Tuttavia, queste sono le più importanti:
```bash
# 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:
```bash
# 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 di Nitro Enclave utilizzano l'estensione **`eif`** (Enclave Image File).

L'output apparirà simile a:
```
Using the locally available Docker image...
Enclave Image successfully created.
{
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "e199261541a944a93129a52a8909d29435dd89e31299b59c371158fc9ab3017d9c450b0a580a487e330b4ac691943284",
"PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
"PCR2": "2e1fca1dbb84622ec141557dfa971b4f8ea2127031b264136a20278c43d1bba6c75fea286cd4de9f00450b6a8db0e6d3"
}
}
```
### Esegui un'immagine

Come indicato nella [**documentazione**](https://catalog.us-east-1.prod.workshops.aws/event/dashboard/en-US/workshop/1-my-first-enclave/1-1-nitro-enclaves-cli#run-connect-and-terminate-the-enclave), 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.
```shell
/etc/nitro_enclaves/allocator.yaml
```
> [!CAUTION]
> Ricorda sempre che devi **riservare alcune risorse per l'istanza EC2** genitore!

Dopo aver conosciuto le risorse da assegnare a un'immagine e aver anche modificato il file di configurazione, è possibile eseguire un'immagine enclave con:
```shell
# 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 gli Enclavi

Se comprometti un host EC2, è possibile ottenere un elenco delle immagini di enclave in esecuzione con:
```bash
nitro-cli describe-enclaves
```
Non è **possibile 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:
```shell
ENCLAVE_ID=$(nitro-cli describe-enclaves | jq -r ".[0].EnclaveID")
nitro-cli console --enclave-id ${ENCLAVE_ID}
```
### Terminare gli Enclavi

Se un attaccante compromette un'istanza EC2, per impostazione predefinita non sarà in grado di ottenere una shell all'interno di esse, ma sarà in grado di **terminarle** con:
```shell
nitro-cli terminate-enclave --enclave-id ${ENCLAVE_ID}
```
## Vsocks

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

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

> [!TIP]
> Pertanto, un indirizzo vsock appare così: `<CID>:<Port>`

Per trovare i **CID** delle immagini enclave in esecuzione, puoi semplicemente eseguire il seguente comando e ottenere il **`EnclaveCID`**:

<pre class="language-bash"><code class="lang-bash">nitro-cli describe-enclaves

[
{
"EnclaveName": "secure-channel-example",
"EnclaveID": "i-0bc274f83ade02a62-enc18ef3d09c886748",
"ProcessID": 10131,
<strong>    "EnclaveCID": 16,
</strong>    "NumberOfCPUs": 2,
"CPUIDs": [
1,
3
],
"MemoryMiB": 1024,
"State": "RUNNING",
"Flags": "DEBUG_MODE",
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "e199261541a944a93129a52a8909d29435dd89e31299b59c371158fc9ab3017d9c450b0a580a487e330b4ac691943284",
"PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
"PCR2": "2e1fca1dbb84622ec141557dfa971b4f8ea2127031b264136a20278c43d1bba6c75fea286cd4de9f00450b6a8db0e6d3"
}
}
]
</code></pre>

> [!WARNING]
> Nota che dall'host non c'è modo di sapere se un CID sta esponendo qualche porta! A meno di utilizzare qualche **scanner di porte vsock come** [**https://github.com/carlospolop/Vsock-scanner**](https://github.com/carlospolop/Vsock-scanner).

### Vsock Server/Listener

Trova qui un paio di esempi:

- [https://github.com/aws-samples/aws-nitro-enclaves-workshop/blob/main/resources/code/my-first-enclave/secure-local-channel/server.py](https://github.com/aws-samples/aws-nitro-enclaves-workshop/blob/main/resources/code/my-first-enclave/secure-local-channel/server.py)

<details>

<summary>Simple Python Listener</summary>
```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:

- [https://github.com/aws-samples/aws-nitro-enclaves-workshop/blob/main/resources/code/my-first-enclave/secure-local-channel/client.py](https://github.com/aws-samples/aws-nitro-enclaves-workshop/blob/main/resources/code/my-first-enclave/secure-local-channel/client.py)

<details>

<summary>Client Python Semplice</summary>
```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.connect((CID, PORT))
s.sendall(b"Hello, world!")
s.close()
```
</details>
```bash
# Using socat
echo "Hello, vsock!" | socat - VSOCK-CONNECT:3:5000
```
### Vsock Proxy

Lo strumento vsock-proxy consente di proxy un vsock proxy con un altro indirizzo, ad esempio:
```bash
vsock-proxy 8001 ip-ranges.amazonaws.com 443 --config your-vsock-proxy.yaml
```
Questo inoltrerà la **porta locale 8001 in vsock** a `ip-ranges.amazonaws.com:443` e il file **`your-vsock-proxy.yaml`** potrebbe avere questo contenuto che consente di accedere a `ip-ranges.amazonaws.com:443`:
```yaml
allowlist:
- { address: ip-ranges.amazonaws.com, port: 443 }
```
È possibile vedere gli indirizzi vsock (**`<CID>:<Port>`**) utilizzati dall'host EC2 con (nota il `3:8001`, 3 è il CID e 8001 è la porta):
```bash
sudo ss -l -p -n | grep v_str
v_str LISTEN 0      0                                                                              3:8001                   *:*     users:(("vsock-proxy",pid=9458,fd=3))
```
## Nitro Enclave Atestazione & KMS

Il Nitro Enclaves SDK consente a un enclave di richiedere un **documento di attestazione firmato crittograficamente** dal Nitro **Hypervisor**, che include **misurazioni uniche** specifiche per quell'enclave. Queste misurazioni, che includono **hash e registri di configurazione della piattaforma (PCR)**, vengono utilizzate durante il processo di attestazione per **provare l'identità dell'enclave** e **costruire fiducia con i servizi esterni**. Il documento di attestazione contiene tipicamente valori come PCR0, PCR1 e PCR2, che hai già incontrato quando hai costruito e salvato un EIF dell'enclave.

Dai [**docs**](https://catalog.us-east-1.prod.workshops.aws/event/dashboard/en-US/workshop/1-my-first-enclave/1-3-cryptographic-attestation#a-unique-feature-on-nitro-enclaves), questi sono i valori PCR:

<table><thead><tr><th width="97">PCR</th><th width="221">Hash di ...</th><th>Descrizione</th></tr></thead><tbody><tr><td>PCR0</td><td>File immagine dell'enclave</td><td>Una misura contigua dei contenuti del file immagine, senza i dati della sezione.</td></tr><tr><td>PCR1</td><td>Kernel Linux e bootstrap</td><td>Una misurazione contigua dei dati del kernel e del ramfs di avvio.</td></tr><tr><td>PCR2</td><td>Applicazione</td><td>Una misurazione contigua e in ordine delle applicazioni utente, senza il ramfs di avvio.</td></tr><tr><td>PCR3</td><td>Ruolo IAM assegnato all'istanza padre</td><td>Una misurazione contigua del ruolo IAM assegnato all'istanza padre. Garantisce che il processo di attestazione abbia successo solo quando l'istanza padre ha il ruolo IAM corretto.</td></tr><tr><td>PCR4</td><td>ID dell'istanza padre</td><td>Una misurazione contigua dell'ID dell'istanza padre. Garantisce che il processo di attestazione abbia successo solo quando l'istanza padre ha un ID di istanza specifico.</td></tr><tr><td>PCR8</td><td>Certificato di firma del file immagine dell'enclave</td><td>Una misura del certificato di firma specificato per il file immagine dell'enclave. Garantisce che il processo di attestazione abbia successo solo quando l'enclave è stata avviata da un file immagine dell'enclave firmato da un certificato specifico.</td></tr></tbody></table>

Puoi integrare **l'attestazione crittografica** nelle tue applicazioni e sfruttare integrazioni pre-costruite con servizi come **AWS KMS**. AWS KMS può **validare le attestazioni dell'enclave** e offre chiavi di condizione basate sull'attestazione (`kms:RecipientAttestation:ImageSha384` e `kms:RecipientAttestation:PCR`) nelle sue politiche delle chiavi. Queste politiche garantiscono che AWS KMS consenta operazioni utilizzando la chiave KMS **solo se il documento di attestazione dell'enclave è valido** e soddisfa le **condizioni specificate**.

> [!TIP]
> Nota che gli Enclaves in modalità debug (--debug) generano documenti di attestazione con PCR che sono composti da zeri (`000000000000000000000000000000000000000000000000`). Pertanto, le politiche KMS che controllano questi valori falliranno.

### Bypass PCR

Dal punto di vista di un attaccante, nota che alcuni PCR consentirebbero di modificare alcune parti o l'intera immagine dell'enclave e sarebbero comunque validi (ad esempio, PCR4 controlla solo l'ID dell'istanza padre, quindi eseguire qualsiasi immagine dell'enclave in quell'EC2 consentirà di soddisfare questo potenziale requisito PCR).

Pertanto, un attaccante che compromette l'istanza EC2 potrebbe essere in grado di eseguire altre immagini dell'enclave per eludere queste protezioni.

La ricerca su come modificare/creare nuove immagini per eludere ciascuna protezione (specialmente quelle non così ovvie) è ancora da fare.

## Riferimenti

- [https://medium.com/@F.DL/understanding-vsock-684016cf0eb0](https://medium.com/@F.DL/understanding-vsock-684016cf0eb0)
- Tutte le parti del tutorial Nitro di AWS: [https://catalog.us-east-1.prod.workshops.aws/event/dashboard/en-US/workshop/1-my-first-enclave/1-1-nitro-enclaves-cli](https://catalog.us-east-1.prod.workshops.aws/event/dashboard/en-US/workshop/1-my-first-enclave/1-1-nitro-enclaves-cli)

{{#include ../../../../banners/hacktricks-training.md}}
