mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-05 20:40:18 -08:00
Merge pull request #231 from HackTricks-wiki/update_Vulnerabilities_in_LUKS2_disk_encryption_for_confi_20251030_130547
Vulnerabilities in LUKS2 disk encryption for confidential VM...
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
# ⛈️ Pentesting Cloud
|
||||
|
||||
- [Pentesting Cloud Methodology](pentesting-cloud/pentesting-cloud-methodology.md)
|
||||
- [Luks2 Header Malleability Null Cipher Abuse](pentesting-cloud/confidential-computing/luks2-header-malleability-null-cipher-abuse.md)
|
||||
- [Kubernetes Pentesting](pentesting-cloud/kubernetes-security/README.md)
|
||||
- [Kubernetes Basics](pentesting-cloud/kubernetes-security/kubernetes-basics.md)
|
||||
- [Pentesting Kubernetes Services](pentesting-cloud/kubernetes-security/pentesting-kubernetes-services/README.md)
|
||||
@@ -579,4 +580,3 @@
|
||||
|
||||
- [HackTricks Pentesting Network$$external:https://book.hacktricks.wiki/en/generic-methodologies-and-resources/pentesting-network/index.html$$]()
|
||||
- [HackTricks Pentesting Services$$external:https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-ssh.html$$]()
|
||||
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
# LUKS2 Header Malleability and Null-Cipher Abuse in Confidential VMs
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## TL;DR
|
||||
|
||||
- Many Linux-based Confidential VMs (CVMs) running on AMD SEV-SNP or Intel TDX use LUKS2 for persistent storage. The on-disk LUKS2 header is malleable and not integrity-protected against storage-adjacent attackers.
|
||||
- If the header’s data segment encryption is set to a null cipher (e.g., "cipher_null-ecb"), cryptsetup accepts it and the guest transparently reads/writes plaintext while believing the disk is encrypted.
|
||||
- Prior to and including cryptsetup 2.8.0, null ciphers could be used for keyslots; since 2.8.1 they are rejected for keyslots with non-empty passwords, but null ciphers remain allowed for volume segments.
|
||||
- Remote attestation usually measures VM code/config, not mutable external LUKS headers; without explicit validation/measurement, an attacker with disk write access can force plaintext I/O.
|
||||
|
||||
## Background: LUKS2 on-disk format (what matters for attackers)
|
||||
|
||||
- A LUKS2 device starts with a header followed by encrypted data.
|
||||
- The header contains two identical copies of a binary section and a JSON metadata section, plus one or more keyslots.
|
||||
- JSON metadata defines:
|
||||
- keyslots enabled and their wrapping KDF/cipher
|
||||
- segments that describe the data area (cipher/mode)
|
||||
- digests (e.g., hash of the volume key to verify passphrases)
|
||||
- Typical secure values: keyslot KDF argon2id; keyslot and data segment encryption aes-xts-plain64.
|
||||
|
||||
Quickly inspect the segment cipher directly from JSON:
|
||||
|
||||
```bash
|
||||
# Read JSON metadata and print the configured data segment cipher
|
||||
cryptsetup luksDump --type luks2 --dump-json-metadata /dev/VDISK \
|
||||
| jq -r '.segments["0"].encryption'
|
||||
```
|
||||
|
||||
## Root cause
|
||||
|
||||
- LUKS2 headers are not authenticated against storage tampering. A host/storage attacker can rewrite the JSON metadata accepted by cryptsetup.
|
||||
- As of cryptsetup 2.8.0, headers that set a segment’s encryption to cipher_null-ecb are accepted. The null cipher ignores keys and returns plaintext.
|
||||
- Up to 2.8.0, null ciphers could also be used for keyslots (keyslot opens with any passphrase). Since 2.8.1, null ciphers are rejected for keyslots with non-empty passwords, but remain allowed for segments. Switching only the segment cipher still yields plaintext I/O post-2.8.1.
|
||||
|
||||
## Threat model: why attestation didn’t save you by default
|
||||
|
||||
- CVMs aim to ensure confidentiality, integrity, and authenticity in an untrusted host.
|
||||
- Remote attestation usually measures the VM image and launch configuration, not the mutable LUKS header living on untrusted storage.
|
||||
- If your CVM trusts an on-disk header without robust validation/measurement, a storage attacker can alter it to a null cipher and your guest will mount a plaintext volume without error.
|
||||
|
||||
## Exploitation (storage write access required)
|
||||
|
||||
Preconditions:
|
||||
- Write access to the CVM’s LUKS2-encrypted block device.
|
||||
- The guest uses the on-disk LUKS2 header without robust validation/attestation.
|
||||
|
||||
Steps (high level):
|
||||
1) Read the header JSON and identify the data segment definition. Example target field: segments["0"].encryption.
|
||||
2) Set the data segment encryption to a null cipher, e.g., cipher_null-ecb. Keep keyslot parameters and digest structure intact so the guest’s usual passphrase still “works.”
|
||||
3) Update both header copies and associated header digests so the header is self-consistent.
|
||||
4) On next boot, the guest runs cryptsetup, successfully unlocks the existing keyslot with its passphrase, and mounts the volume. Because the segment cipher is a null cipher, all reads/writes are plaintext.
|
||||
|
||||
Variant (pre-2.8.1 keyslot abuse): if a keyslot’s area.encryption is a null cipher, it opens with any passphrase. Combine with a null segment cipher for seamless plaintext access without knowing the guest secret.
|
||||
|
||||
## Robust mitigations (avoid TOCTOU with detached headers)
|
||||
|
||||
Always treat on-disk LUKS headers as untrusted input. Use detached-header mode so validation and opening use the same trusted bytes from protected RAM:
|
||||
|
||||
```bash
|
||||
# Copy header into protected memory (e.g., tmpfs) and open from there
|
||||
cryptsetup luksHeaderBackup --header-backup-file /tmp/luks_header /dev/VDISK
|
||||
cryptsetup open --type luks2 --header /tmp/luks_header /dev/VDISK --key-file=key.txt
|
||||
```
|
||||
|
||||
Then enforce one (or more) of:
|
||||
|
||||
1) MAC the full header
|
||||
- Compute/verify a MAC over the entire header prior to use.
|
||||
- Only open the volume when the MAC verifies.
|
||||
- Examples in the wild: Flashbots tdx-init and Fortanix Salmiac adopted MAC-based verification.
|
||||
|
||||
2) Strict JSON validation (backward compatible)
|
||||
- Dump JSON metadata and validate a strict allowlist of parameters (KDF, ciphers, segment count/type, flags).
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
# Store header in confidential RAM fs
|
||||
cryptsetup luksHeaderBackup --header-backup-file /tmp/luks_header $BLOCK_DEVICE
|
||||
# Dump JSON metadata header to a file
|
||||
cryptsetup luksDump --type luks2 --dump-json-metadata /tmp/luks_header > header.json
|
||||
# Validate the header
|
||||
python validate.py header.json
|
||||
# Open the cryptfs using key.txt
|
||||
cryptsetup open --type luks2 --header /tmp/luks_header $BLOCK_DEVICE --key-file=key.txt
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Example validator (enforce safe fields)</summary>
|
||||
|
||||
```python
|
||||
from json import load
|
||||
import sys
|
||||
with open(sys.argv[1], "r") as f:
|
||||
header = load(f)
|
||||
if len(header["keyslots"]) != 1:
|
||||
raise ValueError("Expected 1 keyslot")
|
||||
if header["keyslots"]["0"]["type"] != "luks2":
|
||||
raise ValueError("Expected luks2 keyslot")
|
||||
if header["keyslots"]["0"]["area"]["encryption"] != "aes-xts-plain64":
|
||||
raise ValueError("Expected aes-xts-plain64 encryption")
|
||||
if header["keyslots"]["0"]["kdf"]["type"] != "argon2id":
|
||||
raise ValueError("Expected argon2id kdf")
|
||||
if len(header["tokens"]) != 0:
|
||||
raise ValueError("Expected 0 tokens")
|
||||
if len(header["segments"]) != 1:
|
||||
raise ValueError("Expected 1 segment")
|
||||
if header["segments"]["0"]["type"] != "crypt":
|
||||
raise ValueError("Expected crypt segment")
|
||||
if header["segments"]["0"]["encryption"] != "aes-xts-plain64":
|
||||
raise ValueError("Expected aes-xts-plain64 encryption")
|
||||
if "flags" in header["segments"]["0"] and header["segments"]["0"]["flags"]:
|
||||
raise ValueError("Segment contains unexpected flags")
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
3) Measure/attest the header
|
||||
- Remove random salts/digests and measure the sanitized header into TPM/TDX/SEV PCRs or KMS policy state.
|
||||
- Release decryption keys only when the measured header matches an approved, safe profile.
|
||||
|
||||
Operational guidance:
|
||||
- Enforce detached header + MAC or strict validation; never trust on-disk headers directly.
|
||||
- Consumers of attestation should deny pre-patch framework versions in allow-lists.
|
||||
|
||||
## Notes on versions and maintainer position
|
||||
|
||||
- cryptsetup maintainers clarified that LUKS2 was not designed to provide integrity against storage tampering in this setting; null ciphers are retained for backward compatibility.
|
||||
- cryptsetup 2.8.1 (Oct 19, 2025) rejects null ciphers for keyslots with non-empty passwords but still allows null ciphers for segments.
|
||||
|
||||
## Quick checks and triage
|
||||
|
||||
- Inspect whether any segment encryption is set to a null cipher:
|
||||
|
||||
```bash
|
||||
cryptsetup luksDump --type luks2 --dump-json-metadata /dev/VDISK \
|
||||
| jq -r '.segments | to_entries[] | "segment=" + .key + ", enc=" + .value.encryption'
|
||||
```
|
||||
|
||||
- Verify keyslot and segment algorithms before opening the volume. If you cannot MAC, enforce strict JSON validation and open using the detached header from protected memory.
|
||||
|
||||
## References
|
||||
|
||||
- [Vulnerabilities in LUKS2 disk encryption for confidential VMs (Trail of Bits)](https://blog.trailofbits.com/2025/10/30/vulnerabilities-in-luks2-disk-encryption-for-confidential-vms/)
|
||||
- [cryptsetup issue #954 (null cipher acceptance and integrity considerations)](https://gitlab.com/cryptsetup/cryptsetup/-/issues/954)
|
||||
- [CVE-2025-59054](https://nvd.nist.gov/vuln/detail/CVE-2025-59054)
|
||||
- [CVE-2025-58356](https://nvd.nist.gov/vuln/detail/CVE-2025-58356)
|
||||
- [Related context: CVE-2021-4122 (auto-recovery path silently decrypting disks)](https://www.cve.org/CVERecord?id=CVE-2021-4122)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
@@ -446,14 +446,13 @@ aws-security/
|
||||
azure-security/
|
||||
{{#endref}}
|
||||
|
||||
### Attack Graph
|
||||
## Common Cloud Security Features
|
||||
|
||||
[**Stormspotter** ](https://github.com/Azure/Stormspotter)creates an “attack graph” of the resources in an Azure subscription. It enables red teams and pentesters to visualize the attack surface and pivot opportunities within a tenant, and supercharges your defenders to quickly orient and prioritize incident response work.
|
||||
|
||||
### Office365
|
||||
|
||||
You need **Global Admin** or at least **Global Admin Reader** (but note that Global Admin Reader is a little bit limited). However, those limitations appear in some PS modules and can be bypassed accessing the features **via the web application**.
|
||||
### Confidential Computing
|
||||
|
||||
{{#ref}}
|
||||
confidential-computing/luks2-header-malleability-null-cipher-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user