LUKS2 헤더 변경 가능성 및 Null-Cipher 악용 (Confidential VMs)
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
요약
- 많은 Linux 기반 Confidential VMs (CVMs)이 AMD SEV-SNP 또는 Intel TDX에서 실행되며 영구 스토리지에 LUKS2를 사용한다. 디스크 상의 LUKS2 헤더는 변경 가능하며 스토리지 인접 공격자에 대해 무결성 보호가 되어 있지 않다.
- 헤더의 데이터 세그먼트 암호가 null cipher(e.g., “cipher_null-ecb”)로 설정되어 있으면 cryptsetup은 이를 허용하고 게스트는 디스크가 암호화되어 있다고 믿는 동안 평문을 투명하게 읽고/쓴다.
- cryptsetup 2.8.0 이전 및 해당 버전까지는 null ciphers를 keyslots에 사용할 수 있었고, 2.8.1 이후에는 비어 있지 않은 비밀번호가 있는 keyslots에 대해 거부되지만 null ciphers는 볼륨 세그먼트에는 여전히 허용된다.
- Remote attestation은 일반적으로 VM 코드/구성만 측정하며 변경 가능한 외부 LUKS 헤더를 측정하지 않는다; 명시적 검증/측정이 없으면 디스크 쓰기 권한이 있는 공격자가 평문 I/O를 강제할 수 있다.
배경: LUKS2 온디스크 포맷 (공격자에게 중요한 부분)
- LUKS2 장치는 헤더로 시작하고 그 뒤에 암호화된 데이터가 온다.
- 헤더는 바이너리 섹션의 동일한 복사본 두 개와 JSON 메타데이터 섹션, 그리고 하나 이상의 keyslots를 포함한다.
- JSON 메타데이터는 다음을 정의한다:
- 활성화된 keyslots와 그들을 감싸는 KDF/cipher
- 데이터 영역을 설명하는 segments (cipher/mode)
- digests (예: 암호문 확인을 위한 볼륨 키의 해시)
- 일반적인 안전 설정: keyslot KDF는 argon2id; keyslot 및 데이터 세그먼트 암호화는 aes-xts-plain64.
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 헤더는 스토리지 변조에 대해 인증되지 않습니다. 호스트/스토리지 공격자는 cryptsetup이 수용하는 JSON 메타데이터를 재작성할 수 있습니다.
- cryptsetup 2.8.0부터, 세그먼트의 암호화를 cipher_null-ecb로 설정한 헤더가 허용됩니다. The null cipher는 키를 무시하고 평문을 반환합니다.
- 2.8.0까지는 null ciphers를 keyslots에도 사용할 수 있었고 (keyslot은 어떤 패스프레이즈로든 열림). 2.8.1부터는 비어있지 않은 비밀번호가 있는 keyslots에 대해 null ciphers가 거부되지만, segments에 대해서는 여전히 허용됩니다. segment cipher만 변경해도 2.8.1 이후에도 평문 I/O가 발생합니다.
위협 모델: 왜 attestation이 기본적으로 보호하지 못했는가
- CVMs는 신뢰할 수 없는 호스트에서 기밀성, 무결성, 및 진위성을 보장하는 것을 목표로 합니다.
- Remote attestation은 보통 VM 이미지와 런치 구성(launch configuration)을 측정하며, 신뢰할 수 없는 스토리지에 있는 변경 가능한 LUKS 헤더는 측정하지 않습니다.
- 만약 CVM이 충분한 검증/측정 없이 온디스크 헤더를 신뢰한다면, 스토리지 공격자는 이를 null cipher로 변경할 수 있고 guest는 오류 없이 평문 볼륨을 마운트하게 됩니다.
악용 (스토리지 쓰기 접근 필요)
Preconditions:
- CVM의 LUKS2로 암호화된 블록 디바이스에 대한 쓰기 접근.
- guest가 온디스크 LUKS2 헤더를 강력한 검증/attestation 없이 사용함.
Steps (high level):
- 헤더 JSON을 읽고 data segment 정의를 식별합니다. 예시 대상 필드: segments[“0”].encryption.
- 데이터 세그먼트의 암호화를 null cipher로 설정합니다(예: cipher_null-ecb). guest의 일반적인 패스프레이즈가 여전히 “작동“하도록 keyslot 파라미터와 digest 구조는 그대로 유지합니다.
- 두 헤더 복사본과 연관된 header digests를 업데이트하여 헤더가 자체적으로 일관되게 만듭니다.
- 다음 부팅 시 guest는 cryptsetup을 실행하고 기존 keyslot을 패스프레이즈로 성공적으로 언락한 뒤 볼륨을 마운트합니다. 세그먼트 cipher가 null cipher이므로 모든 읽기/쓰기 동작은 평문입니다.
Variant (pre-2.8.1 keyslot abuse): keyslot의 area.encryption이 null cipher라면 어떤 패스프레이즈로도 열립니다. 이를 null segment cipher와 결합하면 guest의 비밀을 알지 못해도 원활하게 평문에 접근할 수 있습니다.
강력한 완화책 (detached headers로 TOCTOU 회피)
온디스크 LUKS 헤더는 항상 신뢰할 수 없는 입력으로 취급하십시오. detached-header 모드를 사용해 검증과 오픈이 보호된 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 메타데이터를 덤프하고 파라미터의 엄격한 허용 목록을 검증합니다 (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
예시 validator (안전한 필드 강제)
```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 policy state에 측정(measure)하십시오.
- 측정된 헤더가 승인된 안전 프로파일과 일치할 때만 복호화 키를 해제하십시오.
운영 지침:
- detached header + MAC을 강제하거나 엄격한 검증을 적용하십시오; 디스크 상의(on-disk) 헤더를 직접 신뢰하지 마십시오.
- attestation의 소비자는 허용 목록에서 패치 이전(pre-patch) 프레임워크 버전을 거부해야 합니다.
버전 및 유지관리자 입장
- cryptsetup maintainers는 LUKS2가 이 환경에서 스토리지 변조에 대한 무결성을 제공하도록 설계되지 않았음을 명확히 했으며; null ciphers는 하위 호환성을 위해 유지됩니다.
- cryptsetup 2.8.1 (Oct 19, 2025)은 비어있지 않은 비밀번호가 설정된 keyslots에 대해 null ciphers를 거부하지만 여전히 segments에 대해서는 null ciphers를 허용합니다.
빠른 점검 및 분류
- 세그먼트(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)를 사용해 여세요.
References
- 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 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HackTricks Cloud

