LUKS2 Header Ευπλαστότητα και Κατάχρηση Null-Cipher σε Confidential VMs
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
TL;DR
- Πολλές Linux-based Confidential VMs (CVMs) που τρέχουν σε AMD SEV-SNP ή Intel TDX χρησιμοποιούν LUKS2 για persistent storage. Το on-disk LUKS2 header είναι ευπλαστό και δεν προστατεύεται ως προς την ακεραιότητα απέναντι σε storage-adjacent attackers.
- Εάν η data segment encryption του header οριστεί σε null cipher (π.χ. “cipher_null-ecb”), το cryptsetup το αποδέχεται και το guest διαβάζει/γράφει διαφανώς plaintext ενώ πιστεύει ότι ο δίσκος είναι κρυπτογραφημένος.
- Πριν και μέχρι και το cryptsetup 2.8.0, null ciphers μπορούσαν να χρησιμοποιηθούν για keyslots· από το 2.8.1 απορρίπτονται για keyslots με μη-κενά passwords, αλλά οι null ciphers παραμένουν επιτρεπτοί για volume segments.
- Το remote attestation συνήθως μετράει VM code/config, όχι mutable external LUKS headers· χωρίς ρητή validation/measurement, ένας attacker με write access στο disk μπορεί να αναγκάσει plaintext I/O.
Background: LUKS2 on-disk format (τι έχει σημασία για attackers)
- Μια συσκευή LUKS2 ξεκινά με ένα header ακολουθούμενο από encrypted data.
- Το header περιέχει δύο ταυτόσημα αντίγραφα μιας binary section και μιας JSON metadata section, συν ένα ή περισσότερα keyslots.
- Το JSON metadata ορίζει:
- τα keyslots που είναι enabled και το wrapping KDF/cipher τους
- τα segments που περιγράφουν την data area (cipher/mode)
- digests (π.χ., hash του volume key για verification των passphrases)
- Τυπικές ασφαλείς τιμές: keyslot KDF argon2id; keyslot και data segment encryption aes-xts-plain64.
Quickly inspect the segment cipher directly from JSON:
# Read JSON metadata and print the configured data segment cipher
cryptsetup luksDump --type luks2 --dump-json-metadata /dev/VDISK \
| jq -r '.segments["0"].encryption'
Βασική αιτία
- Οι LUKS2 headers δεν είναι authenticated απέναντι σε tampering του storage. Ένας host/storage attacker μπορεί να ξαναγράψει τα JSON metadata που αποδέχεται το cryptsetup.
- Από το cryptsetup 2.8.0, headers που ορίζουν την κρυπτογράφηση ενός segment σε cipher_null-ecb γίνονται αποδεκτά. Ο null cipher αγνοεί τα κλειδιά και επιστρέφει plaintext.
- Μέχρι την 2.8.0, null ciphers μπορούσαν επίσης να χρησιμοποιηθούν για keyslots (το keyslot ανοίγει με οποιαδήποτε passphrase). Από την 2.8.1, οι null ciphers απορρίπτονται για keyslots με μη-κενους κωδικούς, αλλά παραμένουν επιτρεπτοί για segments. Η αλλαγή μόνο του segment cipher εξακολουθεί να δίνει plaintext I/O μετά την 2.8.1.
Μοντέλο απειλής: γιατί η attestation δεν σας έσωσε από προεπιλογή
- CVMs στοχεύουν στην εξασφάλιση εμπιστευτικότητας, ακεραιότητας και αυθεντικότητας σε έναν μη αξιόπιστο host.
- Η remote attestation συνήθως μετράει το VM image και τη διαμόρφωση εκκίνησης, όχι το mutable LUKS header που ζει σε μη αξιόπιστο storage.
- Αν το CVM σας εμπιστεύεται ένα on-disk header χωρίς ισχυρό validation/measurement, ένας storage attacker μπορεί να το αλλάξει σε null cipher και το guest σας θα κάνει mount έναν plaintext τόμο χωρίς σφάλμα.
Εκμετάλλευση (απαιτείται write access στο storage)
Προϋποθέσεις:
- Write access στο LUKS2-encrypted block device του CVM.
- Το guest χρησιμοποιεί το on-disk LUKS2 header χωρίς ισχυρή validation/attestation.
Βήματα (σε υψηλό επίπεδο):
- Διαβάστε το header JSON και εντοπίστε τον ορισμό του data segment. Παράδειγμα πεδίου-στόχου: segments[“0”].encryption.
- Ορίστε την κρυπτογράφηση του data segment σε null cipher, π.χ. cipher_null-ecb. Διατηρήστε τις παραμέτρους keyslot και τη δομή του digest ανέπαφες ώστε η συνηθισμένη passphrase του guest να εξακολουθεί να “works.”
- Ενημερώστε και τα δύο αντίγραφα header και τα συνδεδεμένα header digests ώστε το header να είναι αυτοσυνεπές.
- Στο επόμενο boot, το guest τρέχει cryptsetup, ξεκλειδώνει επιτυχώς το υπάρχον keyslot με την passphrase του και κάνει mount τον τόμο. Επειδή ο segment cipher είναι null cipher, όλες οι αναγνώσεις/εγγραφές είναι plaintext.
Παραλλαγή (pre-2.8.1 keyslot abuse): αν το area.encryption ενός keyslot είναι null cipher, ανοίγει με οποιαδήποτε passphrase. Συνδυάστε με null segment cipher για αδιάλειπτη πρόσβαση σε plaintext χωρίς να γνωρίζετε το guest secret.
Ισχυρές μετριαστικές ενέργειες (αποφύγετε TOCTOU με detached headers)
Πάντοτε αντιμετωπίζετε τα on-disk LUKS headers ως μη αξιόπιστη είσοδο. Χρησιμοποιήστε detached-header mode ώστε η validation και το opening να χρησιμοποιούν τα ίδια trusted bytes από προστατευμένη RAM:
# 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
Στη συνέχεια, επιβάλετε ένα (ή περισσότερα) από τα εξής:
- MAC ολόκληρης της κεφαλίδας
- Υπολογίστε/επικυρώστε ένα MAC για ολόκληρη την κεφαλίδα πριν τη χρήση.
- Ανοίξτε τον τόμο μόνο όταν το MAC επαληθεύεται.
- Παραδείγματα στην πράξη: Flashbots tdx-init και Fortanix Salmiac υιοθέτησαν MAC-based verification.
- Αυστηρή επικύρωση JSON (συμβατό προς τα πίσω)
- Εξάγετε (dump) τα JSON metadata και επικυρώστε μια αυστηρή λίστα επιτρεπόμενων παραμέτρων (KDF, ciphers, segment count/type, flags).
#!/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
Παράδειγμα επικυρωτή (επιβολή ασφαλών πεδίων)
```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") ```- Μετρήστε/πιστοποιήστε την κεφαλίδα
- Αφαιρέστε τυχόν τυχαία salts/digests και μετρήστε την καθαρισμένη κεφαλίδα στους TPM/TDX/SEV PCRs ή στην κατάσταση πολιτικής του KMS.
- Απελευθερώστε τα κλειδιά αποκρυπτογράφησης μόνο όταν η μετρημένη κεφαλίδα ταιριάζει με ένα εγκεκριμένο, ασφαλές προφίλ.
Operational guidance:
- Επιβάλετε detached header + MAC ή αυστηρή επικύρωση· μην εμπιστεύεστε ποτέ απευθείας τις κεφαλίδες που βρίσκονται στο δίσκο.
- Οι καταναλωτές της attestation πρέπει να απορρίπτουν προ-patch εκδόσεις framework από τις allow-lists.
Σημειώσεις για τις εκδόσεις και τη θέση των συντηρητών
- Οι συντηρητές του cryptsetup διευκρίνισαν ότι το LUKS2 δεν σχεδιάστηκε για να παρέχει ακεραιότητα έναντι παραποίησης αποθηκευτικού χώρου σε αυτό το περιβάλλον· τα null ciphers διατηρούνται για συμβατότητα προς τα πίσω.
- Το cryptsetup 2.8.1 (19 Οκτ 2025) απορρίπτει τα null ciphers για keyslots με μη-κενά passwords, αλλά εξακολουθεί να επιτρέπει null ciphers για segments.
Γρήγοροι έλεγχοι και διαλογή
- Ελέγξτε εάν η κρυπτογράφηση οποιουδήποτε segment είναι ρυθμισμένη σε null cipher:
cryptsetup luksDump --type luks2 --dump-json-metadata /dev/VDISK \
| jq -r '.segments | to_entries[] | "segment=" + .key + ", enc=" + .value.encryption'
- Επαληθεύστε τους keyslot και segment αλγόριθμους πριν ανοίξετε τον όγκο. Εάν δεν μπορείτε να MAC, επιβάλλετε αυστηρή επικύρωση JSON και ανοίξτε χρησιμοποιώντας το detached header από προστατευμένη μνήμη.
Αναφορές
- Vulnerabilities in LUKS2 disk encryption for confidential VMs (Trail of Bits)
- cryptsetup issue #954 (null cipher acceptance and integrity considerations)
- CVE-2025-59054
- CVE-2025-58356
- Related context: CVE-2021-4122 (auto-recovery path silently decrypting disks)
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Δείτε τα subscription plans!
- Εγγραφείτε στο 💬 Discord group ή την telegram group ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε τα hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
HackTricks Cloud

