<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p><br>
</p>
<div class="moz-cite-prefix">Le 10/03/2025 à 17:27, Adrian Vovk a
écrit :<br>
</div>
<blockquote type="cite"
cite="mid:CAAdYy_kDJnqx6SpTLa7LtWmPWthbpgDXMvi1KX3Lr6CJ7+v30A@mail.gmail.com">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<div dir="auto">
<div>Hello,<br>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Mon, Mar 10, 2025,
12:06 Mikko Rapeli <<a
href="mailto:mikko.rapeli@linaro.org" target="_blank"
rel="noreferrer" moz-do-not-send="true"
class="moz-txt-link-freetext">mikko.rapeli@linaro.org</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
On Mon, Mar 10, 2025 at 11:16:25AM -0400, Adrian Vovk
wrote:<br>
> Hello,<br>
> <br>
> Just to see if I understand your concern correctly,
I'll try boiling it<br>
> down to its simplest, by cutting out the need for two
partitions. Here's<br>
> the scenario:<br>
> <br>
> - An attacker replaces the real rootfs with a
malicious one that just drops<br>
> to a shell. The attacker keeps a copy of the original
real rootfs<br>
<br>
This should not be possible without breaking encryption
keys from the device.<br>
If the rootfs is not encrypted with device specific keys
derived from TPM<br>
measurements or dm-verity where root hash has been hard
coded into secureboot<br>
signed UKI binary for the kernel, then the setup is not
secure to start with.<br>
If dm-verity image has been tampered it will fail
signature checks and fail<br>
to mount.<br>
</blockquote>
</div>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">This is inaccurate. systemd's security model
allows for the rootfs to be replaced with a different one.
There's no good way to actually prevent that: all partition
table metadata is spoofable, including UUIDs and whatnot </div>
<div dir="auto"><br>
</div>
<div dir="auto">Of course, if you're using dm-verity on the
rootfs, the attacker can only replace the rootfs with a copy
of itself. But I don't think this is the case here, since the
thread started with the presumption that the attacker can
replace the rootfs.</div>
<div dir="auto"><br>
</div>
<div dir="auto">To be clear, the partition layout I'm thinking
about is: dm-verity protected /usr partitions (A/B copies),
and then a separate rootfs partition that exists just to store
persistent data (/var, /etc, etc). In this scenario, there's
nothing preventing someone from replacing the rootfs
partition's contents with anything arbitrary.</div>
<div dir="auto"><br>
</div>
<div dir="auto">
<div class="gmail_quote">
<blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">>
- The system boots, then tries and fails to decrypt the
fake rootfs.</blockquote>
<blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
> <br>
> - The attacker now starts impeding communication
between the TPM and the<br>
> CPU. Potentially by physically interposing on the bus
and blocking<br>
> communication. Or by glitching the bus so that the
data isn't successfully<br>
> measured. Anyway, the attacker somehow makes TPM
measurements fail<br>
> <br>
> - The attacker unlocks their malicious rootfs, and
then the system<br>
> continues booting. The attacker now gains control of
the system via the<br>
> root shell.<br>
<br>
This means that TPM, firmware, kernel or initrd have been
compromized at<br>
runtime after their TPM measurements and secureboot
signatures have been<br>
verified. A denial of service attack is relatively simple
but any code<br>
executions should be grave bugs which need updates to get
fixed. An initrd<br>
should have only very limited functionality and no
fallback interactive<br>
shells or prompts, or network drivers or daemons.<br>
</blockquote>
</div>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">If you can replace the rootfs (which we've
established: you can), then that rootfs can contain whatever
you want to gain execution early during boot. It can be as
easy as a single symlink in /etc:
basic.target.wants/systemd-debug-shell.service</div>
<div dir="auto"><br>
</div>
<div dir="auto">
<div class="gmail_quote">
<blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
It may be possible to cut down TPM communication and to
make systemd and other<br>
service to wait for longer time but it is simpler to
freeze RAM and CPU<br>
state and change the rootfs entry with physical attack via
JTAG, if such interfaces<br>
are enabled in HW.<br>
</blockquote>
</div>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">The point is to disable the TPM enough that
systemd gives up trying to measure pcrphases, and moves on. If
it continues booting in that case, there's a big problem</div>
<div dir="auto"><br>
</div>
<div dir="auto">
<div class="gmail_quote">
<blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">>
- The attacker stops impeding the communication between
the TPM and the<br>
> CPU. The TPM is still in the same state as it was in
the initrd. The<br>
> leave-initrd pcrphase, and the PCR15 measurement of
the fake root's volume<br>
> key, are both missing<br>
><br>
> - The attacker is in control of the system, and the
TPM is in the right<br>
> state to unlock the real rootfs. The attacker talks
to the TPM to get the<br>
> real rootfs's volume key. Attacker wins<br>
> <br>
> I think, ultimately, this is the same issue as the
one you describe. Do you<br>
> think that's correct?<br>
> <br>
> Lennart would have a better idea than I do of what
mitigations to this<br>
> would look like. But I suspect that:<br>
> <br>
> - You can't MITM the TPM, since the communication is
encrypted<br>
> <br>
> - Other kinds of attacks cause the OS to know that a
measurement failed. So<br>
> perhaps we need to very strict about ensuring that
measurements happen.<br>
> i.e. By not letting the TPM disappear at runtime, and
making sure that<br>
> measurements always succeed (and if it does, failing
to boot or something)<br>
<br>
TOCTOU, time of check vs. time of use bugs may exists but
they should be<br>
very hard to trigger, e.g. require HW debugger level
access.<br>
</blockquote>
</div>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">Well, the TPM is supposed to be secure against
hardware debugger access, in theory. Ditto with CPUs, and JTAG
lockout.</div>
<div dir="auto"><br>
</div>
<div dir="auto">So if there's TOCTOU bugs in our code we need to
be robust against them too.</div>
<div dir="auto"><br>
</div>
<div dir="auto">Anyway, I don't think this is a TOCTOU bug.
Basically, it seems that we're sometimes OK letting
communication to the TPM fail. In which case, an attacker can
cause the communication to fail, and we'll be none the wiser</div>
<div dir="auto"><br>
</div>
<div dir="auto">
<div class="gmail_quote">
<blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">If
device specific encryption key leaks, then the data there
can be modified</blockquote>
<blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
by the attacker. I too fail to see the bug here.<br>
</blockquote>
</div>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">Right, this is what we're trying to avoid.</div>
<div dir="auto"><br>
</div>
<div dir="auto">Basically, the bug is: an attacker does a DOS on
the TPM in such a way that systemd boots to the rootfs without
measuring the `leave-initrd` pcrphase, or the fake rootfs's
pcr15. Once in the rootfs, the TPM doesn't know that it has
left the initrd. And that's game over: the attacker stops
DOSing the TPM, and extracts the encryption keys for the real
rootfs from the TPM.</div>
</div>
</blockquote>
<p>Yes, you can maybe using MITN in order to make pcrextend exit
with 0 exitcode, because the measurement execution is checked in
prcextend. Which is not the case in cryptsetup you may just jam
the communication. (<a class="moz-txt-link-freetext" href="https://github.com/systemd/systemd/blob/bd0d22c2a5bdbf427c68eab630dc06f55dc96c72/src/cryptsetup/cryptsetup.c#L1085">https://github.com/systemd/systemd/blob/bd0d22c2a5bdbf427c68eab630dc06f55dc96c72/src/cryptsetup/cryptsetup.c#L1085</a>.</p>
<p><br>
</p>
<p>Let retry to explain the issue.</p>
<p>crypttab:</p>
<p>root /dev/sda1 tpm2-measure-pcr=yes</p>
<p>var /dev/sda2 tpm2-measure-pcr=yes</p>
<p>root and var enrolled using pcrs=7+11+15</p>
<p><br>
</p>
<p>-> Normal situation</p>
<p>1) Just before opening root LUKS:</p>
<p>PCR15=0 or something predictable<br>
</p>
<p>cryptsetup is used to open root and update PCR15 thanks to
tpm2-measure-pcr=yes</p>
<p><br>
</p>
<p>2) Just before opening the var LUKS:</p>
<p>PCR15=hash1<br>
</p>
<p>cryptsetup is used to open var and update PCR15 thanks to
tpm2-measure-pcr=yes</p>
<p>PCR15=hash2</p>
<p><br>
</p>
<p>3) initrd makes the mount of the fs, makes multiple measurements
(notably on PCR11 with leave-initrd) then chroots and executes
init.</p>
<p><br>
</p>
<p>-> Attack situation</p>
<p>1) Just before opening root LUKS:</p>
<p>PCR15=0 or something predictable<br>
</p>
<p>cryptsetup is used to open root. in this case /dev/sda1 is a
malicious LUKS partition. TPM will not work but if there is no
headless=true option, the attacker can unlock it using his
password. Just after entering the password, the attacker jams the
communication with the TPM making cryptsetup measure_volume_key
returning non zero code, but totally ignored by
systemd-cryptsetup.</p>
<p><br>
</p>
<p>2) Just before opening the var LUKS:</p>
<p>PCR15=0 or something predictable</p>
<p>cryptsetup is used to open var and update PCR15 thanks to
tpm2-measure-pcr=yes. but in this case /dev/sda1 is replaced with
the original /dev/sda1 partition.</p>
<p>PCR15=hash1</p>
<p><br>
</p>
<p>3) initrd makes the mount of the fs, makes multiple measurements
(notably on PCR11 with leave-initrd) then chroots and executes
malicious init.</p>
<p><br>
</p>
<p>Is PCR15 checked against a pre-calculated value saved in the
signed initrd before leaving initrd? If it's not the case, then
when executing the init from the chrooted malicious partition, the
original /dev/sda1 LUKS will be opened and mounted as var. <br>
</p>
<p>Aplanas talked about this check in previous conversation, I'm
wondering if it is the case currently. Otherwise it may be easy
for an attacker to force a measurement drop and foll the initrd
like this case.<br>
</p>
<p></p>
<p><br>
</p>
<blockquote type="cite"
cite="mid:CAAdYy_kDJnqx6SpTLa7LtWmPWthbpgDXMvi1KX3Lr6CJ7+v30A@mail.gmail.com">
<div dir="auto">
<div dir="auto"><br>
</div>
<div dir="auto">Best,</div>
<div dir="auto">Adrian </div>
</div>
</blockquote>
</body>
</html>