# AWS - Nitro Enum

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

## 基本情報

AWS Nitroは、AWS EC2インスタンスの基盤となる**革新的な技術**のスイートです。Amazonによって**セキュリティ、パフォーマンス、信頼性を向上させるために**導入され、Nitroはカスタム**ハードウェアコンポーネントと軽量ハイパーバイザー**を活用しています。従来の仮想化機能の多くを専用のハードウェアとソフトウェアに抽象化し、**攻撃面を最小限に抑え**、リソース効率を改善します。仮想化機能をオフロードすることで、NitroはEC2インスタンスに**ほぼベアメタルのパフォーマンス**を提供し、リソース集約型アプリケーションに特に有益です。さらに、Nitro Security Chipは**ハードウェアとファームウェアのセキュリティ**を特に確保し、その堅牢なアーキテクチャをさらに強化します。

### Nitro Enclaves

**AWS Nitro Enclaves**は、Amazon EC2インスタンス内における安全で**隔離されたコンピューティング環境**を提供し、特に高度に機密性の高いデータの処理のために設計されています。AWS Nitro Systemを活用するこれらのエンクレーブは、堅牢な**隔離とセキュリティ**を確保し、PIIや財務記録などの**機密情報を扱う**のに理想的です。ミニマリスト環境を特徴としており、データ露出のリスクを大幅に低減します。さらに、Nitro Enclavesは暗号的証明をサポートし、ユーザーが認可されたコードのみが実行されていることを確認できるため、厳格なコンプライアンスとデータ保護基準を維持するために重要です。

> [!CAUTION]
> Nitro Enclaveイメージは**EC2インスタンス内から実行され**、AWSウェブコンソールからはEC2インスタンスがNitro Enclaveでイメージを実行しているかどうかは確認できません。

## Nitro Enclave CLIのインストール

すべての指示に従ってください[**ドキュメントから**](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)。ただし、最も重要なものは次のとおりです：
```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

Nitro Enclaveで実行できるイメージは、dockerイメージに基づいているため、次のようなdockerイメージからNitro Enclaveイメージを作成できます:
```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
```
Nitro Enclave イメージは **`eif`** (Enclave Image File) 拡張子を使用しています。

出力は次のようになります:
```
Using the locally available Docker image...
Enclave Image successfully created.
{
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "e199261541a944a93129a52a8909d29435dd89e31299b59c371158fc9ab3017d9c450b0a580a487e330b4ac691943284",
"PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
"PCR2": "2e1fca1dbb84622ec141557dfa971b4f8ea2127031b264136a20278c43d1bba6c75fea286cd4de9f00450b6a8db0e6d3"
}
}
```
### イメージを実行する

[**ドキュメント**](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)によると、エンクレーブイメージを実行するには、**`eif`ファイルのサイズの少なくとも4倍のメモリを割り当てる必要があります**。ファイル内でそれに与えるデフォルトリソースを構成することが可能です。
```shell
/etc/nitro_enclaves/allocator.yaml
```
> [!CAUTION]
> 常に**親EC2**インスタンスのためにいくつかのリソースを**予約する**必要があることを忘れないでください！

イメージに与えるリソースを知り、設定ファイルを変更した後でも、次のコマンドでエンクレーブイメージを実行することが可能です：
```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
```
### Enclavesの列挙

EC2ホストを侵害した場合、次のコマンドで実行中のエンクレーブイメージのリストを取得することができます:
```bash
nitro-cli describe-enclaves
```
実行中のエンクレーブイメージ内でシェルを取得することは**不可能**です。なぜなら、それがエンクレーブの主な目的だからです。しかし、**`--debug-mode`**パラメータを使用した場合、次のコマンドでその**stdout**を取得することが可能です：
```shell
ENCLAVE_ID=$(nitro-cli describe-enclaves | jq -r ".[0].EnclaveID")
nitro-cli console --enclave-id ${ENCLAVE_ID}
```
### Enclavesの終了

攻撃者がEC2インスタンスを侵害した場合、デフォルトではシェルにアクセスすることはできませんが、次のコマンドで**終了する**ことができます:
```shell
nitro-cli terminate-enclave --enclave-id ${ENCLAVE_ID}
```
## Vsocks

**エンクレーブ**で実行されているイメージと通信する唯一の方法は、**vsocks**を使用することです。

**Virtual Socket (vsock)**は、Linuxで特に設計されたソケットファミリーで、仮想マシン（**VMs**）とその**ハイパーバイザー**、またはVM同士の**通信**を促進します。Vsockは、ホストのネットワーキングスタックに依存せずに効率的な**双方向通信**を可能にします。これにより、ネットワーク構成がなくてもVM同士が通信できるようになり、**32ビットのコンテキストID（CID）とポート番号**を使用して接続を識別および管理します。vsock APIは、TCPやUDPに似たストリームおよびデータグラムソケットタイプの両方をサポートし、仮想環境におけるユーザーレベルのアプリケーションにとって多用途なツールを提供します。

> [!TIP]
> したがって、vsockアドレスは次のようになります：`<CID>:<Port>`

エンクレーブで実行されているイメージの**CIDs**を見つけるには、次のコマンドを実行して**`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]
> ホストからはCIDがポートを公開しているかどうかを知る方法はありません！一部の**vsockポートスキャナー**を使用しない限り、[**https://github.com/carlospolop/Vsock-scanner**](https://github.com/carlospolop/Vsock-scanner)のような。

### Vsock Server/Listener

ここにいくつかの例があります：

- [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>シンプルなPythonリスナー</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 クライアント

例:

- [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>シンプルな Python クライアント</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

ツール vsock-proxy は、別のアドレスで vsock プロキシをプロキシすることを可能にします。例えば：
```bash
vsock-proxy 8001 ip-ranges.amazonaws.com 443 --config your-vsock-proxy.yaml
```
これは**vsockのローカルポート8001**を`ip-ranges.amazonaws.com:443`に転送し、ファイル**`your-vsock-proxy.yaml`**には`ip-ranges.amazonaws.com:443`にアクセスするための次の内容が含まれている可能性があります：
```yaml
allowlist:
- { address: ip-ranges.amazonaws.com, port: 443 }
```
EC2ホストによって使用されるvsockアドレス（**`<CID>:<Port>`**）を次のように見ることができます（`3:8001`に注意してください。3はCIDで、8001はポートです）：
```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

Nitro Enclaves SDKは、エンクレーブがNitro **ハイパーバイザー**から**暗号的に署名されたアテステーション文書**を要求できるようにします。この文書には、そのエンクレーブに特有の**ユニークな測定値**が含まれています。これらの測定値は、**ハッシュとプラットフォーム構成レジスタ（PCR）**を含み、アテステーションプロセス中に**エンクレーブのアイデンティティを証明し**、**外部サービスとの信頼を構築する**ために使用されます。アテステーション文書には通常、PCR0、PCR1、PCR2のような値が含まれており、これはエンクレーブEIFを構築して保存する際に遭遇したことがあります。

[**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)から、これらはPCR値です：

<table><thead><tr><th width="97">PCR</th><th width="221">Hash of ...</th><th>Description</th></tr></thead><tbody><tr><td>PCR0</td><td>エンクレーブイメージファイル</td><td>セクションデータなしで、イメージファイルの内容の連続的な測定。</td></tr><tr><td>PCR1</td><td>Linuxカーネルとブートストラップ</td><td>カーネルとブートramfsデータの連続的な測定。</td></tr><tr><td>PCR2</td><td>アプリケーション</td><td>ブートramfsなしで、ユーザーアプリケーションの連続的かつ順序通りの測定。</td></tr><tr><td>PCR3</td><td>親インスタンスに割り当てられたIAMロール</td><td>親インスタンスに割り当てられたIAMロールの連続的な測定。親インスタンスが正しいIAMロールを持っている場合にのみ、アテステーションプロセスが成功することを保証します。</td></tr><tr><td>PCR4</td><td>親インスタンスのインスタンスID</td><td>親インスタンスのIDの連続的な測定。親インスタンスが特定のインスタンスIDを持っている場合にのみ、アテステーションプロセスが成功することを保証します。</td></tr><tr><td>PCR8</td><td>エンクレーブイメージファイル署名証明書</td><td>エンクレーブイメージファイルに指定された署名証明書の測定。特定の証明書によって署名されたエンクレーブイメージファイルからブートされた場合にのみ、アテステーションプロセスが成功することを保証します。</td></tr></tbody></table>

**暗号的アテステーション**をアプリケーションに統合し、**AWS KMS**のようなサービスとの事前構築された統合を活用できます。AWS KMSは**エンクレーブアテステーションを検証**でき、キー政策にアテステーションベースの条件キー（`kms:RecipientAttestation:ImageSha384`および`kms:RecipientAttestation:PCR`）を提供します。これらのポリシーは、エンクレーブのアテステーション文書が有効であり、**指定された条件**を満たす場合にのみ、AWS KMSがKMSキーを使用する操作を許可することを保証します。

> [!TIP]
> デバッグ（--debug）モードのエンクレーブは、ゼロ（`000000000000000000000000000000000000000000000000`）で構成されたPCRを持つアテステーション文書を生成することに注意してください。したがって、これらの値をチェックするKMSポリシーは失敗します。

### PCR Bypass

攻撃者の視点から見ると、いくつかのPCRはエンクレーブイメージの一部またはすべてを変更することを許可し、依然として有効であることに注意してください（たとえば、PCR4は親インスタンスのIDのみをチェックするため、そのEC2で任意のエンクレーブイメージを実行することでこの潜在的なPCR要件を満たすことができます）。

したがって、EC2インスタンスを侵害した攻撃者は、これらの保護を回避するために他のエンクレーブイメージを実行できる可能性があります。

各保護を回避するために新しいイメージを変更/作成する方法に関する研究（特にそれほど明白でないもの）はまだTODOです。

## References

- [https://medium.com/@F.DL/understanding-vsock-684016cf0eb0](https://medium.com/@F.DL/understanding-vsock-684016cf0eb0)
- AWSのNitroチュートリアルのすべての部分: [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}}
