# AWS - Nitro Enum

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

## Informations de base

AWS Nitro est une suite de **technologies innovantes** qui forme la plateforme sous-jacente pour les instances AWS EC2. Introduit par Amazon pour **améliorer la sécurité, la performance et la fiabilité**, Nitro s'appuie sur des **composants matériels personnalisés et un hyperviseur léger**. Il abstrait une grande partie des fonctionnalités de virtualisation traditionnelles vers du matériel et des logiciels dédiés, **minimisant la surface d'attaque** et améliorant l'efficacité des ressources. En déchargeant les fonctions de virtualisation, Nitro permet aux instances EC2 de fournir des **performances proches du bare-metal**, ce qui est particulièrement bénéfique pour les applications gourmandes en ressources. De plus, la puce de sécurité Nitro garantit spécifiquement la **sécurité du matériel et du firmware**, renforçant ainsi son architecture robuste.

### Nitro Enclaves

**AWS Nitro Enclaves** fournit un environnement de calcul sécurisé et **isolé au sein des instances Amazon EC2**, spécifiquement conçu pour le traitement de données hautement sensibles. S'appuyant sur le système AWS Nitro, ces enclaves garantissent une **isolation et une sécurité robustes**, idéales pour **traiter des informations confidentielles** telles que des données personnelles identifiables (PII) ou des dossiers financiers. Elles disposent d'un environnement minimaliste, réduisant considérablement le risque d'exposition des données. De plus, les Nitro Enclaves prennent en charge l'attestation cryptographique, permettant aux utilisateurs de vérifier que seul un code autorisé est en cours d'exécution, ce qui est crucial pour maintenir des normes strictes de conformité et de protection des données.

> [!CAUTION]
> Les images Nitro Enclave sont **exécutées depuis l'intérieur des instances EC2** et vous ne pouvez pas voir depuis la console web AWS si une instance EC2 exécute des images dans Nitro Enclave ou non.

## Installation du CLI Nitro Enclave

Suivez toutes les instructions [**de la documentation**](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). Cependant, voici les plus importantes :
```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
```
## Images Nitro Enclave

Les images que vous pouvez exécuter dans Nitro Enclave sont basées sur des images docker, vous pouvez donc créer vos images Nitro Enclave à partir d'images docker comme :
```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
```
Comme vous pouvez le voir, les images Nitro Enclave utilisent l'extension **`eif`** (Fichier d'Image d'Enclave).

La sortie ressemblera à :
```
Using the locally available Docker image...
Enclave Image successfully created.
{
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "e199261541a944a93129a52a8909d29435dd89e31299b59c371158fc9ab3017d9c450b0a580a487e330b4ac691943284",
"PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
"PCR2": "2e1fca1dbb84622ec141557dfa971b4f8ea2127031b264136a20278c43d1bba6c75fea286cd4de9f00450b6a8db0e6d3"
}
}
```
### Exécuter une image

Selon [**la documentation**](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), pour exécuter une image d'enclave, vous devez lui attribuer une mémoire de **au moins 4 fois la taille du fichier `eif`**. Il est possible de configurer les ressources par défaut à lui attribuer dans le fichier.
```shell
/etc/nitro_enclaves/allocator.yaml
```
> [!CAUTION]
> N'oubliez jamais que vous devez **réserver des ressources pour l'instance EC2 parente** également !

Après avoir connu les ressources à attribuer à une image et même après avoir modifié le fichier de configuration, il est possible d'exécuter une image d'enclave avec :
```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
```
### Énumérer les enclaves

Si vous compromettez un hôte EC2, il est possible d'obtenir une liste des images d'enclave en cours d'exécution avec :
```bash
nitro-cli describe-enclaves
```
Il n'est **pas possible d'obtenir un shell** à l'intérieur d'une image d'enclave en cours d'exécution car c'est le principal objectif de l'enclave, cependant, si vous utilisez le paramètre **`--debug-mode`**, il est possible d'obtenir le **stdout** avec :
```shell
ENCLAVE_ID=$(nitro-cli describe-enclaves | jq -r ".[0].EnclaveID")
nitro-cli console --enclave-id ${ENCLAVE_ID}
```
### Terminer les enclaves

Si un attaquant compromet une instance EC2, par défaut, il ne pourra pas obtenir un shell à l'intérieur, mais il pourra **les terminer** avec :
```shell
nitro-cli terminate-enclave --enclave-id ${ENCLAVE_ID}
```
## Vsocks

Le seul moyen de communiquer avec une **enclave** exécutant une image est d'utiliser **vsocks**.

**Virtual Socket (vsock)** est une famille de sockets dans Linux spécifiquement conçue pour faciliter la **communication** entre les machines virtuelles (**VMs**) et leurs **hyperviseurs**, ou entre les VMs **elles-mêmes**. Vsock permet une **communication** efficace et **bidirectionnelle** sans dépendre de la pile réseau de l'hôte. Cela permet aux VMs de communiquer même sans configurations réseau, **en utilisant un ID de contexte de 32 bits (CID) et des numéros de port** pour identifier et gérer les connexions. L'API vsock prend en charge à la fois les types de sockets de flux et de datagrammes, similaires à TCP et UDP, fournissant un outil polyvalent pour les applications de niveau utilisateur dans des environnements virtuels.

> [!TIP]
> Par conséquent, une adresse vsock ressemble à ceci : `<CID>:<Port>`

Pour trouver les **CIDs** des images d'enclave en cours d'exécution, vous pouvez simplement exécuter la commande suivante et obtenir le **`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]
> Notez qu'à partir de l'hôte, il n'y a aucun moyen de savoir si un CID expose un port ! À moins d'utiliser un **scanneur de port vsock comme** [**https://github.com/carlospolop/Vsock-scanner**](https://github.com/carlospolop/Vsock-scanner).

### Vsock Server/Listener

Trouvez ici quelques exemples :

- [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!"
```
### Client Vsock

Exemples :

- [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 Simple</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

L'outil vsock-proxy permet de proxy un vsock proxy avec une autre adresse, par exemple :
```bash
vsock-proxy 8001 ip-ranges.amazonaws.com 443 --config your-vsock-proxy.yaml
```
Cela redirigera le **port local 8001 dans vsock** vers `ip-ranges.amazonaws.com:443` et le fichier **`your-vsock-proxy.yaml`** pourrait avoir ce contenu permettant d'accéder à `ip-ranges.amazonaws.com:443` :
```yaml
allowlist:
- { address: ip-ranges.amazonaws.com, port: 443 }
```
Il est possible de voir les adresses vsock (**`<CID>:<Port>`**) utilisées par l'hôte EC2 avec (notez le `3:8001`, 3 est le CID et 8001 le port) :
```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 Atestation & KMS

Le SDK Nitro Enclaves permet à une enclave de demander un **document d'attestation signé cryptographiquement** au **Hyperviseur** Nitro, qui inclut des **mesures uniques** spécifiques à cette enclave. Ces mesures, qui incluent des **hashes et des registres de configuration de plateforme (PCRs)**, sont utilisées lors du processus d'attestation pour **prouver l'identité de l'enclave** et **établir la confiance avec des services externes**. Le document d'attestation contient généralement des valeurs comme PCR0, PCR1 et PCR2, que vous avez rencontrées auparavant lors de la création et de l'enregistrement d'un EIF d'enclave.

D'après les [**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), voici les valeurs PCR :

<table><thead><tr><th width="97">PCR</th><th width="221">Hash de ...</th><th>Description</th></tr></thead><tbody><tr><td>PCR0</td><td>Fichier image de l'enclave</td><td>Une mesure contiguë du contenu du fichier image, sans les données de section.</td></tr><tr><td>PCR1</td><td>Noyau Linux et bootstrap</td><td>Une mesure contiguë des données du noyau et du ramfs de démarrage.</td></tr><tr><td>PCR2</td><td>Application</td><td>Une mesure contiguë et ordonnée des applications utilisateur, sans le ramfs de démarrage.</td></tr><tr><td>PCR3</td><td>Rôle IAM attribué à l'instance parente</td><td>Une mesure contiguë du rôle IAM attribué à l'instance parente. Assure que le processus d'attestation réussit uniquement lorsque l'instance parente a le rôle IAM correct.</td></tr><tr><td>PCR4</td><td>ID de l'instance parente</td><td>Une mesure contiguë de l'ID de l'instance parente. Assure que le processus d'attestation réussit uniquement lorsque l'instance parente a un ID d'instance spécifique.</td></tr><tr><td>PCR8</td><td>Certificat de signature du fichier image de l'enclave</td><td>Une mesure du certificat de signature spécifié pour le fichier image de l'enclave. Assure que le processus d'attestation réussit uniquement lorsque l'enclave a été démarrée à partir d'un fichier image d'enclave signé par un certificat spécifique.</td></tr></tbody></table>

Vous pouvez intégrer l'**attestation cryptographique** dans vos applications et tirer parti des intégrations préconstruites avec des services comme **AWS KMS**. AWS KMS peut **valider les attestations d'enclave** et offre des clés de condition basées sur l'attestation (`kms:RecipientAttestation:ImageSha384` et `kms:RecipientAttestation:PCR`) dans ses politiques de clés. Ces politiques garantissent qu'AWS KMS permet des opérations utilisant la clé KMS **uniquement si le document d'attestation de l'enclave est valide** et répond aux **conditions spécifiées**.

> [!TIP]
> Notez que les Enclaves en mode debug (--debug) génèrent des documents d'attestation avec des PCR composés de zéros (`000000000000000000000000000000000000000000000000`). Par conséquent, les politiques KMS vérifiant ces valeurs échoueront.

### PCR Bypass

Du point de vue d'un attaquant, notez que certains PCR permettraient de modifier certaines parties ou l'ensemble de l'image de l'enclave et seraient toujours valides (par exemple, PCR4 vérifie uniquement l'ID de l'instance parente, donc exécuter n'importe quelle image d'enclave dans cette EC2 permettra de satisfaire cette exigence potentielle de PCR).

Par conséquent, un attaquant qui compromet l'instance EC2 pourrait être en mesure d'exécuter d'autres images d'enclave afin de contourner ces protections.

La recherche sur la façon de modifier/créer de nouvelles images pour contourner chaque protection (en particulier celles qui ne sont pas si évidentes) est encore à faire.

## References

- [https://medium.com/@F.DL/understanding-vsock-684016cf0eb0](https://medium.com/@F.DL/understanding-vsock-684016cf0eb0)
- Toutes les parties du tutoriel Nitro d'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}}
