Skip to content


MSI's (in)Secure Boot

I guess I have found a reason to write my first blog post.

Before we start, maybe I will quickly explain what Secure Boot is. It is a security feature, which allows our computer to decline booting operating systems that have not been signed by a key that the firmware trusts.

On 2022-12-11, I decided to setup Secure Boot on my new desktop with a help of sbctl. Unfortunately I have found that my firmware was… accepting every OS image I gave it, no matter if it was trusted or not. It wasn't the first time that I have been self-signing Secure Boot, I wasn't doing it wrong.

As I have later discovered on 2022-12-16, it wasn't just broken firmware, MSI had changed their Secure Boot defaults to allow booting on security violations(!!).

This can be changed by going to the place where the settings are for Secure Boot on your motherboard. In my case it's in Security\Secure Boot. From this place, we can see a menu called "Image Execution Policy", which is the culprit.

Firmware Screenshot 0

When we enter the menu, we can see the disappointing default settings. It's doing no verification. It's useless. It's just there to satisfy Windows 11 requirements. OS has no idea that Secure Boot is doing nothing, it just knows that it's "enabled".

Firmware Screenshot 1

To change the settings to something saner, we have to change "Always Execute" to "Deny Execute" for "Removable Media" and "Fixed Media". What's funny is that "Allow Execute" and "Query User" options are breaking UEFI specification, though I'm not really sure what's the difference between "Allow Execute" and "Always Execute".

We can also change "Option ROM", about which you can read more about here:

Firmware Screenshot 2

Case closed, everyone can move on, right?

Well, not really. I needed to figure out if this is only affecting my motherboard or also other models and maybe even other vendors. And also we need to document this, because even if I know this, there is probably a lot of people that are not aware about this issue.

I had asked 2 users of B450 TOMAHAWK MAX (thanks Sage Hane and Daniel Nathan Gray) to check their firmware and what? Unsurprisingly, it's also there. We were able to determine that version 7C02v3C from 2022-01-18 introduced this issue.

EDIT: I have noticed that some websites have misreported about this issue because they have not fully read my article. This firmware version only affects B450 TOMAHAWK MAX, other motherboards have different versions. 7C02 in the version is the codename for B450 TOMAHAWK MAX. More information is available down below.

Is it mentioned in the changelog? Hah, nope.

Firmware Screenshot 3

I have also received information from a user of B550-A PRO (CEC) (thanks Joseph Richey) that they have this issue from 7C56vH1 (2021-12-20) onwards.

While I was able to extrapolate this information to guess which versions for other boards have introduced this issue, that isn't really enough. We need to go deeper.

I have tried extracting some information from MSI's binary firmware files, but to no avail. I tried using binwalk, UEFITool and others, but I didn't really find what I wanted. Until one day I have found out that UEFI has a thing called "UEFI Internal Form Representation" or in short "IFR". It's a way to describe firmware configuration options. This is exactly what I need to look for! Now, what do I do with this knowledge?

Once we extract files from the firmware using UEFIExtract from UEFITool project, we can find a file called Section_PE32_image_899407D7-99FE-43D8-9A21-79EC328CAC21_Setup_body.bin. It contains most of UEFI GUI stuff and seems to be available on all firmware from all major desktop motherboard makers, though ASUS decided to remove "Setup" from the name for some reason or maybe it has to do something to do with the UEFIExtract, not sure.

EDIT (thanks Nikolaj Schlej): "Setup" comes from User Interface section of that FFS file with GUID 899407D7-99FE-43D8-9A21-79EC328CAC21. Some vendors don't provide any UI sections, so "Setup" will be missing from the name, but most of them don't change the default GUID that AMI chose for their firmware."

Now once we have this file, we have to extract IFR data from it, to do it we can use IFRExtractor RS. Funnily enough, it's made by the same people as UEFITool. Thanks guys for your hard work, otherwise I would have to do it myself ;p.

Now with IFR extracted, we have what we wanted. We can see all the UEFI settings available, including "Image Execution Policy".

Form FormId: 0x2A79, Title: "Image Execution Policy"
	Text Prompt: "Internal FV", Help: "", Text: "Always Execute"
	OneOf Prompt: "Option ROM", Help: "Image Execution Policy on Security Violation per Device Path", QuestionFlags: 0x10, QuestionId: 0x1116, VarStoreId: 0x28, VarOffset: 0x4, Flags: 0x10, Size: 8, Min: 0x0, Max: 0x5, Step: 0x0
		Default DefaultId: 0x0 Value: 0
		OneOfOption Option: "Always Execute" Value: 0
		OneOfOption Option: "Always Deny" Value: 1
		OneOfOption Option: "Allow Execute" Value: 2
		OneOfOption Option: "Defer Execute" Value: 3
		OneOfOption Option: "Deny Execute" Value: 4
		OneOfOption Option: "Query User" Value: 5
	End
	OneOf Prompt: "Removable Media", Help: "Image Execution Policy on Security Violation per Device Path", QuestionFlags: 0x10, QuestionId: 0x1117, VarStoreId: 0x28, VarOffset: 0x5, Flags: 0x10, Size: 8, Min: 0x0, Max: 0x5, Step: 0x0
		Default DefaultId: 0x0 Value: 0
		OneOfOption Option: "Always Execute" Value: 0
		OneOfOption Option: "Always Deny" Value: 1
		OneOfOption Option: "Allow Execute" Value: 2
		OneOfOption Option: "Defer Execute" Value: 3
		OneOfOption Option: "Deny Execute" Value: 4
		OneOfOption Option: "Query User" Value: 5
	End
	OneOf Prompt: "Fixed Media", Help: "Image Execution Policy on Security Violation per Device Path", QuestionFlags: 0x10, QuestionId: 0x1118, VarStoreId: 0x28, VarOffset: 0x6, Flags: 0x10, Size: 8, Min: 0x0, Max: 0x5, Step: 0x0
		Default DefaultId: 0x0 Value: 0
		OneOfOption Option: "Always Execute" Value: 0
		OneOfOption Option: "Always Deny" Value: 1
		OneOfOption Option: "Allow Execute" Value: 2
		OneOfOption Option: "Defer Execute" Value: 3
		OneOfOption Option: "Deny Execute" Value: 4
		OneOfOption Option: "Query User" Value: 5
	End
End

I have checked if other vendors (ASRock, ASUS, Biostar, EVGA, Gigabyte and NZXT) have the same thing and I wasn't able to find anything like that in their IFR. Also MSI's laptops are not affected by this issue. I'm gonna assume that they figured that Microsoft wouldn't approve it and/or that they had less tickets from people about Secure Boot related issues for their laptops.

Now, doing this manually would be kinda annoying, so I made a small little shell script which checks if "Image Execution Policy" menu is available and if any of the three options are set to "Always Execute".

#!/bin/sh

if [ ! -d "$1" ]; then
	[ ! -f "$1.zip" ] && curl "https://download.msi.com/bos_exe/mb/$1.zip" -O -#
	bsdtar xf "$1.zip"
fi

cd "$1" || exit
UEFIExtract ./*MS.* unpack 1>/dev/null
ifrextractor ./*.dump/Section_PE32_image_899407D7-99FE-43D8-9A21-79EC328CAC21_Setup_body.bin 1>/dev/null
output="$(grep -A1 -E 'OneOf Prompt: "(Option ROM|Removable Media|Fixed Media)", Help: "Image Execution Policy' ./*.dump/Section_PE32_image_899407D7-99FE-43D8-9A21-79EC328CAC21_Setup_body.bin.*ifr.txt)"
clear

if echo "$output" | grep -q "DefaultId: 0x0"; then
	printf "\033[1;31m%s: Bad\033[0m\n" "$1"
else
	printf "\033[1;32m%s: Good\033[0m\n" "$1"
fi

Now this is where the fun part ends. Now I had to check firmware for MSI's somewhat recent boards.

While we can get most of the firmware just by going to motherboard's support page, MSI usually only lists stable firmware and the newest beta. The problem is that I need to figure out the earliest affected version of the firmware for each board, which means that I have to guess what the betas were called (if they even existed). At least MSI doesn't remove most of its beta firmware from their servers, so they are still accessible if you know the link.

For some AMD boards, I have found a list of beta firmware on some German forum. Thankfully, I didn't have to read any German, because contrary to the popular belief, I don't know German or Russian, I'm Polish.

This… took forever. I checked every motherboard for:

  • AMD: TRX40, X399, X670, X570, X470, X370, B650, B550, B450, B350, A520, A320
  • Intel: X299, Z790, Z690, Z590, Z490, Z390, Z370, B760, B660, B560, B460, B360, H670, H510, H410, H370, H310

It's… a lot of motherboards. For a full list of affected motherboards and their firmware versions, visit sbctl#181.

And now it's time for some "fun" statistic:

# The amount of times I ran the script
$ history 0 | grep "  msi " | wc -l
1989

According to Wikipedia in 1989:

The first commercial Internet service providers surfaced in this year, as well as the first written proposal for the World Wide Web and New Zealand, Japan and Australia's first Internet connections.

Well, that was a mistake.

You could ask me, why didn't I automate it? The reason is… well… some of it is not really easy to as some beta names have arbitrary suffixes which was faster for me to guess than having a script bruteforce its way in. Also some boards weren't listed on their motherboard list page.

Now, after doing all the work for MSI, I think I should bill them, that or they should give me a lifetime supply of their motherboards.

If you are curious, yes, I have tried contacting MSI about this issue, but they ignored my emails and other forms of communication I have tried.

EDIT: MSI have made a statement on the issue. What's weird is that it's only on their subreddit. And just like how I guessed it, it was an intentional change. Oh well.

Conclusion

Don't trust that whatever security features you enabled are working, TEST THEM! Somehow I was the first person to document this, even though it has been first introduced somewhere in 2021 Q3.

Quiz time!

What's the difference between these 3 boards:

Heatsink and PCB colours! They are the same board and share the same firmware! But hey, the red and white one is only for gamers but black is only suitable for "professionals".