LUKS2 Header Malleability and Null-Cipher Abuse in Confidential VMs
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
TL;DR
- Багато Linux-based Confidential VMs (CVMs) на AMD SEV-SNP або Intel TDX використовують LUKS2 для постійного зберігання. LUKS2 header на диску є змінним і не має захисту цілісності проти атакуючих з доступом до сусіднього сховища.
- Якщо шифрування сегмента даних у header встановлене як null cipher (наприклад, “cipher_null-ecb”), cryptsetup приймає його і гість прозоро читає/записує plaintext, вважаючи диск зашифрованим.
- До та включно з cryptsetup 2.8.0 null ciphers могли використовуватися для keyslots; починаючи з 2.8.1 вони відхиляються для keyslots з непорожніми паролями, але null ciphers залишаються дозволеними для volume segments.
- Remote attestation зазвичай вимірює код/конфігурацію VM, а не змінні зовнішні LUKS headers; без явної валідації/вимірювання атакуючий з правом запису на диск може примусити plaintext I/O.
Background: LUKS2 on-disk format (what matters for attackers)
- Пристрій LUKS2 починається з header, за яким ідуть зашифровані дані.
- Header містить дві ідентичні копії бінарної секції і секцію JSON metadata, плюс один або декілька keyslots.
- JSON metadata визначає:
- які keyslots увімкнені та їх wrapping KDF/cipher
- segments, які описують область даних (cipher/mode)
- digests (наприклад, хеш volume key для перевірки passphrases)
- Типові безпечні значення: keyslot KDF argon2id; шифрування keyslot і data segment — 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 are not authenticated against storage tampering. Атакуючий на рівні хоста/сховища може переписати JSON-метадані, які приймає cryptsetup.
- Починаючи з cryptsetup 2.8.0, заголовки, що встановлюють шифрування сегмента як cipher_null-ecb, приймаються. null cipher ігнорує ключі і повертає plaintext.
- До 2.8.0 null ciphers також могли використовуватися для keyslots (keyslot відкривається з будь-якою passphrase). Починаючи з 2.8.1, null ciphers відхиляються для keyslots з непорожніми паролями, але залишаються дозволеними для сегментів. Заміна лише segment cipher все ще дає plaintext I/O після 2.8.1.
Модель загрози: чому атестація не врятувала вас за замовчуванням
- CVMs прагнуть забезпечити конфіденційність, цілісність і автентичність на ненадійному хості.
- Віддалена атестація зазвичай вимірює образ VM і конфігурацію запуску, а не змінний LUKS header, що знаходиться на ненадійному сховищі.
- Якщо ваш CVM довіряє on-disk header без надійної валідації/вимірювання, атакуючий на сховище може змінити його на null cipher, і ваша гостьова система змонтує plaintext том без помилок.
Експлуатація (потрібен доступ на запис до сховища)
Передумови:
- Доступ на запис до LUKS2-зашифрованого блочного пристрою CVM.
- Гість використовує on-disk LUKS2 header без надійної валідації/атестації.
Кроки (на високому рівні):
- Зчитайте header JSON і визначте визначення data segment. Приклад цільового поля: segments[“0”].encryption.
- Встановіть шифрування data segment на null cipher, наприклад cipher_null-ecb. Залиште параметри keyslot і структуру digest незмінними, щоб звичайна passphrase гостя все ще “працювала.”
- Оновіть обидві копії header та пов’язані header digests так, щоб заголовок був узгодженим.
- При наступному завантаженні гість запускає cryptsetup, успішно розблоковує існуючий keyslot своєю passphrase і монтує том. Оскільки segment cipher — null cipher, усі операції читання/запису будуть plaintext.
Варіант (pre-2.8.1 keyslot abuse): якщо area.encryption keyslot встановлено як null cipher, він відкривається з будь-якою passphrase. Поєднайте це з null segment cipher для безперервного доступу до plaintext без знання секрету гостя.
Надійні пом’якшення (уникайте TOCTOU за допомогою detached headers)
Завжди розглядайте on-disk LUKS headers як недовірений вхід. Використовуйте detached-header mode, щоб валідація та відкриття використовували ті самі довірені байти з protected 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.
- Строга валідація JSON (зворотно сумісна)
- Зробити дамп JSON-метаданих і перевірити сувору allowlist параметрів (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 і виміряйте очищений заголовок у PCRs TPM/TDX/SEV або у стан політики KMS.
- Видавайте ключі розшифрування лише коли виміряний заголовок відповідає затвердженому, безпечному профілю.
Оперативні рекомендації:
- Примусово використовуйте detached header + MAC або сувору валідацію; ніколи не довіряйте заголовкам на диску безпосередньо.
- Споживачі атестації повинні відхиляти версії фреймворку до застосування патчів у allow-list’ах.
Примітки щодо версій та позиції мейнтейнера
- Розробники cryptsetup уточнили, що LUKS2 не призначався для забезпечення цілісності проти підміни даних на носії в цьому сценарії; null ciphers збережено для зворотної сумісності.
- cryptsetup 2.8.1 (Oct 19, 2025) відкидає null ciphers для keyslots з непустими паролями, але все ще дозволяє null ciphers для сегментів.
Швидкі перевірки та тріаж
- Перевірте, чи для шифрування будь-якого сегмента встановлено null cipher:
cryptsetup luksDump --type luks2 --dump-json-metadata /dev/VDISK \
| jq -r '.segments | to_entries[] | "segment=" + .key + ", enc=" + .value.encryption'
- Перевірте keyslot та segment algorithms перед відкриттям volume. Якщо ви не можете виконати MAC, застосуйте сувору валідацію JSON і відкривайте, використовуючи detached header із protected memory.
Посилання
- 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)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
HackTricks Cloud

