Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

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



## KMS

For more information check:
Expand Down Expand Up @@ -178,6 +180,52 @@ aws kms derive-shared-secret \
--key-agreement-algorithm <algorithm>
```


### Nitro Enclaves–KMS integration attacks

For PCR and attestation background, check:

{{#ref}}
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/aws-nitro-enum.md
{{#endref}}

Attested Nitro requests only change **authorization** and how AWS KMS returns **plaintext** material. `Decrypt`, `DeriveSharedSecret`, `GenerateDataKey`, `GenerateDataKeyPair`, and `GenerateRandom` can receive a `Recipient` attestation document containing the enclave public key; AWS KMS validates the attestation and encrypts the sensitive response to that key. `Encrypt` does **not** get this attested-response flow, so direct CMK encryption is a common design smell when enclave identity is expected to gate the operation.<sup>[1][2][3][5]</sup>

- **Omit `Recipient` / weak PCR policy enforcement:** If the application accepts KMS requests or responses without `Recipient`, or the key policy does not require the expected PCRs, the enclave loses the binding between the measured enclave, KMS authorization, and the response-encryption key. Look for designs where the parent EC2 instance or another broker can call KMS without enclave attestation and still obtain usable output.<sup>[1][2][3][5]</sup>
- **Wrapped-key / shared-secret substitution:** A valid `CiphertextBlob`, encrypted private key, or ECDH shared-secret blob stored outside the enclave can often be swapped with another blob produced under the same CMK. Successful `Decrypt` only proves that the blob was encrypted under an allowed KMS key, not that it belongs to the expected tenant, object, or protocol step.<sup>[1]</sup>

Bind every wrapped value to trusted state with `EncryptionContext`, and explicitly send the expected `KeyId` on `Decrypt`.<sup>[1][4]</sup>

```python
context = {
"tenant": tenant_id,
"object": record_id,
"purpose": "db-field-encryption",
"version": version,
}
kms.generate_data_key(KeyId=EXPECTED_CMK_ARN,
EncryptionContext=context,
Recipient=recipient)
kms.decrypt(CiphertextBlob=wrapped_key,
KeyId=EXPECTED_CMK_ARN,
EncryptionContext=context,
Recipient=recipient)
```

- **Ciphertext + context pair swapping:** `EncryptionContext` only helps if at least one security-critical field comes from trusted enclave state or attested configuration. If the attacker controls both the wrapped blob and the entire context, they can replay a matching pair or mint new valid pairs anywhere they still have `kms:Encrypt` or `kms:GenerateDataKey*` on the same CMK.<sup>[1][4]</sup>
- **Application-ciphertext relocation:** Protecting the wrapped data key is not enough. Data encrypted locally with that key also needs AEAD-associated data bound to tenant, object, record type, location, purpose, and version; otherwise valid ciphertext can be moved between records or semantic roles.<sup>[1][4]</sup>

Bind locally encrypted data to the same trusted identifiers used in the KMS context, and prefer formats with key commitment.<sup>[1]</sup>

```python
aad = encode(tenant_id, record_id, record_type, purpose, version)
ciphertext = aead_encrypt(data_key, nonce, plaintext, aad)
plaintext = aead_decrypt(data_key, nonce, ciphertext, aad)
```

- **CMK / alias / account / Region confusion:** If an attacker can influence the `KeyId`, alias, IAM role, account, or Region used by the enclave, they may redirect the flow to an unintended but still valid key. Hardcode the full CMK ARN, avoid mutable aliases, explicitly pass `KeyId` to `Decrypt`, and verify that the returned `KeyId` matches the expected ARN.<sup>[1]</sup>
- **Replay / rollback / metadata confusion:** Old wrapped keys, ciphertexts, and responses can remain perfectly valid and still roll the enclave back to stale state. Enforce freshness with authenticated versions, counters, epochs, or nonces, and do not trust external metadata or defaults for key type, algorithm, or key usage.<sup>[1]</sup>

### Impersonation via kms:Sign
With the `kms:Sign` permission, an actor can use a KMS-stored CMK to cryptographically sign data without exposing the private key, producing valid signatures that can enable impersonation or authorize malicious actions.

Expand All @@ -204,5 +252,13 @@ aws kms update-custom-key-store --custom-key-store-id <CUSTOM_KEY_STORE_ID> --ne

<figure><img src="../../../images/image (76).png" alt=""><figcaption></figcaption></figure>

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

## References

- [1] [A few notes on AWS Nitro Enclaves: KMS integration - The Trail of Bits Blog](https://blog.trailofbits.com/2026/08/05/a-few-notes-on-aws-nitro-enclaves-kms-integration/)
- [2] [Cryptographic attestation support in AWS KMS - AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/cryptographic-attestation.html)
- [3] [RecipientInfo - AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/APIReference/API_RecipientInfo.html)
- [4] [Encryption context - AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/encrypt_context.html)
- [5] [Cryptographic attestation - AWS Nitro Enclaves](https://docs.aws.amazon.com/enclaves/latest/user/set-up-attestation.html)

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