AWS - Nitro Enum

Wspieraj HackTricks

Podstawowe informacje

AWS Nitro to zestaw innowacyjnych technologii, które stanowią podstawową platformę dla instancji AWS EC2. Wprowadzony przez Amazon w celu zwiększenia bezpieczeństwa, wydajności i niezawodności, Nitro wykorzystuje niestandardowe komponenty sprzętowe i lekki hipernadzorcę. Abstrahuje wiele tradycyjnych funkcji wirtualizacji do dedykowanego sprzętu i oprogramowania, minimalizując powierzchnię ataku i poprawiając efektywność zasobów. Dzięki przeniesieniu funkcji wirtualizacji, Nitro pozwala instancjom EC2 na dostarczanie wydajności zbliżonej do wydajności sprzętu fizycznego, co jest szczególnie korzystne dla aplikacji wymagających dużych zasobów. Dodatkowo, Nitro Security Chip zapewnia bezpieczeństwo sprzętu i oprogramowania układowego, co dodatkowo wzmacnia jego solidną architekturę.

Nitro Enclaves

AWS Nitro Enclaves zapewnia bezpieczne, izolowane środowisko obliczeniowe w ramach instancji Amazon EC2, specjalnie zaprojektowane do przetwarzania wysoce wrażliwych danych. Wykorzystując system AWS Nitro, te enklawy zapewniają solidną izolację i bezpieczeństwo, idealne do obsługi poufnych informacji takich jak PII czy dane finansowe. Charakteryzują się minimalistycznym środowiskiem, co znacznie zmniejsza ryzyko wycieku danych. Dodatkowo, Nitro Enclaves wspiera kryptograficzne poświadczenia, pozwalając użytkownikom na weryfikację, że uruchamiany jest tylko autoryzowany kod, co jest kluczowe dla utrzymania ścisłych standardów zgodności i ochrony danych.

Obrazy Nitro Enclave są uruchamiane wewnątrz instancji EC2 i nie można zobaczyć z konsoli webowej AWS, czy instancja EC2 uruchamia obrazy w Nitro Enclave, czy nie.

Instalacja Nitro Enclave CLI

Postępuj zgodnie ze wszystkimi instrukcjami z dokumentacji. Jednakże, te są najważniejsze:

# 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

Obrazy, które można uruchomić w Nitro Enclave, są oparte na obrazach docker, więc można tworzyć obrazy Nitro Enclave z obrazów docker, takich jak:

# 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

Jak widać, obrazy Nitro Enclave używają rozszerzenia eif (Enclave Image File).

Wynik będzie wyglądał podobnie do:

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

Uruchom obraz

Zgodnie z dokumentacją, aby uruchomić obraz enclave, musisz przypisać mu pamięć co najmniej 4 razy większą niż rozmiar pliku eif. Możliwe jest skonfigurowanie domyślnych zasobów do przydzielenia w pliku

/etc/nitro_enclaves/allocator.yaml

Zawsze pamiętaj, że musisz zarezerwować trochę zasobów dla nadrzędnej instancji EC2!

Po poznaniu zasobów do przydzielenia obrazowi i nawet po modyfikacji pliku konfiguracyjnego możliwe jest uruchomienie obrazu enclave za pomocą:

# 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

Enumerate Enclaves

Jeśli przejmiesz hosta EC2, możliwe jest uzyskanie listy uruchomionych obrazów enclave za pomocą:

nitro-cli describe-enclaves

Nie jest możliwe uzyskanie powłoki wewnątrz działającego obrazu enclave, ponieważ to jest główny cel enclave, jednakże, jeśli użyjesz parametru --debug-mode, możliwe jest uzyskanie stdout za pomocą:

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

Terminate Enclaves

Jeśli atakujący skompromituje instancję EC2, domyślnie nie będzie w stanie uzyskać powłoki wewnątrz nich, ale będzie mógł je zakończyć za pomocą:

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

Vsocks

Jedynym sposobem komunikacji z obrazem uruchomionym w enklawie jest użycie vsocks.

Virtual Socket (vsock) to rodzina gniazd w systemie Linux, zaprojektowana specjalnie do ułatwienia komunikacji między maszynami wirtualnymi (VMs) a ich hipernadzorcami lub między samymi VMs. Vsock umożliwia efektywną, dwukierunkową komunikację bez polegania na stosie sieciowym hosta. Dzięki temu VMs mogą się komunikować nawet bez konfiguracji sieci, używając 32-bitowego identyfikatora kontekstu (CID) i numerów portów do identyfikacji i zarządzania połączeniami. API vsock obsługuje zarówno strumieniowe, jak i datagramowe typy gniazd, podobnie jak TCP i UDP, co czyni go wszechstronnym narzędziem dla aplikacji użytkownika w środowiskach wirtualnych.

Dlatego adres vsock wygląda tak: <CID>:<Port>

Aby znaleźć CIDs obrazów uruchomionych w enklawie, można wykonać następujące polecenie i uzyskać 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"
}
}
]

Zauważ, że z hosta nie ma żadnego sposobu, aby dowiedzieć się, czy CID udostępnia jakikolwiek port! Chyba że użyjesz jakiegoś skanera portów vsock, takiego jak https://github.com/carlospolop/Vsock-scanner.

Vsock Server/Listener

Znajdź tutaj kilka przykładów:

Prosty Python Listener

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

```markdown
</details>
# Using socat
socat VSOCK-LISTEN:<port>,fork EXEC:"echo Hello from server!"

Vsock Client

Przykłady:

Last updated