Files
parking_solution/wiki/decisions/disk-os-hardening.md
T
julian 1b86750b0d docs(wiki): firmware/dbx-vs-TPM hardening + create disk-os-hardening page
Real-world park-buzi episode: a UEFI dbx update (delivered via fwupd/LVFS,
NOT apt) revoked a stale GRUB -> panic, and moved PCR 7 -> broke TPM-sealed
LUKS auto-unlock -> passphrase prompt. Recovered by re-sealing PCR 7.

- appliance-provisioning.md: extend the §4 re-seal runbook to name dbx; new
  §4a (fwupd-not-apt, GRUB-panic ordering, PCR-7 re-seal, operator lockdown:
  mask fwupd + remove firmware-updater snap + BIOS-password + passphrase
  escrow) incl. the --test-passphrase-silently-passes-via-TPM trap
  (--disable-external-tokens); gotchas #12/#13.
- disk-os-hardening.md: NEW — resolves a long-dangling wikilink referenced
  from ~18 pages. The *why* of host hardening (5 controls + firmware lockdown);
  commands stay in appliance-provisioning; reconciliation remains the primary
  anti-fraud control.
- index.md: expand the disk-os-hardening catalog line.
- log.md: two note entries.

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
2026-06-30 15:21:32 +02:00

93 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
type: decision
tags: [parking, hardening, threat-model, luks, tpm, secure-boot, grub, firmware, offline-first]
sources: [parking-system-architecture]
updated: 2026-06-30
status: settled
---
# Disk & OS hardening (booth appliance)
The host-level defences that raise the cost of **offline, physical tamper** of a booth PC: full-disk
encryption, TPM-sealed auto-unlock, Secure Boot, a GRUB edit-lock, an unprivileged operator account,
and locking firmware updates away from the operator. This page is the **rationale (the *why*)**; the
step-by-step verified commands live in the [[appliance-provisioning]] runbook (§3–5c, §4a). Settled
across the first real provisioning (2026-06-23) and the firmware-update episode (2026-06-30).
> ⚠ **This is the secondary control, not the main event.** The load-bearing anti-fraud mechanism is
> [[reconciliation]] over the [[append-only-event-chain|signed event chain]]. Disk/OS hardening
> defends the [[threat-model|outsider-with-the-box]] and raises the cost of offline tamper — it does
> **not** replace reconciliation, and it cannot stop a *legitimate, logged-in* operator from
> committing fraud through the app (that's what the signed ledger + reconciliation are for).
## What it defends against
The appliance sits on-site, physically reachable by the [[threat-model|booth operator (the primary
adversary)]] and by an outsider who can open the case. Without host hardening, either can:
- **Pull the SSD** and read/alter the SQLite ledger offline → FDE (LUKS) defeats this.
- **Boot a live USB** to mount and edit the disk → Secure Boot + TPM-sealing (PCR 7) defeats booting
a tampered/unsigned kernel; FDE keeps the data unreadable.
- **Edit the GRUB cmdline** (`init=/bin/bash`) for a no-login root shell on the *decrypted* disk →
the GRUB edit-lock defeats this (the TPM seal does NOT — see below).
- **Escalate from the operator login** (sudo, `docker`/`lxd` groups) → the unprivileged-operator
model defeats this.
## The five controls and why each is shaped the way it is
| Control | Choice | Why this shape (the load-bearing nuance) |
| --- | --- | --- |
| **FDE** | LUKS, **passphrase** at install (not the installer's "hardware-backed" option) | The 26.04 installer's automated FDE profiler fails on this firmware (`PCR_UNUSABLE`/`dbt`). Passphrase LUKS + a *manual* TPM seal sidesteps it and lets us pick PCRs. The passphrase slot is the **permanent recovery key**. |
| **TPM auto-unlock** | `systemd-cryptenroll`, **PCR 7 only** | Unattended reboot is a hard requirement (no operator types a passphrase). PCR 7 = Secure-Boot policy: catches the attack that matters (disabling Secure Boot) **without** churning on kernel/GRUB updates (PCRs 4/8/9 → would drop to passphrase every boot). **Keep BOTH slots** — slot 0 password (recovery), slot 1 tpm2 (auto-unlock); the TPM is never the only key. |
| **Secure Boot** | Enabled, **Deployed Mode**, stock MS keys | Ubuntu's signed shim needs stock `db`. Reaching the installer with Secure Boot ON is itself proof the MS third-party UEFI CA is trusted. |
| **GRUB edit-lock** | password, **edit-only** (`--unrestricted`) | Closes the `init=/bin/bash` root-shell hole. **The PCR-7 TPM seal does NOT cover this** — editing the cmdline doesn't change PCR 7, so the TPM still releases the key and the attacker lands on the decrypted disk. Edit-only so the box still boots **unattended** (password required only to *edit* entries). |
| **Operator account** | unprivileged, auto-login; separate **admin**+sudo | The operator is the adversary; their OS identity must not be able to escalate. Strip `sudo`, and the latent-escalation groups `lxd`/`docker` (both root-equivalent) + `lpadmin`. Admin is a distinct, no-auto-login identity. |
See [[tpm]] for the TPM-2.0 analysis (why PCR-only sealing, bus-sniff limits, TPM-vs-[[atecc608|ATECC608]]).
## Firmware / UEFI dbx updates — a hardening surface AND an operator threat
Settled 2026-06-30 after a real incident on `park-buzi`. This is the non-obvious one, because it
turns a routine "security update" into a booth-availability risk:
- **UEFI `dbx`** (the Secure Boot revocation database) and BIOS firmware are delivered by
**`fwupd`/LVFS — a channel SEPARATE from APT** (Ubuntu's GNOME "Firmware Updater" = the
`firmware-updater` snap). A clean `apt list --upgradable` does NOT mean no firmware update is pending.
- **It can brick boot:** a new dbx against a *stale* GRUB/shim **revokes the installed bootloader** →
Secure Boot refuses it → unbootable / GRUB panic. Correct order: `apt full-upgrade` (current
`grub-efi`/`shim-signed`) **first**, then dbx.
- **It breaks auto-unlock:** even with a current GRUB, applying dbx **moves PCR 7** → the TPM refuses
the LUKS key → next boot falls back to the slot-0 passphrase prompt (not a brick). Recover with the
PCR-7 re-seal runbook ([[appliance-provisioning]] §4/§4a).
- **Threat-model consequence:** a firmware/dbx update makes the booth need a passphrase to boot
unattended — so the **operator must be unable to trigger one, and must never hold the passphrase.**
Lock it down: `systemctl mask fwupd.service fwupd-refresh.timer`, `snap remove firmware-updater`,
a **BIOS admin password** that gates *entering setup* (so the operator can't disable Secure Boot /
change boot order), and the **slot-0 passphrase escrowed off-machine** (same custody as
`EVENT_SIGNING_KEY` / `BACKUP_KEY`). Firmware maintenance becomes **admin-only, on-site, deliberate**.
> The booth is unattended-bootable **only while the firmware / Secure-Boot state is frozen** — that is
> the security property, not a bug. The cost is that legitimate firmware maintenance now needs physical
> presence + the slot-0 passphrase + a PCR-7 re-enroll.
> **⚠ Verification trap:** `cryptsetup … --test-passphrase` **silently passes via the TPM token** (a
> false safety signal). Before any firmware change, prove a *typed* passphrase still unlocks the disk
> with `--disable-external-tokens` — see [[appliance-provisioning]] §4a.
## Where the commands live
This page is the rationale. The **verified, run-on-real-hardware commands** are in
[[appliance-provisioning]]: §1 BIOS, §2 Secure-Boot live-USB check, §3 encrypted install (the `dbt`
workaround), §4 TPM seal (PCR 7) + re-seal runbook, **§4a firmware/dbx lockdown**, §5 GRUB edit-lock,
§5c admin-vs-operator accounts. Komodo Periphery is folded into the same hardened surface as a
root-capable remote agent — see [[fleet-deployment-komodo]] (bind to the NetBird interface only).
## Relates
- [[appliance-provisioning]] — the runbook (commands); this page is its *why*.
- [[tpm]] — TPM 2.0 analysis (sealing, PCR choice, limits, vs ATECC608).
- [[threat-model]] — the operator-adversary framing this hardening serves.
- [[reconciliation]] / [[append-only-event-chain]] — the **primary** anti-fraud control this
complements, never replaces.
- [[fleet-deployment-komodo]] — Periphery as part of the trusted computing base.