pbatard / rufus

The Reliable USB Formatting Utility
https://rufus.ie
GNU General Public License v3.0
28.29k stars 2.54k forks source link

Feature Request: Warn if media will no longer be bootable after Q1 2024. #2244

Open rcmaehl opened 1 year ago

rcmaehl commented 1 year ago

<!-- PLEASE READ THIS CAREFULLY:

  1. You MUST read and complete the steps from the checklist below, by placing an x into each [ ] (so that it shows '[x]', NOT '[ x]' or '[x ]'), BEFORE clicking on 'Submit new issue'.

  2. Failure to perform these steps, WHICH ARE ONLY THERE TO HELP YOU, will usually result in your issue being dismissed without notice.

  3. If you are reporting an issue when trying to run Rufus, or when trying to boot a media created by Rufus, you MUST provide a log, period. Please do not assume that the developer(s) will be able to "guess" the specifics of your environment, what image you used, what type of media you used it with or the many many other critical parameters that the log provides data for. To investigate an issue, a log from Rufus is ALWAYS required.

  4. If you still choose not to provide a log when reporting a problem, you agree that your issue will be closed without any further investigation.

YOU HAVE BEEN WARNED. -->

Checklist

Additionally (if applicable):

Issue description

Due to changes to the Windows Boot Manager from CVE-2023-24932. Previously created boot media will no longer be able to boot once enforcement begins Q1 of 2024. If possible, detect this issue and provide a warning.

https://support.microsoft.com/en-us/topic/kb5025885-how-to-manage-the-windows-boot-manager-revocations-for-secure-boot-changes-associated-with-cve-2023-24932-41a975df-beb2-40c1-99a3-b3ff139f832d#avoidissues5025885

Log

N/A

Hrxn commented 1 year ago

Yikes...

Do I get that right, any official ISOs past a given date will be good, then? But they have not released anything yet, right?

pbatard commented 1 year ago

Aha, I was wondering how long Microsoft would try to swipe that CVE under the carpet until they had no choice but to take action.

If possible, detect this issue

Yeah, that's the major issue here. Microsoft have some kind of revocation list, but of course, they didn't make it downloadable as a standalone (because, why would they? Security through obscurity has always worked WONDERS for everybody....), so it's going to be a PITA.

and provide a warning.

I'll try to do that. But I'm not going to rush into it, and spend time that I don't have being a trailblazer. So I'm going to tag this as deferred for now.

rcmaehl commented 1 year ago

Aha, I was wondering how long Microsoft would try to swipe that CVE under the carpet until they had no choice but to take action.

If possible, detect this issue

Yeah, that's the major issue here. Microsoft have some kind of revocation list, but of course, they didn't make it downloadable as a standalone (because, why would they? Security through obscurity has always worked WONDERS for everybody....), so it's going to be a PITA.

and provide a warning.

I'll try to do that. But I'm not going to rush into it, and spend time that I don't have being a trailblazer. So I'm going to tag this as deferred for now.

Sounds good! I mean there's essentially an entire year to work on this

rcmaehl commented 1 year ago

Looks like checking for

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Secureboot\AvailableUpdates dword >= 0x10 may work. I'll need to apply the revocation steps myself later to verify that the registry value doesn't change after applying the list.

pbatard commented 1 year ago

I saw the registry key, but I don't think it's enough, because it only tells if the current machine might have been upgraded to reject old MS bootloaders, but not if the ISO contains one.

In other words, if we only check for the registry key, we will warn the user regardless of whether the ISO they selected uses an old or new bootloader, whereas we obviously don't want to warn about ISOs that use the new bootloaders.

So, again, to properly display the warning, we need to check the bootloader's hash against the revoked hashes.

From my understanding, the registry key is just a switch to tell the system to update the UEFI revocation list with the hashes of the old bootloaders since, understandably, Microsoft does not yet want to apply revocation wholesale and leave users booting older Windows ISOs facing a Secure Boot validation error. They only want to do that for users who opt-in.

Now, another potential workaround I am considering, provided we can actually download the new bootloaders from Microsoft's servers without having to extract a whole ISO (the issue being that I can't just store a copy of these bootloaders on a server somewhere for Rufus to download, without committing copyright infringement, so we have to hope that they're in a small enough .cab/.msi downloadable directly from Microsoft) would be for Rufus to replace the old soon-to-be-revoked bootloaders with the new non-revoked version, since these should be fully interchangeable.

The problem with this workaround however is that this would potentially only work for the initial USB boot (pre-installation phase) and not for the post file-copy (re)boot, as my current assumption is that during initial file copy, Microsoft picks the bootloaders from install.wim/install.esd rather than the ones from the USB (if you look at the wim/esd you'll find bootmgr.efi in Windows\Boot\EFI\), and therefore we'd have to replace them there for things to work, which will be very costly as manipulating the full >4 GB .wim is a very time consuming operation. If we are lucky however, the bootmgr.efi Microsoft installs in the file copy phase is the one found in boot.wim, which, on the other hand, we should be able to replace, as we are already performing boot.wim image manipulation to add the registry keys for the TPM/Secure Boot bypass, and thus, changing a file there would be a no brainer (well, except for people who get Rufus from the Windows Store, because the Windows Store version cannot mount .wim files, so users there will be screwed).

I am obviously planning to test this when I have a chance (which may not be before a couple of month or worse) and when I have upgraded a system to the new revoked hashes (which I will need to do carefully and make sure to keep a copy of the revocation list before and after, since I need to isolates these bloody hashes that Microsoft SHOULD provide publicly but, no matter where I looked so far, doesn't!)...

stdin82 commented 1 year ago

and when I have upgraded a system to the new revoked hashes (which I will need to do carefully and make sure to keep a copy of the revocation list before and after, since I need to isolates these bloody hashes that Microsoft SHOULD provide publicly but, no matter where I looked so far, doesn't!)...

https://uefi.org/revocationlistfile https://uefi.org/sites/default/files/resources/dbx_info.csv

pbatard commented 1 year ago

Aha! Since we're talking about an upcoming revocation, and Microsoft is the sole entity that controls the revocation list, I didn't think they would have started to add DBX entries prior to Q1 2024, since it means that we're definitely going to see Secure Boot validation errors with Windows media long before that date (because motherboard manufacturers are not going to cherry pick what goes in the DBX they apply but pick the most recent).

Their process to decide whether a bootloader should be flagged as vulnerable or not is less than straightforward though, per https://uefi.org/sites/default/files/resources/dbx_release_info.pdf:

The following is a summary of Microsoft’s revocation techniques used for the Black Lotus vulnerability: • Boot Managers from Windows 8 to Windows 10, version 1507: revoked by DBX entries • Boot Managers from Windows 10, version 1507 to Windows 10, version 1607: revoked by hash by SKU SiPolicy • Boot Managers from Windows 10, version 1703 to today: revoked by version number by SKU SiPolicy

So, we do not have a complete list of hashes of vulnerable bootloaders, and we're going to have deal with this mess to decide whether a bootloader has been revoked or not, which, and I very much hope I can be proved wrong here, Microsoft is providing no explicit details about. Especially, it does not say what version numbers are being revoked, and it is also my impression that the hashes revoked by SKU SiPolicy are not in the UEFI CSV...

pbatard commented 1 year ago

Indeed, Microsoft explicitly state here:

We have released the DbxUpdate.bin file for this issue on UEFI.org. These hashes include all revoked Windows boot managers released between Windows 8 and the initial release of Windows 10 that do not respect the Code Integrity Policy.

So, everything that is meant to be rejected after Windows 10 1507 has not been made public by Microsoft, and, as much as I'd very much like it to be otherwise, my initial comment about Microsoft not publishing information that they should provide still stands (and is made worse by the fact that we can't just rely on getting our hands on a list of hashes).

pbatard commented 1 year ago

I guess the other option we have, since we're going to have to deal with a version whatershed anyway, is to not bother with hashes and just check the version number from the EFI bootloader to display a warning if it's anything below the 22H2 v2's version (which appears to be 10.0.2261.1702 vs 10.0.2261.1 for 22H2 v1). Of course it would be nice to have the actual version that acts as the separator from Microsoft themselves...

Note that there is an additional SECURITYVERSION variable in the resource file of the EFI bootloaders, which is probably tied to the new SiPolicy feature, but for those who might be wondering if the 2.0.0.2 VersionEx referenced here has anything to do with the actual version filtering, and could be used against SECURITYVERSION, that latter variable is set to 1.0.0.0 in all the bootloaders I see, and considering that the UEFI variable is described as Set’s the code integrity boot policy version, it seems to be more about defining the minimum version of the SiPolicy environment than defining the actual minimum version of the bootloaders that should be rejected (else, I'd expect Microsoft to describe it as Sets the minimal version of bootloaders accepted by the boot policy). In short, this seems to be a version number that applies when you want to replace a an existing SkuSiPolicy.p7b and not something that give us a precise idea of the bootloader version below which a EFI bootloader should be considered vulnerable.

pbatard commented 1 year ago

Interestingly, if we need to download a bootmgfw.efi replacement, we may end up using the same method as the actual Black Lotus malware (See "1. An installer deploys files to the ES") to download the file from Microsoft by fetching the executables straight from https://msdl.microsoft.com/download/symbols/.

It does seem however that Microsoft might have taken steps to try to prevent these kind of downloads as I can't seem to manage to get this to work.

For instance, the following to retrieve a PDB will work just fine (symbols for the latest bootmgfw.efi from 22H2 v2 ISOs):

wget -c -U="Microsoft-Symbol-Server/10.0.0.0" https://msdl.microsoft.com/download/symbols/bootmgfw.pdb/F2B888C9A171A1FC2F9587649411BFD12/bootmgfw.pdb

But trying to do the same for the associated binary, which should resolve to https://msdl.microsoft.com/download/symbols/bootmgfw.efi/B647817D2ba000/bootmgfw.efi and should be served in the same manner as the PDB by Microsoft's symbol servers, just doesn't seem to work (and the same is true for a similar-but-not-the-exact-same URL that Black Lotus uses to download its own bootmgfw.efi, though of course, we want to be careful relying on this one to tell us anything as Microsoft may have deliberately chosen to remove it to stop the spread of the malware).

Using the same method I used to generate the bootmgfw.efi URL for notepad.exe (method is basically described here) yields https://msdl.microsoft.com/download/symbols/notepad.exe/E798EFB45a000/notepad.exe which downloads just fine through wget -c -U="Microsoft-Symbol-Server/10.0.0.0"

Goddammit, this is so annoying! What the hell does one have to do (besides becoming a full blown malware author) to be able to download a simple executable from Microsoft??

pbatard commented 1 year ago

Even more interestingly, since it appears that we can easily download Windows 8.1's diskcopy.dll from https://msdl.microsoft.com/download/symbols/diskcopy.dll/54505118173000/diskcopy.dll, that Black Lotus trick may help us restore the MS-DOS installation functionality, that we had to remove from Windows 10 or later on account that Microsoft had removed this DLL (which contains a full blown MS-DOS floppy disk image) from recent Windows version. 😉

pbatard commented 1 year ago

Gotta also leave https://support.microsoft.com/en-us/topic/kb5025885-how-to-manage-the-windows-boot-manager-revocations-for-secure-boot-changes-associated-with-cve-2023-24932-41a975df-beb2-40c1-99a3-b3ff139f832d#updatebootable5025885 here. Of course, it would be A LOT better if Microsoft did bother to check the "content" they provide an have an actual working hyperlink for:

If you use a bootable disk image (ISO), a CD-ROM, or DVD media, update the media by following the instructions here.

In short, Microsoft needs to provide a direct download for the non-vulnerable bootmgfw.efi for all archs, if they want their efforts against Black Lotus to be taken seriously, because they have to consider the case of customers updating boot media for a different arch than the current system (e.g. ARM64 from x86_64) that doesn't force folks to go through a full blown multi GB ISO/ESD download just to extract a 2 MB file...

pbatard commented 1 year ago

What a load of crap this whole thing is!

So I updated a system following the 3. APPLY the revocations steps from Microsoft, doing everything as described (double reboot, wait 5 minutes, confirm in Event Viewer that there's an entry that says that DBX has been updated) and then created a Windows 8.1 bootable media (from en-gb_windows_8.1_with_update_x64_dvd_4048142.iso, SHA-1 1F18420D65956DFE56E2359DA71AB6C363146570), fully expecting Secure Boot to produce a validation error, as indicated by Microsoft... but the media boots just fine in a Secure Boot environment...

So much for:

• Boot Managers from Windows 8 to Windows 10, version 1507: revoked by DBX entries

Unless both Microsoft and Linux are lying, my system should have the latest DBX applied:

root@debian:~# fwupdmgr get-devices
(...)
├─System Firmware:
│ │   Device ID:          a45df35ac0e948ee180fe216a5f703f32dda163f
│ │   Summary:            UEFI ESRT device
│ │   Current version:    53
│ │   Minimum Version:    53
│ │   Vendor:             Intel(R) Client Systems (DMI:Intel Corp.)
│ │   Update State:       Success
│ │   GUIDs:              f4cd40f8-4947-4069-bd4d-d5987adefc79
│ │                       230c8b18-8d9b-53ec-838b-6cfc0383493a ← main-system-firmware
│ │   Device Flags:       • Internal device
│ │                       • Updatable
│ │                       • System requires external power source
│ │                       • Needs a reboot after installation
│ │                       • Cryptographic hash verification is available
│ │                       • Device is usable for the duration of the update
│ │
│ └─UEFI dbx:
│       Device ID:        362301da643102b9f38477387e2193e57abaa590
│       Summary:          UEFI revocation database
│       Current version:  423
│       Minimum Version:  423
│       Vendor:           UEFI:Linux Foundation
│       Install Duration: 1 second
│       GUIDs:            c6682ade-b5ec-57c4-b687-676351208742 ← UEFI\CRT_A1117F516A32CEFCBA3F2D1ACE10A87972FD6BBE8FE0D0B996E09E65D802A503
│                         f8ba2887-9411-5c36-9cee-88995bb39731 ← UEFI\CRT_A1117F516A32CEFCBA3F2D1ACE10A87972FD6BBE8FE0D0B996E09E65D802A503&ARCH_X64
│       Device Flags:     • Internal device
│                         • Updatable
│                         • Needs a reboot after installation
│                         • Device is usable for the duration of the update
│                         • Only version upgrades are allowed
│                         • Signed Payload
(...)

And I can tell that Secure Boot is really enabled and enforcing validation, since I do get a big fat Secure Boot validation error when I try to boot the unsigned UEFI Shell...

Someone, somewhere, is not telling the truth...

stdin82 commented 1 year ago

Maybe the efi files from that iso are not revoked? i checked SHA-256 of bootx64.efi & bootmgfw.efi from en_windows_8.1_with_update_x64_dvd_6051480.iso, they are not listed in dbx_info.csv

pbatard commented 1 year ago

i checked SHA-256 of bootx64.efi & bootmgfw.efi from en_windows_8.1_with_update_x64_dvd_6051480.iso, they are not listed in dbx_info.csv

The thing is, if you try to lookup plain SHA-256's in the CSV, from a revoked executable, you will not find it either.

That's because the "flat" SHA-256's provided by Microsoft are not the SHA-256 you get by computing the hash for the whole file (because, of course, that would be too straightforward, and who wants to be straightforward and non-obtuse when dealing with matters of security...), but the hash you get by Frankenstein's Monstering only a selection of sections from it (and, yeah, technically, that might make sense as the Secure Boot signature does not apply to all the PE data in the first place, so one could defeat the DBX by altering one of these sections, as they wouldn't invalidate the signature, but would change the hash from the DBX, though I would counter with WHO IN THEIR RIGHT MIND DECIDED THAT HASHING A FILE FOR FRIGGING DIGITAL SIGNATURE VALIDATION SHOULD NOT BE ON THE WHOLE ORIGINAL SOURCE BINARY BUT INSTEAD ON SECTIONS CHERRY PICKED AT RANDOM?!? HOW HARD WOULD IT HAVE BEEN TO DESIGN A NEW PE CONTAINER EXTENSION THAT COULD EMBED THE ORIGINAL BINARY WHOLESALE + DIGITAL SIGNATURE INTO A SIGNED PE FILE INSTEAD OF THIS COMPLETE SECURITY ABOMINATION THAT ULTIMATELY FORCES EVERYONE TO HAVE DEAL WITH THIS MICROSOFT INDUCED BULLSHIT?). So, if all you have is a EFI binary, and you want to find out if it's in the Microsoft published DBX, well, better be ready to code your own SHA-256 hashing application, because good luck finding a standalone SHA-256 computation application that can deal with the intricacies of PE hashing for Secure Boot...

Thankfully, after much searching and sieving through bullshit, I found that the obscure PE256 value that Microsoft also does provide in the CSV is actually the SHA-256 "hash" that Get-AppLockerFileInformation reports when you feed it a Secure Boot signed UEFI executable.

For instance, if you issue Get-AppLockerFileInformation bootx64.efi from PowerShell for the bootx64.efi of en-gb_windows_8_x64_dvd_915412.iso, you get Hash: SHA256 0xCF7F9E7D091023A1A1C3F5CBF7DDACF7B18F03A4D07961F71506FE9DF4388EEE, and you will find that this last value is in the CSV under PE256, whereas the standard SHA-256 for that file is BEA5931767DCA4C46EF7D6AD73E6913A592860138D3FC82056289B8DFF337940 and does not match the 196243A87389B47FC9033AF3884F3FF0A5C891D80E22C82D2ECD5B9A3434186E SHA-256 that Microsoft expects for that file in the CSV.

All this to say that, whereas Microsoft were supposed, and have indicated, that all their Windows 8, 8.1 and 10 UEFI bootloaders prior to 1507 should have been entered in the DBX, the bootx64.efi from en-gb_windows_8.1_with_update_x64_dvd_4048142.iso certainly has not been, because its PE256, as computed by Get-AppLockerFileInformation is CD2CFDA64B9D6DB3CA88D27B3F90453ABCD842844A3B45696B90BE54E58AAE04, and that value is NOT in the bloody DBX.

And I guess that, now that you know how to validate whether a Windows UEFI bootloader executable is in the DBX, you too can play the game of "What other bootx64.efi/bootmgfw.efi did Microsoft forgot to register for DBX exclusion when they said it should be excluded?

Oh and incidentally, trying to boot a USB media created from en-gb_windows_8_x64_dvd_915412.iso on my updated test machine does produce a Secure Boot security violation as expected...

stdin82 commented 1 year ago

I see the standard SHA-256 of bootmgfw.efi (both x86/x64) from Windows 8.1 update KB3084905 are listed though, and Get-AppLockerFileInformation result match the listed PE256 Authenticode

neither values are listed for 6051480.iso files

the list might have glitches, or they forgot to revoke some files

pbatard commented 1 year ago

Yeah, my worry here is that those missed EFI bootloaders, which the DBX does let through (it's not a list issue, it's a DBX issue, as I did validate that these bootloaders are being let through on a fully updated system), might be compatible with newer Windows (whilst ignoring the SKUSiPolicy.p7b which is how Windows 10 1507+ bootloaders are being filtered out), meaning that the Black Lotus team may just have to install one of these, and folks who went through all the steps to prevent Black Lotus might still get infected with Black Lotus regardless...

pbatard commented 1 year ago

Note: I have just e-mailed the UEFI Forum administrators as well as the Microsoft Secure Boot signing team with my concerns about these missing Windows 8.1 bootloaders from the DBX.

Oh, and for the record, these bootloaders were built in 2014.03, and look a bit too early to have benefited from the post 2015.07 revocation features...

UPDATE: On advice from Microsoft, I have also created a new vulnerability report (VULN-102832) at https://msrc.microsoft.com/report/vulnerability.

pbatard commented 1 year ago

A few more random notes, for those who might be interested in this whole thing:

  1. If you copy %systemroot%\System32\SecureBootUpdates\SKUSiPolicy.p7b to the efi\microsoft\boot\ directory of boot media created from a post 1507, pre 2305 Windows ISO (tested with a Windows 10 1703 bootable USB created with Rufus), you get the expected Microsoft equivalent of a Secure Boot Security Violation with the Recovery screen below, with a The digital signature for this file could not be verified / Error code: 0xc0000428 message:
    Sany4910
  2. In an unexpected Microsoft did the right thing for once, it appears that the SKUSiPolicy.p7b file is universal, which means that the version you get from an x86_64 Windows installation contains the revocations for ARM64, and vice versa. This is of interest to us if we plan to automatically add SKUSiPolicy.p7b to Windows media created by Rufus (see below).
  3. Windows 7 has never been Secure Boot compatible (the bootloaders are signed by Microsoft... but not with the UEFI Secure Boot credentials), so there's no need to revoke anything there as you'll get a Security Violation regardless.
  4. It appears that Microsoft Hyper-V looks at the host system's SKUSiPolicy.p7b to check if the UEFI bootloader should be trusted, meaning that, even if the virtual disk you boot from does not have an SKUSiPolicy.p7b present, you will get a standard Secure Boot Security Violation (rather than the 0xc000042 Recovery screen) if that bootloader happens to have been revoked in the host's SKUSiPolicy.p7b.
  5. Adding SKUSiPolicy.p7b to USB media created from the en_windows_8.1_with_update_x64_dvd_6051480.iso or en-gb_windows_8.1_with_update_x64_dvd_4048142.iso ISOs (the two Windows 8.1 ISOs whose bootloaders appear to have been "forgotten" by Microsoft for exclusion) still results in media that boots in an updated system, meaning that Microsoft did not voluntarily exclude these bootloaders from the DBX on account that they were modern enough for SKUSiPolicy.p7b to apply...

At this stage, considering that trying to secure systems of unaware users is something that applications should strive for (rather than let unaware users potentially get infected through known easily patchable security holes), I am planning to have Rufus automatically copy the system's SKUSiPolicy.p7b to the boot media when a efi\microsoft\boot\ is detected there and either SKUSiPolicy.p7b does not exist, or one exists but it is older than the system's.

My reasoning is that, in an ideal world, all the bootloaders for which SKUSiPolicy.p7b applies would have been added to the DBX, but they haven't been because the DBX is actually running out of space and Microsoft (as well as the Shim folks) devised alternate methods that mirror what the DBX does without actually using the DBX. So, in an ideal world, these Microsoft bootloaders should generate a Security Violation on up to date Secure Boot enabled systems regardless of whether a SKUSiPolicy.p7b exists or not, and we really don't want users to get the idea that everything is fine and dandy when they are booting a media that is known to be potentially problematic and/or used as vector of infection. Especially, it needs to be hammered to users that, if they get a Security Violation and still want to boot that media, they can always disable Secure Boot. But then that decision to boot known insecure bootloaders becomes their explicit choice and is not something they'll be able to dismiss with a "Well, I didn't know I was potentially putting my system at risk..."

And this is where we might for once be helped by SKUSiPolicy.p7b appearing to be universal, as my one worry was that trying to use the SKUSiPolicy.p7b from an x86_64 system to create an ARM64 boot media would leave that ARM64 media open, on account that Microsoft may have chosen to produce arch-specific SKUSiPolicy.p7b's...

stdin82 commented 1 year ago

Doesn't KB5025885 article state that SKUSiPolicy.p7b should not be copied to the boot media (ISO, USB, DVD..)?

pbatard commented 1 year ago

Doesn't KB025885 also not provide any instructions on how one should update ISO/USB/DVD media ("update the media by following the instructions here." with no hyperlink)?

Again, there are no two ways of going on about bootloaders that should be revoked because they can potentially be used to infect one's system: They must be filtered out with an obvious security violation on a Secure Boot enabled system, so that users are clear about what they are about to do.

Now, of course, in a context where you either created your own media (which is the context of the KB) or you are using media that came from Microsoft themselves, it does make little sense to try to filter the bootloaders because that media should be considered safe, and SKUSiPolicy.p7b should be applied to the installed system either directly (post 2305 images) or through Windows update pre (2305). Plus, because that statement is extraordinarily "blanket" and does not provide even a hint of why, I'm half convinced that this note is really about not copying SKUSiPolicy.p7b to media that use non Microsoft bootloaders (such as GRUB, etc).

However, in the context of Rufus, I have no way of telling if the source media is safe (and I am not going to add a very costly SHA-1 validation to check for retail ISOs, especially as a lot of folks are going to use MCT ISOs anyway which should be considered safe but cannot be validated for safety). Furthermore, the creation of boot media using Rufus from a Black Lotus infected ISO (or a Black Lotus derivative) is a real scenario that I expect to happen, so, again, I do want users to make their own explicit decision (especially if they are using dodgy-sourced ISOs) when it comes to potentially lowering the security of their system as well as nudge them towards using a more up to date ISO. And, yeah, I am well aware this will annoy a lot of people, but that's how security works, and the minute you attempt to compromise security for convenience (which, IMO, is what Microsoft are doing by not advising people to copy SKUSiPolicy.p7b to post 1507 bootable media), you lose security.

So, I am just going to re-state what I just said above, regardless of what Microsoft states (who, as we have seen, are not impervious to botching security): In an ideal world, all the Microsoft EFI bootloaders prior to 2305 should have been added to the UEFI DBX and should generate a Security Violation in a Secure Boot enabled environment. As such, so that the majority of users remain safe, especially if they are using ill-sourced ISOs, I want Rufus to create media that behaves as close as possible to that ideal situation, and this entails going against Microsoft's "recommendations" and copying the system's SKUSiPolicy.p7b to the media.

pineapple63 commented 1 year ago
4. It appears that Microsoft Hyper-V looks at the host system's `SKUSiPolicy.p7b` to check if the UEFI bootloader should be trusted, meaning that, even if the virtual disk you boot from does not have an `SKUSiPolicy.p7b` present, you will get a standard Secure Boot Security Violation (rather than the `0xc000042` Recovery screen) if that bootloader happens to have been revoked in the host's `SKUSiPolicy.p7b`.

Seems as though Microsoft Surface devices also look at that file to decide what should trigger a secure boot violation Just now i was doing some experementing with a Surface Go 3 (which i have applied the revocations to, its the same device that i made the discovery with microsofts annoying "more secure than normal secure boot" thing), i downloaded the latest recovery image for it, only to find that microsoft hadn't released an updated (post 9th of May) recovery image, the files in the image were showing as last modified in April (so out of curiosity i tried booting the image (which i copied to a USB, as the recovery images are supplied as a ZIP file), and with secure boot enabled (both "Microsoft only" and standard secure boot settings), it was doing exactly what it does for a secure boot violation, it only booted when i temporarally disabled secure boot (and yes, i did re-enable secure boot afterwards))

pbatard commented 1 year ago

@pineapple63, thanks for the report.

That's actually part of the reason why I think Microsoft's "advice" about not copying SKUSiPolicy.p7b to Windows bootable media is something that can/should safely be ignored, because if you don't copy that file then any non-Microsoft machine you boot from will pretend that everything is fine and dandy, whereas, on Microsoft controlled hardware, be it virtual or real, if you boot the same media, even without SKUSiPolicy.p7b, you get an explicit UEFI Security Violation.

So, clearly, Microsoft, in its actions (rather than in its words) is telling us that any of their pre 2305 EFI bootloaders should generate a Security Violation. And the only way to get that on non-Microsoft controlled hardware, for post 1507 media, is to manually copy the system's SKUSiPolicy.p7b, which is why, if there's no other possibility (such as replacing pre 2305 bootloaders with more recent ones, which, even if we were to have direct download access to such bootloaders from Microsoft, is not guaranteed to be viable if we also have to replace these bootloaders in install.wim), I am planning to do just that in Rufus...

pbatard commented 1 year ago

Update from Microsoft with regards to the missing DBX entries MSRC case:

Thank you again for reporting this behavior. Microsoft is working on a comprehensive fix that will update the DBX to include additional boot loaders. However, due to the complexity of the fixes involved, we are targeting January 2024 for the next update.

So, yeah, they acknowledged that their DBX update is currently incomplete, which I'm going to assume means that you might still be able to get infected by Black Lotus, on a fully up to date system, until January 2024...

pbatard commented 1 year ago

Tonight, on the ongoing saga of whatever the heck Microsoft is doing to try to mitigate Black Lotus we attempt to take a closer look at:

• Boot Managers from Windows 10, version 1507 to Windows 10, version 1607: revoked by hash by SKU SiPolicy

The idea is that, since I am planning to detect EFI bootloaders that have been revoked by the DBX in Rufus and warn the user about them (hence why I just added PE256 hash support), I also wouldn't mind being able to do that for bootloaders that have been revoked in the .p7b.

That's because, as one would expect, SKUSiPolicy.p7b does contain a bunch of hashes, which you can plainly see by looking at the binary and also can (more or less) nicely convert to the kind of Security Policy XML file they fed to WDAC Wizard to create the .p7b.

You can download the converted XML below: SKUSiPolicy.zip

Allegedly, all of the ID_DENY_D_#### hashes you can see in the file are the PE256's of the Windows 10 'bootloaders' that Microsoft wants to flag (that sure is a lot for just 1 year of Windows 10 releases, even if you factor in that it's for x86_32, x86_64, ARM64 and(?) ARM. Oh, and don't ask me why some of these hashes are duplicated: it's the .p7b that's duplicating them)... except none of these hashes appear to match the PE256 of Windows 1511's bootx64.efi or bootmgr.efi and I did find some information that, yes, it is really a PE256 that is being used in the .p7b, so it's not a matter of using the wrong hash algorithm (by the way, if you want to compute the PE256 without using PowerShell, I found that you can also use sigcheck with option -h).

Soooo, the question now becomes: What the hell is Microsoft hashing then???

I guess it makes a modicum of sense that Microsoft would not use the EFI hashes, since SKUSiPolicy.p7b is actually referenced from these bootloaders and ideally anything EFI that should be revoked should be handled by the DBX, though of course, if the point is to spare space of the DBX, then by all means WDAC revocation policies should start at the EFI level, including the EFI bootloader that performs WDAC denial.

I have tried to see if winload.exe from boot.wim was the file being hashed, since it's allegedly the first exe that gets executed after exiting EFI, but this appears not to be the case either. And I haven't found any .exe/.dll/.efi on en_windows_10_multiple_editions_version_1511_x64_dvd_7223712.iso itself with a PE256 that appears in SKUSiPolicy.p7b.

So, if anyone wants to pick a post 1507 pre 1607 Windows 10 ISO to play the "What the hell is Microsoft actually hashing in SKUSiPolicy.p7b?" game, feel free to join the "fun"...

stdin82 commented 1 year ago

1607 ISO is the oldest i still keep :grinning: and i did find PE256 hash for bootx64.efi / bootmgfw.efi / bootmgr.efi in SKUSiPolicy.xml

pineapple63 commented 1 year ago

Been using a 1511 ISO, and haven’t had any luck so far

(And i did verify my Surface Go 3 rejects that ISO when extracted to a USB drive (i copied the files across manually, rather than using Rufus), and in the process of verifying that i screwed up, i wanted to make sure it booted with secure boot turned off, and the device froze when i did that, after force powering it off, and re-enabling secure boot, i was met with a bitlocker recovery screen)

pbatard commented 1 year ago

Goddammit! Why do I always pick the ISOs that Microsoft forgot to add to their deny list?

Can confirm that en_windows_10_multiple_editions_version_1607_updated_jan_2017_x64_dvd_9714399.iso contains bootx64.efi / bootmgr.efi that are in the SkuSiPolicy list. But en_windows_10_multiple_editions_version_1511_x64_dvd_7223712.iso or en_windows_10_multiple_editions_version_1511_updated_feb_2016_x64_dvd_8379634.iso don't.

The thing is, since I wasn't sure whether Microsoft's list was inclusive or not, I deliberately picked 1511 as the "safer" bet, since it's right between 1507 and 1607. And I tested multiple 1511 ISOs I had.

So, once again, it looks like Microsoft screwed up their Black Lotus filtering, even though, in the case of SkuSiPolicy, they don't have to worry about limiting the bootloaders they pick so as not to run out of space.

I sure am starting to grow tired of having to tell Microsoft how to do their job. But at any rate, many thanks to @stdin82 for finding at least one ISO that Microsoft did properly filter out...

pbatard commented 1 year ago

EDIT: The following is not accurate per the comments further down

Well, Since it's been my lucky category so far, I'll take "Things that Microsoft said they would do but certainly did not do" for 500, Alex...Copying SKUSiPolicy.p7b to a bootable media created from Windows 10 20H2 does NOT produce any error when trying to boot on a fully updated UEFI system, in accordance with Microsoft's guidance, when Secure Boot is enabled.What is "• Boot Managers from Windows 10, version 1703 to today: revoked by version number by SKU SiPolicy"?

Gotta hand it to Microsoft they managed to turn every single line from:

• Boot Managers from Windows 8 to Windows 10, version 1507: revoked by DBX entries • Boot Managers from Windows 10, version 1507 to Windows 10, version 1607: revoked by hash by SKU SiPolicy • Boot Managers from Windows 10, version 1703 to today: revoked by version number by SKU SiPolicy

into a straight out lie.

And yeah, after spending some time trying to look for something that even remotely looks like a version number validation rule in the .p7b, I can safely conclude that, no, Microsoft did not revoke any Boot Managers from Windows 10, version 1703 to today by version number by SKU SiPolicy...

You'd think that, as the sole judge, jury and executioner of Secure Boot signing, Microsoft would know how not to completely botch the handling of a Secure Boot vulnerability...

pbatard commented 1 year ago

In the absence of any hints of how Microsoft plans to perform version number revocation, I have now added the closest thing I can provide to the feature being requested in this issue, which is a warning to the user if the source media they use happens to use either a DBX revoked bootloader or an SkuSiPolicy one.

In the first case, you will see the following alter:

Revoked_1

And in the second case, this slightly different one (and yeah, I do realise Hyper-V or Surface will not actually show the Recovery BSOD, but I am targeting the most common usage here).

Revoked_2

Both these warnings intervene after the user presses START (since we don't want to pester the user as soon as they select the ISO).

This adds an awful loads of hashes to check (which isn't really an issue in terms of performance, it's just that it does increase the size of the executable by about 100 KB) but I think the end result justifies the means.

Note that this feature may evolve on account of the complete shit show that Microsoft has left us with when it comes to Black Lotus detection and remediation, and that since Rufus is not yet copying the system's SkuSiPolicy.p7b onto the target media, you will not actually get the Recovery screen when trying to boot it. I am planning to add copying of SkuSiPolicy.p7b in a subsequent patch.

Still, if you want to test, and find if your pre 1607 media is currently going to get flagged for Black Lotus, feel free to test the binaries aritfacts from https://github.com/pbatard/rufus/actions/runs/5293179952.

pbatard commented 1 year ago

I have now updated the code to read the revoked PE256 directly from the system's SkuSiPolicy.p7b rather than embedding these values in Rufus.

I didn't go for this solution initially, first, because parsing WDAC Code Integrity p7b's is a pain in the ass (yeah, it looks easy when it's done, but, even if you have a PowerShell example script to follow, making it work with Windows' wincrypt API is a always a long trial and error ordeal) and second because the drawback of doing it that way is that people creating the media on non up to date Windows systems aren't going to be warned about the revocation, whereas this is probably the folks that may need the warning the most. But then again, if folks are choosing not to keep their systems up to date, they are taking a risk anyway...

And we are now also adding SkuSiPolicy.p7b to the target media, so drives created with Rufus should produce the 0xc0000428 error code if Rufus did produce a warning.

You can find the latest builds here if you wanna play.

When launching Rufus, you should now see the following lines in the Rufus log, with the last one indicating that it successfully parsed the .p7b:

Found 517 officially revoked UEFI bootloaders from embedded list
Found 2351 additional revoked UEFI bootloaders from this system's SKUSiPolicy.p7b
Wack0 commented 1 year ago

By the way, about skusipolicy:

Yes it contains a bunch of hashes, but it also does contain a flat deny entry by filename (this is OriginalFileName in version resources) for bootmgr.efi, the idea is bootmgr does check its own signature and any version that can process this entry will cause the sigcheck to fail.

And the latest bootmgrs which have the additional BOOTMGRSECURITYVERSION resource can boot in any case, so don't bother checking skusipolicy hashes, rather check for the presence or absence of the additional BOOTMGRSECURITYVERSION resource (for now, the actual content doesn't matter, this may change in the future)

pbatard commented 1 year ago

@Wack0, please see SKUSiPolicy.zip from 8 posts above, which should contain ALL the rules from SKUSiPolicy.zip in XML. You will see that it does not yet actually contain a rule to revoke bootloaders by version.

I am well aware that " bootmgr does check its own signature and any version that can process this entry will cause the sigcheck to fail", because that's the 3rd item from the following section found in https://uefi.org/sites/default/files/resources/dbx_release_info.pdf:

• Boot Managers from Windows 8 to Windows 10, version 1507: revoked by DBX entries • Boot Managers from Windows 10, version 1507 to Windows 10, version 1607: revoked by hash by SKU SiPolicy • Boot Managers from Windows 10, version 1703 to today: revoked by version number by SKU SiPolicy

which is how Microsoft details the steps they will use to mitigate bootloader revocation. However, per the official description above, the SECURITYVERSION based revocation will only be applied to post 1703 bootloaders, most likely because older bootloaders did not have the recovation by version feature, and therefore you very much still need to check for hashes for post 1507 to pre 1703 bootloaders, and these hashes are provided by SkuSiPolicy.p7b.

Please understand that Rufus is not "guessing" how it should detect revocations here, but we are following Microsoft's official guidance on how bootloaders will be revoked.

Plus, even as messy as their current handling of Black Lotus mitigation is, it would make no sense for Microsoft to add thousands of revoked hashes to SkuSiPolicy.p7b if the same bootloaders could be revoked by version.

Oh, and while we're on the subject, I was half hoping that Microsoft would be updating SkuSiPolicy.p7b with the July 11 Patch Tuesday, as they have the following for the timing of their mitigation:

May 9, 2023 – Initial Deployment Phase July 11, 2023 – Second Deployment Phase First quarter of 2024 – Enforcement Phase

but the July 11 update did not alter SkuSiPolicy.p7b in any way, meaning that, as I pointed out above, it still lets bootloaders through that it shouldn't and, more relevant to your comment, it still does not in fact contain any rule that revokes bootloaders by version. The only thing the July 11 update added (as far as I can see) is a new dbxupdate.bin in C:\Windows\System32\SecureBootUpdates, which is in line with Microsoft's "Allow easier, automated deployment of the revocation files (Code Integrity Boot policy and Secure Boot disallow list (DBX))" comment in the "Timing of updates" section (though how exactly this dbxupdate.bin is meant to be used is still a mystery.

Wack0 commented 1 year ago

You will see that it does not yet actually contain a rule to revoke bootloaders by version.

Yes, it does:

<DeniedSigner SignerId="ID_SIGNER_S_0002" />

<Signer Name="Signer 2" ID="ID_SIGNER_S_0002">
      <CertRoot Type="Wellknown" Value="06" />
      <CertEKU ID="ID_EKU_E_0001" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_0A51" />
    </Signer>

<FileAttrib ID="ID_FILEATTRIB_F_0A51" FileName="bootmgr.exe" MinimumFileVersion="65535.65535.65535.65535" />

as documentation mentions https://learn.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/select-types-of-rules-to-create :

"MinimumFileVersion specified without MaximumFileVersion: [...] For Deny rules, file with version less than or equal to the specified version are blocked."

...therefore this rule does block EVERY bootmgr (and later versions of bootmgr just don't use this rule)

Regarding it only working from RS2+, that's due to a bug in bootmgr from th1 until then. When getting the version resources from the PE (for checking against CiPolicy), it's expected that the PE is already mapped into memory (rather than a flat image), which is true when actually loading a boot application, but not when sigchecking PE loaded from disk, so some wild values get calculated, function returns an error due to bounds check, and the on-disk filename is used (which will never be equal to bootmgr.exe, so the rule won't apply).

pineapple63 commented 1 year ago

Just now I tried setting up a Windows 10 1803 "Windows to Go" VM (using the Beta version of Rufus, so i could see what happened), and it seems Microsoft may not have forgotten to revoke by version number, as i got a secure boot violation message in hyper V

Screenshot 2023-07-12 202725

Here is the rufus log, incase you are intrested Windows 10 1803.log

I do not get that violation message when booting the ISO in hyper V (i have not tried using that ISO to install Windows 10 1803 on a VM)

pbatard commented 1 year ago

@Wack0,

You are correct. I could have sworn I tested with a post 1703 ISO where I also copied SkuSiPolicy.p7b and got the bootloader let through, but I have now re-tested with Win10_20H2_v2_EnglishInternational_x64.iso and got the 0xc0000428 error.

The thing that also threw me off is that I could not see how the 65535.65535.65535.65535 could let through newer bootloaders, especially as the bootmgr.efi/bootx64.efi do have some nice incremental versions that would have been easy to filter out through non-blanket min/max.

Do you have some clarification on how "later versions of bootmgr just don't use this rule" and how this is tied in with the rule, because I've been having a hard time interpreting how this actually works.

Right now, I'm guessing the ID="ID_SIGNER_S_0002" and ID="ID_FILEATTRIB_F_0A51" are just internal cross references so they don't matter, therefore the filtering is enacted by either Name="Signer 2" or, most likely, the file being signed with a certificate that matches the Type="Wellknown" Value="06" attribute, whatever those mean.

In short, I'm trying to understand how exactly you can tie that BOOTMGRSECURITYVERSION resource you speak of with ignoring that blanket max version filtering rule, that, by all means, unless <CertRoot Type="Wellknown" Value="06" /> or the <CertEKU ID="ID_EKU_E_0001" /> do apply some filtering (how?), should logically be expected to apply to all bootloaders (because, as obtuse as that SkuSiPolicy revocation seems to be, I don't see Microsoft switching newer bootloaders to simply ignore SkuSiPolicy, when it appears to have been designed to be able to be fine-tuneable enough not to warrant ditching this rules-based approach).

Wack0 commented 1 year ago

All bootmgr binaries starting from May update has BOOTMGRSECURITYVERSION resource which is used as revocation check when loading bootmgr from a boot application (that resource MUST exist and be >= a hardcoded value when loading bootmgr otherwise error). bootmgfw does also have some additional check right after bootlib init that checks a constant (hardcoded but equal to BOOTMGRSECURITYVERSION) against an EFI variable and panics if the EFI variable is greater.

I'm not sure exactly what it does to ignore the fileattrib rule in skusipolicy, the CiPolicy loading code is a mess. That newer bootmgr does run (passing the sigcheck on itself) with the skusipolicy present is enough to show empirically that at least that rule is ignored.

pbatard commented 1 year ago

what it does to ignore the fileattrib rule in skusipolicy, the CiPolicy loading code is a mess.

Yeah, even Microsoft's own WDAC Wizard doesn't seem to offer much insight about that rule when loading the XML, which is something I had looked into in the past. It's quite unfortunate that WDAC Wizard can be used to create a .p7b from a set of rules, but cannot do the reverse operation directly from a .p7b, because I'm not entirely sure that the XML I got from the .p7b (through a non Microsoft third party script) is complete.

I can also see the 32-bit BOOTMGRSECURITYVERSIONNUMBER resource from newer EFI's, and, similar to what you suggested, I had initially planned to apply a blanket "if lower than version x.y.z / older than 2023.05 then just consider the bootloader as revoked" except that these can only work as long as Microsoft don't screw up their revocation, which unfortunately they did when it comes to DBX and hash from SkuSiPolicy.p7b. So, if I was to just look for the BOOTMGRSECURITYVERSIONNUMBER to decide if a bootloader is revoked or not, I would for instance state that the bootloader used by en_windows_10_multiple_editions_version_1511_x64_dvd_7223712.iso has been revoked (which it really should have been), whereas, because its hash is missing from SkuSiPolicy.p7b and because this EFI bootloader is too old for the version rule to apply, it is very much being let through. Note that this can be easily be validated if you have the relevant ISO, and I have done so once again, as I did above, just to be safe, so I can assert very positively that the version rule does not apply to older Windows bootloaders, and that, the hash rule that should have applied to revoke them, is missing their hashes.

In other words, unfortunately, and currently, you can very much find Windows bootloaders that are not officially revoked and are being let through, even as they don't have the BOOTMGRSECURITYVERSIONNUMBER resource, on account that (in line with Microsoft's notes) pre 1607 bootloaders don't honour the version number revocation rule and are being dealt with by hash revocation only.

This means that, if we want to be accurate in alerting users about which bootloaders are revoked and which aren't, we do want to check SkuSiPolicy.p7b hashes, and if we want to be even more accurate, we need to figure out what governs the blanket version rule not being picked up from the .p7b by post 2023.05 bootloaders...

Now, since my initial assertion that Microsoft did not yet have a working version rule in place was actually something that I was relying on for Rufus to not start filtering out the Windows bootloaders from the past couple of years (or at least not do so until Microsoft start with their third "Enforcement" phase), and I am now realising that ISOs as young a Windows 11 22H2 v1 (from 2022.09 — v2 from 2023.05 is fine) will produce a 0xc0000428 security validation error, I think I am either going to fall back to not copying SkuSiPolicy.p7b for bootloaders that weren't detected as revoked by hash in the .p7b, or, alternatively, look at the build version from the efi bootloader (that as far as I can tell, should closely match the Windows build version) and only copy SkuSiPolicy.p7b if it's older than, say, 21H1. This way, folks using 21H2 to 22H2v1 aren't going to suddenly be unable to to install Windows media created by Rufus in Secure Boot environment... with the assumption, of course, that they are going to update their OS after install, so that their bootloaders are updated to non vulnerable versions and so that an SkuSiPolicy.p7b also gets installed. And of course, once Microsoft does start enforcing revocations per phase 3, I will do the same in Rufus and copy SkuSiPolicy.p7b always.

But I sure wouldn't mind understanding how that version rule from the .p7b is being ignored by post 2023.05 bootloaders...

Wack0 commented 1 year ago

If you really want to be accurate then check against hash for bootmgr build number <= 14393 (rs1 rtm) and check for presence or absence of BOOTMGRSECURITYVERSIONNUMBER resource (added in 2023-05 bootmgr) otherwise.

Meanwhile, did a bindiff and found how that rule is being ignored. In fact the whole skusipolicy is being ignored.

After loading a CiPolicy, if the loaded cipolicy type is skusipolicy, it does check if the loaded secure boot policy's publisher guid is equal to 25b2429b-6e93-4dfb-9bdf-286243b21970 (this is true for the Surface Hub secure boot policy).

If so it returns STATUS_SYSTEM_INTEGRITY_INVALID_POLICY (and clears skusipolicy) if skusipolicy version is at least 2.0.0.0 (Surface Hub used skusipolicy with earlier version).

Otherwise, it returns STATUS_SYSTEM_INTEGRITY_INVALID_POLICY (and clears skusipolicy) if skusipolicy version is less than 2.0.0.0; if skusipolicy version is at least 2.0.0.0 and below 3.0.0.0, skusipolicy is cleared and success is returned.

So, in newer bootmgrs skusipolicy is just loaded to ensure its presence and then unloaded straight away.

Wack0 commented 1 year ago

I just noticed some additional code that was added in May 2023 update, like I said the CiPolicy loading code is a mess:

If a signed policy was required (ie, "uefi lock" variables were in place), for skusipolicy, if the variables expect an skusipolicy version of >= 2.0.0.0 and < 3.0.0.0, then the loading function returns success, even if skusipolicy is not present.

This allows bootmgrs from May 2023 update to work, even if the skusipolicy was already installed previously.

Hence MS guidelines suggesting "don't copy skusipolicy to install media" - if it was already taken, old bootmgr will panic (due to not being able to load it), and new bootmgr (from May 2023 update onwards) just doesn't care.

pbatard commented 1 year ago

Thanks for the additional information.

It looks like what you are describing is in part the same as what Microsoft is detailing in KB5027455 and it is now finally starting to make some sense to me.

For one thing, looking at the UEFI variables of a fully updated Windows system, it looks like the UEFI Lock is what Microsoft plans to activate during third phase (planned for Q1 2024) but it is not yet something that has been activated by the May or July updates, or even by creating the AvailableUpdates registry key from 3. APPLY the revocations steps from Microsoft, as I had originally assumed it would.

This can be validated by using Windows PowerShell and the UEFI commandlets from Michael Niehaus where you'll find that Get-UEFIVariable -VariableName SkuSiPolicyVersion -Namespace $UEFIWindows -AsByteArray or Get-UEFIVariable -VariableName SkuSiPolicyUpdateSigners -Namespace $UEFIWindows -AsByteArray returns nothing (NB, per the script, $UEFIWindows is {77FA9ABD-0359-4D32-BD60-28F4E78F784B} which is the same as SECUREBOOT_EFI_NAMESPACE_GUID from KB5027455).

And KB5027455, that does indeed describe that you need these 2 UEFI variables set for the UEFI Lock to apply, also states:

If the UEFI lock is in place and the (SkuSiPolicy) policy has been removed, the Windows boot manager will not start. If the policy is in place, the boot manager will not start if it has been blocked by the policy.

In other words (and of course that's the only way that it could ever work), Microsoft probably added provisions for anti-rollback based on UEFI variables starting with its 1507 bootloaders, so that, as you indicated above, once a PC has the lock in place, you can't simply bypass the SkuSiPolicy.p7b revocations by removing that file, because, once UEFI Lock is set, then, depending on the version from the variables, the absence of SkuSiPolicy.p7b can just make the bootloader bail out with an error.

Now, I have still to try enabling the UEFI Lock on my updated system (if you are feeling adventurous, you should be able to do so through an elevated PowerShell by using the commands at the end of this post, that are just a re-hash of what KB5027455 describes), on account that, even without the lock, I'm seeing some weird things with the Win11_22H2_EnglishInternational_x64v1.iso bootloaders (note that this is the 2022.09 vulnerable v1 and not the 2023.05 patched v2) that I want to investigate. Also, one probably wants to be mindful that the provider of the Get-UEFIVariable/Set-UEFIVariable commandlets does not appear to provide a way to delete these variables, so once you have created them, and if you want to go back to an non-UEFI-Locked system you're probably going to have to disable Secure Boot and then fire up a UEFI Shell to use dmpstore -d <variable> -guid <guid>.

PowerShell commands to set the UEFI Lock variables per KB5027455

# If not yet installed
Install-Module UEFI

# Set the SkuSiPolicyVersion UEFI variable
[byte[]] $SkuSiPolicyVersion = 0x2, 0x0 ,0x0 ,0x0 ,0x0, 0x0, 0x2, 0x0
Set-UEFIVariable -VariableName SkuSiPolicyVersion -Namespace $UEFIWindows -ByteArray $SkuSiPolicyVersion

# Validate that the SkuSiPolicyVersion variable has been set
Get-UEFIVariable -VariableName SkuSiPolicyVersion -Namespace $UEFIWindows -AsByteArray

# Set the SkuSiPolicyUpdateSigners UEFI variable
[byte[]] $SkuSiPolicyUpdateSigners = `
  0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, `
  0x0b, 0x00, 0x00, 0x00, 0xd0, 0x91, 0x73, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x54, 0xa6, 0x78, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x5c, 0xa6, 0x78, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x64, 0xa6, 0x78, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, `
  0x00, 0x00, 0x00, 0x00, 0x0a, 0x2b, 0x06, 0x01, `
  0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x06, 0x00, `
  0x00, 0x00, 0x00
Set-UEFIVariable -VariableName SkuSiPolicyUpdateSigners -Namespace $UEFIWindows -ByteArray $SkuSiPolicyUpdateSigners

# Validate that the SkuSiPolicyUpdateSigners variable has been set
Get-UEFIVariable -VariableName SkuSiPolicyUpdateSigners -Namespace $UEFIWindows -AsByteArray
Wack0 commented 1 year ago

bootmgr itself does apply the variables, when it loads skusipolicy.

The variables are boot services only; so they can only be read/written inside UEFI boot services, that is, they are invisible to the running OS (and bootmgr checks the attributes exactly, if you set them from a running OS then they will be considered not present by bootmgr).

pbatard commented 1 year ago

Ah, that makes more sense, and probably explains what I saw with my 22H2 v1 image.

Indeed, from a UEFI Shell, dmpstore -guid 77FA9ABD-0359-4D32-BD60-28F4E78F784B returns:

(...)
Variable NV+BS '77FA9ABD-0359-4D32-BD60-28F4E78F784B:SkuSiPolicyUpdateSigners' DataSize = 0x83
  00000000: 01 00 00 00 06 00 00 00-00 00 00 00 00 00 00 00  *................*
  00000010: 00 00 00 00 00 00 00 00-00 00 00 00 01 00 00 00  *................*
  00000020: 0B 00 00 00 80 12 1C 54-06 F8 FF FF 00 00 02 00  *.......T........*
  00000030: 00 00 00 00 BC A7 25 54-06 F8 FF FF 00 00 02 00  *......%T........*
  00000040: 00 00 00 00 C4 A7 25 54-06 F8 FF FF 00 00 02 00  *......%T........*
  00000050: 00 00 00 00 CC A7 25 54-06 F8 FF FF 00 00 00 00  *......%T........*
  00000060: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  *................*
  00000070: 00 00 00 00 0A 2B 06 01-04 01 82 37 0A 03 06 00  *.....+.....7....*
  00000080: 00 00 00                                         *...*
Variable NV+BS '77FA9ABD-0359-4D32-BD60-28F4E78F784B:SkuSiPolicyVersion' DataSize = 0x08
  00000000: 02 00 00 00 00 00 02 00-                         *........*
(...)

So the variables are set.

But now I don't get why, if I don't have SkuSiPolicy.p7b on a Win10_20H2_v2_EnglishInternational_x64.iso media, it appears to boot just fine on my system...

Wack0 commented 1 year ago

But now I don't get why, if I don't have SkuSiPolicy.p7b on a Win10_20H2_v2_EnglishInternational_x64.iso media, it appears to boot just fine on my system...

because MS made an error when implementing support for loading multiple CiPolicy files in v1903 (this was fixed only in Iron) - basically, they initially forgot to specifically check the lock variables for all legacy CiPolicy files (skusipolicy included) and only check the lock variables if the files actually exist (which removes the entire point of these variables in the first place).

Affected bootmgrs are 18362-19041, I created a new MSRC case to make them aware about the issue.

pbatard commented 1 year ago

Thanks again for the clarification. I still need to digest all this, along with the multiple "misses" that Microsoft have imparted upon us, to decide what I want to do in Rufus...

Looks like I have a knack for picking Windows ISOs, as my first choice, that should work a specific documented way for revocation, yet don't, which doesn't help when trying to make sense of this whole mess...

At any rate, I greatly appreciate your input on the matter!

Wack0 commented 1 year ago

By the way, just for clarification on the earlier symbol server discussion:

It indeed was possible to download boot applications from the symbol server in the same way. A few days after the blacklotus blog post from eset, MS removed at least bootmgr,bootmgfw,hvloader (binaries and symbols). Some time after that (not sure exactly when) symbols were readded but binaries are still gone.

GurliGebis commented 1 year ago

I don't know if this has already been mentioned, but by guess for the sha256 mismatch is, that it doesn't cover the signature part. (that would be a chicken and egg problem) So when you sha256 the entire file, you also sha256 the signature bytes. When using the applocker powershell command, it takes the checksum of the executable without the signature. I think the idea is to be able to sign the same file again with a new certificate, without the checksum changing.

pbatard commented 1 year ago

@Wack0, yeah, I gathered Microsoft took the heavy-handed approach of removing access to all of the bootloader binaries instead of removing access to just the ones that they know are being downloaded by the malware.

I have just released Rufus 4.2 today, and since theoretical vs practical revocation as enforced by Microsoft is a mess, I just kept the current 20H1 watershed in Rufus (where Rufus will only warn you and copy SkuSiPolicy if you use a pre 20H1 ISO), even as people who have pre-emptively enabled the UEFI Lock are going to get an error.

On that subject, it should be noted that the affected Windows's EFI bootloaders will return EFI errorcode 17 (EFI_NO_MAPPING) when the UEFI Lock is in place and they can't find SkuSiPolicy.p7b which has the "interesting" property of making the UEFI firmware attempt to boot the next bootable device... and leaving users in the dark that there was an explicit issue with bootmgr.

This is the reason why, for instance, if you have the UEFI Lock enabled and try to boot a Rufus created media with a recent Black Lotus vulnerable Windows ISO, you will end up with the following UEFI:NTFS screen (since UEFI:NTFS prefers to abort on error rather than attempt to pass the hot potatoe to whoever's next as if nothing happened):

UEFI:NTFS No mapping

It also seems like, independently of Black Lotus, EFI_NO_MAPPING is the generic error code Windows boot manager returns whenever it encounters something that prevents it from booting the Windows partition.

At any rate, since I expect a few Rufus users to run into errorcode 17 moving forward, I have created an explicit entry for it in the FAQ.

@GurliGebis, I am well aware of the reasons for excluding specific fields from the hash computation, but my point is, how hard would it have been to introduce a signed PE extension to the PE format, that simply embeds the original file wholesale and makes life easier for everybody (except perhaps of course OS developers). Add this with a new extension (like .sexe for "Signed exe", if you pardon my French 😄), and you would also have fostered the adoption of signed executable by users who would naturally gravitate towards the "more secure" signed executable extension than the regular "unsafe" .exe).

But, as usual, whoever designed the extension for signed PE's didn't stop to think whether the immediate patting on the back from managing to shoehorn the extensions into the original PE specs would be worth the long term drawbacks.

GurliGebis commented 1 year ago

@pbatard since Authenticode was announced back in 1996, I think it is safe to say that the approach to development has changed since then - back then signatures and cryptography was pretty new to most developers.

Wack0 commented 1 year ago

Microsoft updated their page about bootloader revocation a couple of weeks ago.

Another round of bootloader revocation will happen in January, with mandatory enforcement starting six months later.