AWS - Nitro Enum

Reading time: 16 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

基本情報

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のインストール

すべての指示に従ってくださいドキュメントから。ただし、最も重要なものは次のとおりです:

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"
}
}

イメージを実行する

ドキュメントによると、エンクレーブイメージを実行するには、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**を取得できます:

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"
}
}
]

warning

ホストからはCIDがポートを公開しているかどうかを知る方法はありません!一部のvsockポートスキャナーを使用しない限り、https://github.com/carlospolop/Vsock-scannerのような。

Vsock Server/Listener

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

シンプルな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}")
bash
# Using socat
socat VSOCK-LISTEN:<port>,fork EXEC:"echo Hello from server!"

Vsock クライアント

例:

シンプルな 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.connect((CID, PORT))
s.sendall(b"Hello, world!")
s.close()
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のローカルポート8001ip-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から、これらはPCR値です:

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

暗号的アテステーションをアプリケーションに統合し、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

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする