{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
AWS Nitro is a suite of innovative technologies that form the underlying platform for AWS EC2 instances. Introduced by Amazon to enhance security, performance, and reliability, Nitro leverages custom hardware components and a lightweight hypervisor. It abstracts much of the traditional virtualization functionality to dedicated hardware and software, minimizing the attack surface and improving resource efficiency. By offloading virtualization functions, Nitro allows EC2 instances to deliver near bare-metal performance, making it particularly beneficial for resource-intensive applications. Additionally, the Nitro Security Chip specifically ensures the security of the hardware and firmware, further solidifying its robust architecture.
AWS Nitro Enclaves provides a secure, isolated compute environment within Amazon EC2 instances, specifically designed for processing highly sensitive data. Leveraging the AWS Nitro System, these enclaves ensure robust isolation and security, ideal for handling confidential information such as PII or financial records. They feature a minimalist environment, significantly reducing the risk of data exposure. Additionally, Nitro Enclaves support cryptographic attestation, allowing users to verify that only authorized code is running, crucial for maintaining strict compliance and data protection standards.
{% hint style="danger" %} Nitro Enclave images are run from inside EC2 instances and you cannot see from the AWS web console if an EC2 instances is running images in Nitro Enclave or not. {% endhint %}
Follow the all instructions from the documentation. However, these are the most important ones:
# 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
The images that you can run in Nitro Enclave are based on docker images, so you can create your Nitro Enclave images from docker images like:
# 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
As you can see the Nitro Enclave images use the extension eif
(Enclave Image File).
The output will look similar to:
Using the locally available Docker image...
Enclave Image successfully created.
{
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "e199261541a944a93129a52a8909d29435dd89e31299b59c371158fc9ab3017d9c450b0a580a487e330b4ac691943284",
"PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
"PCR2": "2e1fca1dbb84622ec141557dfa971b4f8ea2127031b264136a20278c43d1bba6c75fea286cd4de9f00450b6a8db0e6d3"
}
}
As per the documentation, in order to run an enclave image you need to assign it memory of at least 4 times the size of the eif
file. It's possible to configure the default resources to give to it in the file
/etc/nitro_enclaves/allocator.yaml
{% hint style="danger" %} Always remember that you need to reserve some resources for the parent EC2 instance also! {% endhint %}
After knowing the resources to give to an image and even having modified the configuration file it's possible to run an enclave image with:
{% code overflow="wrap" %}
# 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
{% endcode %}
If you compromise and EC2 host it's possible to get a list of running enclave images with:
nitro-cli describe-enclaves
It's not possible to get a shell inside a running enclave image because thats the main purpose of enclave, however, if you used the parameter --debug-mode
, it's possible to get the stdout of it with:
ENCLAVE_ID=$(nitro-cli describe-enclaves | jq -r ".[0].EnclaveID")
nitro-cli console --enclave-id ${ENCLAVE_ID}
If an attacker compromise an EC2 instance by default he won't be able to get a shell inside of them, but he will be able to terminate them with:
nitro-cli terminate-enclave --enclave-id ${ENCLAVE_ID}
The only way to communicate with an enclave running image is using vsocks.
Virtual Socket (vsock) is a socket family in Linux specifically designed to facilitate communication between virtual machines (VMs) and their hypervisors, or between VMs themselves. Vsock enables efficient, bi-directional communication without relying on the host's networking stack. This makes it possible for VMs to communicate even without network configurations, using a 32-bit Context ID (CID) and port numbers to identify and manage connections. The vsock API supports both stream and datagram socket types, similar to TCP and UDP, providing a versatile tool for user-level applications in virtual environments.
{% hint style="success" %}
Therefore, an vsock address looks like this: <CID>:<Port>
{% endhint %}
To find CIDs of the enclave running images you could just execute the following cmd and thet the 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"
}
}
]
{% hint style="warning" %} Note that from the host there isn't any way to know if a CID is exposing any port! Unless using some vsock port scanner like https://github.com/carlospolop/Vsock-scanner. {% endhint %}
Find here a couple of examples:
Simple Python Listener
#!/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}")
# Using socat
socat VSOCK-LISTEN:<port>,fork EXEC:"echo Hello from server!"
Examples:
Simple Python Client
#!/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()
# Using socat
echo "Hello, vsock!" | socat - VSOCK-CONNECT:3:5000
The tool vsock-proxy allows to proxy a vsock proxy with another address, for example:
vsock-proxy 8001 ip-ranges.amazonaws.com 443 --config your-vsock-proxy.yaml
This will forward the local port 8001 in vsock to ip-ranges.amazonaws.com:443
and the file your-vsock-proxy.yaml
might have this content allowing to access ip-ranges.amazonaws.com:443
:
allowlist:
- {address: ip-ranges.amazonaws.com, port: 443}
It's possible to see the vsock addresses (<CID>:<Port>
) used by the EC2 host with (note the 3:8001
, 3 is the CID and 8001 the port):
{% code overflow="wrap" %}
sudo ss -l -p -n | grep v_str
v_str LISTEN 0 0 3:8001 *:* users:(("vsock-proxy",pid=9458,fd=3))
{% endcode %}
The Nitro Enclaves SDK allows an enclave to request a cryptographically signed attestation document from the Nitro Hypervisor, which includes unique measurements specific to that enclave. These measurements, which include hashes and platform configuration registers (PCRs), are used during the attestation process to prove the enclave's identity and build trust with external services. The attestation document typically contains values like PCR0, PCR1, and PCR2, which you have encountered before when building and saving an enclave EIF.
From the docs, these are the PCR values:
PCR | Hash of ... | Description |
---|---|---|
PCR0 | Enclave image file | A contiguous measure of the contents of the image file, without the section data. |
PCR1 | Linux kernel and bootstrap | A contiguous measurement of the kernel and boot ramfs data. |
PCR2 | Application | A contiguous, in-order measurement of the user applications, without the boot ramfs. |
PCR3 | IAM role assigned to the parent instance | A contiguous measurement of the IAM role assigned to the parent instance. Ensures that the attestation process succeeds only when the parent instance has the correct IAM role. |
PCR4 | Instance ID of the parent instance | A contiguous measurement of the ID of the parent instance. Ensures that the attestation process succeeds only when the parent instance has a specific instance ID. |
PCR8 | Enclave image file signing certificate | A measure of the signing certificate specified for the enclave image file. Ensures that the attestation process succeeds only when the enclave was booted from an enclave image file signed by a specific certificate. |
You can integrate cryptographic attestation into your applications and leverage pre-built integrations with services like AWS KMS. AWS KMS can validate enclave attestations and offers attestation-based condition keys (kms:RecipientAttestation:ImageSha384
and kms:RecipientAttestation:PCR
) in its key policies. These policies ensure that AWS KMS permits operations using the KMS key only if the enclave's attestation document is valid and meets the specified conditions.
{% hint style="success" %}
Note that Enclaves in debug (--debug) mode generate attestation documents with PCRs that are made of zeros (000000000000000000000000000000000000000000000000
). Therefore, KMS policies checking these values will fail.
{% endhint %}
From an attackers perspective, notice that some PCRs would allow to modify some parts or all the enclave image and would still be valid (for example PCR4 just checks the ID of the parent instance so running any enclave image in that EC2 will allow to fulfil this potential PCR requirement).
Therefore, an attacker that compromise the EC2 instance might be able to run other enclave images in order to bypass these protections.
The research on how to modify/create new images to bypass each protection (spcially the not taht obvious ones) is still TODO.
- https://medium.com/@F.DL/understanding-vsock-684016cf0eb0
- All the parts of the Nitro tutorial from AWS: https://catalog.us-east-1.prod.workshops.aws/event/dashboard/en-US/workshop/1-my-first-enclave/1-1-nitro-enclaves-cli
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.