wmcelderry / systemd_with_tpm2

Scripts to enable TPM2 on ubuntu 22.04
GNU General Public License v3.0
57 stars 27 forks source link

This doesn't provide perfect security! #2

Open wmcelderry opened 2 years ago

wmcelderry commented 2 years ago

Some would say "there's no such thing as perfect security, so that's no surprise!"

Others would say that "this isn't anywhere near and leaves the door WIDE open."

I'd say it all depends on your use!

This issue is to collect together the debate about the pros and cons.

wmcelderry commented 2 years ago

The first issue I am referring to here is that the initrd is probably not /measured/.

If so an attacker that can write to your /boot directory CAN modify the initrd and access your unencrypted data as root. The attacker would not need any form of interaction or password after the system reboots.

To be fair, if someone can access your initrd storage area, that's a pretty big compromise already - someone who can do this can compromise a lot of systems with this approach! I suspect they could even compromise a passphrase based encryption in the same manned, and possibly even capture the passphrase.

Manouchehri commented 2 years ago

Isn't PCR 11 supposed to check the initrd?

See slide 21. https://www.sstic.org/media/SSTIC2022/SSTIC-actes/tpm_is_not_the_holy_way/SSTIC2022-Slides-tpm_is_not_the_holy_way-forgette.pdf

Manouchehri commented 2 years ago

Noticed that on one of my systems, PCR11 is blank.

Hmm, this repo states:

Starting with Linux 5.17, the initrd measurements are now stored in PCR9

Source: https://github.com/grawity/tpm_futurepcr

So we'd want to check:

PCR0 - To prevent an evil new firmware PCR1 - To prevent booting from another device (UEFI settings) PCR2 - Check for Option ROM Code change PCR3 - Check for Option ROM Configuration change PCR4 - Check boot manager PCR5 - Check boot manager setup (including GPT table) PCR7 - Check SecureBoot PCR8 - To check grub command line PCR9 - To check initrd (this appears to work at first glance, untested) PCR10 - Grub binary (not sure if this is needed) PCR11 - Hash of the Unified kernel image (zeros for me) PCR12 - Overridden kernel command line (zeros for me) PCR13 - System Extensions (zeros for me) PCR14 - Check list of code signing certificates hash

See https://wiki.archlinux.org/title/Trusted_Platform_Module#Accessing_PCR_registers as well.

Checking PCR6 (power states) seems like a bad idea.

And when upgrading the system, we'd maybe want to check:

PCR0 - To prevent an evil new firmware PCR1 - To prevent booting from another device (UEFI settings) PCR2 - Check for Option ROM Code change PCR3 - Check for Option ROM Configuration change PCR4 - Check boot manager PCR5 - Check boot manager setup (including GPT table) PCR7 - Check SecureBoot PCR12 - Overridden kernel command line (zeros for me) PCR13 - System Extensions (zeros for me) PCR14 - Check list of code signing certificates hash

wmcelderry commented 2 years ago

@Manouchehri for your comments and links. Those are good points!

I'm not familiar with the details you are referencing, so I've got a lot of reading to do when I get time! Thanks.

guruevi commented 1 year ago

If you use systemd-cryptenroll, it seems the measurements for initrd are done properly in PCR7

From the man page: For most applications it should be sufficient to bind against PCR 7 (and possibly PCR 14, if shim/MOK is desired), as this includes measurements of the trusted certificates (and possibly hashes) that are used to validate all components of the boot process up to and including the OS kernel. In order to simplify firmware and OS version updates it's typically not advisable to include PCRs such as 0 and 2 in the binding of the enrollment, since the program code they cover should already be protected indirectly through the certificates measured into PCR 7. Validation through these certificates is typically preferable over validation through direct measurements as it is less brittle in context of OS/firmware updates: the measurements will change on every update, but code signatures likely will validate against pre-existing certificates.

My personal opinion is security vs usability. Eg. 7 makes sense in most environments, but do you want to enter a passcode every time a kernel gets updated, or every time hardware/software/firmware updates happen, perhaps if you're at some secret government facility, yes. There are Evil Maid attacks through ThunderBolt, keyloggers or physical data loggers, you can access the LPC bus on some TPM implementations and get some/all data, this is just a small component of the overall solution.

kreijack commented 1 year ago

I tested systemd-boot with a separate kernel and initrd using the kernel 'uefi stub'. I didn't test shim. I checked how the PCRs are affected by changing the files involved in the boot:

conclusion I suggest to use the following PCRs

Even tough only 4 and 9 would be enough. PCR10 is related to the IMA mesurement

MathijsNL commented 1 year ago

I tested without the use of PCR 8, and without it it is possible to add

init=/bin/bash

to the grub parameters and just get full access to the filesystem.

I can highly recommend to add PCR 8 as well. @kreijack You mentioned PCR 12, which looks kinda similar to PCR 8. Do you have any insights on that?

kreijack commented 11 months ago

My understanding is that GRUB uses a different set of PCRs than systemd-boot; so a setup which works in systemd-boot may not work in grub.

guruevi commented 11 months ago

PCR8 should measure the kernel command line and PCR9 the initrd and EFI Load Options for both Grub and systemd-boot. Depending on your setup you may also be able to measure down further in PCR11 to get more of the boot process (including the initrd and other options). https://www.freedesktop.org/software/systemd/man/latest/systemd-pcrphase.service.html

There are different measurements based on whether the EFI is loading a Unified Kernel Image - https://wiki.archlinux.org/title/Unified_kernel_image or whether you are using Grub/systemd-boot (total of 3 different options).

kreijack commented 11 months ago

I checked the systemd-boot sources; it seems to me that PCR8 is not used in systemd-boot:

https://github.com/systemd/systemd/blob/d50bf46f19330bca92e960e3c72888936f143467/src/fundamental/tpm2-pcr.h#L22C14-L22C14