Remediating Nessus Plugin ID 139239 "Windows Security Feature Bypass in Secure Boot (BootHole)"
There are a series of vulnerabilities that are detected on a Windows host by Nessus Plugin ID 139239 identified as BootHole. This post discusses that vulnerability and how to effectively remediate it against Windows hosts. Some guidance suggests installing Windows Update KB4535680: Security update for Secure Boot DBX, but that update is only available for Windows 10 up to version 1909.
If you, like many I would hope, run a currently supported version of Windows 10 there is no (that I could find at least) Windows Update that will apply the required security updates to take care of this BootHole vulnerability. Below we will be taking a look at what options are available to install the required patches into the systems firmware to take care of this vulnerability.
Remediating via DBX Updates
This vulnerability is remediated by installing some DBX updates into the UEFI firmware of the affected system, so that Secure Boot knows what boot loaders it should or should not allow to be installed.
UEFI has published a series of updates to the DBX database that deny a Secure Boot system from installing any of the vulnerable GRUB bootloaders. The hashes of these bootloaders are added a revocation list that Secure Boot checks to make sure the bootloader is not revoked. Once these DBX Updates are installed into the firmware of a system the vulnerable GRUB bootloaders can no longer be installed, thus remediating this vulnerability.
Windows Update (Win10 versions 20H1+)
If you happen to be running any of the below versions of Windows, then you can install KB4535680 which allegedly updates the Secure Boot with these new DBX updates.
KB4535680 Applies To:
- Windows Server 2012 x64-bit
- Windows Server 2012 R2 x64-bit
- Windows 8.1 x64-bit
- Windows Server 2016 x64-bit
- Windows Server 2019 x64-bit
- Windows 10, version 1607 x64-bit
- Windows 10, version 1803 x64-bit
- Windows 10, version 1809 x64-bit
- Windows 10, version 1909 x64-bit
These were taken directly from Windows Update KB4535680: Security update for Secure Boot DBX
Installing the above KB should remediate the vulnerability as found by Nessus. I have not been able to use this KB, however, since I only have newer versions of Windows 10 that were being identified by Nessus as vulnerable to BootHole. I am also not sure if this KB includes the absolute latest updates from the UEFI Forum.
Manual Windows DBX Updates
Microsoft published an article titled Microsoft guidance for applying Secure Boot DBX update that provides the manual steps required to install the DBX updates. The steps are summarized below.
Obtain the DBX Updates
Download the relevant (x64, x86, ARM) updates directly from Unified Extensible Firmware Interface Forum. You will also need the older updates, which can be found in the linked archive containing Prior Versions of DBX files as these updates are not cumulative. You will be downloading a single .bin
binary file for each round of updates.
Split the DBX files
To apply the updates we need to split the .bin
files that were downloaded into two parts, a .p7
signature file and another .bin
binary file. This can be done via PowerShell.
You will need to download the SplitDbxContent.ps1
script which was authored by Microsoft. You can get it from the PowerShell Gallery. Follow the instructions on the Gallery to obtain that file.
Once you have the SplitDbxContent.ps1
script, run the following PowerShell to create the signature and contents files.
1.\SplitDbxContent.ps1 <path to downloaded dbxupdate.bin>
You must run this from powershell.exe
built into Windows, if you try to run this from pwsh.exe
for PowerShell version 7 this script will fail due to changes in the commands in later versions of PowerShell.
You should receive feedback showing that two new files were created, a signature.p7
and a content.bin
If you have multiple dbxupdates that will need to be done, save them each into a folder named after their update date, and run the SplitDbxContent.ps1
from that folder. Otherwise the above script will overwrite the signature and content files each time you re-run it.
Install DBX Update via PowerShell
Now that you have one or more pairs of signature and content files, you can use PowerShell to install the updates.
The DBX updates provided by UEFI Forum are not cumulative. This means that you must install each update individually in order to be fully protected from BootHole.
Launch an Administrative PowerShell and enter the following to apply the updates.
1Set-SecureBootUefi -Name dbx -ContentFilePath "content.bin" -SignedFilePath "signature.p7" -Time "2010-03-06T19:17:21Z" -AppendWrite
Make sure you use the -Time "2010-03-06T19:17:21Z"
as-is! Do not change this value otherwise it will not apply. Use this same timestamp for each and every update file.
You should receive output showing the bytes as written.
Microsoft advises to restart the PC before confirming the update applied, however in my experience you can check for the existance of these updates immediately after applying them. Though they may require a restart to actually take affect.
Confirm Updates Applied
You can confirm the updates were properly applied by using these PowerShell scripts. Download both the Check-Dbx.ps1
and Get-UEFIDatabaseSignatures.ps1
scripts. Run them against your content.bin
files that were installed to confirm they exist in the UEFI firmware. Repeat for each update file that was applied.
1Get-UEFIDatabaseSignatures.ps1 "content.bin"
You should get feedback that the update was applied.
All-in-One PowerShell Update Script
I had a need to remediate BootHole on dozens of PC's, both local and remote, and since these are running a current version of Windows 10 the KB update was not an option. I followed Microsoft's guidance and created a PowerShell script that will apply the applicable updates to a PC remotely, and without interaction.
There are some other PowerShell scripts available on GitHub that perform this task, but one of my requirements was that the script be completely self-contained. On the systems I was pushing this update script to I didn't have a reliable way to grab the dbx update files from a file share. As such, I split them ahead of time and converted them into base64 to embed them directly into the script. The script then saves these files to disk temporarily right before applying them, then deletes them afterwards.
If you wish to use this script in a similar fashion, with the update files embedded within, grab the latest and the archived update files and follow the instructions above to split the .bin
into the signature.p7
and content.bin
files. You can then follow the instructions below to Base64 encode these files and paste them into the script.
Fix-BootHole.ps1 script on GitHub
Update Script Variables
If you don't want to embed the update files directly into the script, you can optionally load them from a file share. To do so, follow the instructions previously in this article to download the dbx updates and split the .bin
files into their respective signature.p7
and content.bin
files.
Store these files on a file share accessible to the system you will be running this script on. Next, edit the script on line 19 to set $EmbeddedFiles
to $false
and update the file paths on lines 24 through 59 to the signature and content files.
If you intend to embed the files, there is no need to modify the $EmbeddedFiles
or $DbxUpdateFiles
variables.
Converting DBX Updates to Base64 Encoded Strings
If you want to embed the files into the script so that it is a self-contained script, follow the steps previously in this article to download the dbx updates and to split the .bin
files into their respective signature.p7
and content.bin
files.
With your individual signature and content files, you need to convert them into Base64 and then copy/paste the Base64 data into the appropriate variables in the script.
Run the following PowerShell code against each of the signature.p7
and content.bin
files to generate a rather large string of Base64 encoded text. Piping these to clip
will copy the contents directly into your clipboard so that you can paste them.
1[System.Convert]::ToBase64String((Get-Content -Path ".\signature.p7" -Encoding byte)) | clip
2[System.Convert]::ToBase64String((Get-Content -Path ".\content.p7" -Encoding byte)) | clip
Paste each of the signature and content Base64 code into their respective variables in the script. These are under the $DbxUpdateFiles
variable. You only need to add in the architectures that you plan to deploy to, you can leave the others empty if you won't need them.
Running the Script
You can run Fix-BootHole.ps1
after either setting the file share locations, or pasting in the embedded base64 versions of the files.
1.\Fix-BootHole.ps1
Fix-BootHole.ps1 Script
For the latest script, please see the GitHub
1<#
2.SYNOPSIS
3Applies UEFI dbx updates to fix BootHole vulnerability.
4
5.DESCRIPTION
6Applies the UEFI dbxupdates to fix the BootHole vulnerability. Prior to running,
7edit this script to choose between Embedded files or link to a file share.
8See https://www.rufflabs.com/post/nessus-plugin-139239-remediating-boothole-windows/
9
10.EXAMPLE
11Run the script after making required modifications as mentioned in the descriptions.
12PS C:\>.\Fix-BootHole.ps1
13
14#>
15
16# Set this to false if you want to load the .p7 and .bin files from a file share
17# instead of having them embedded within this script as base64 encoded data.
18#$EmbeddedFiles = $False
19$EmbeddedFiles = $True
20
21# If using a file share instead of embedding files, update these file paths to point
22# to the .p7 and .bin files for each respective update. You can only specify those that
23# will be used (such as, if not using arm, ignore the arm ones.)
24$DbxUpdatePaths = @{
25 "x64" = @{
26 "April 2021" = @{
27 "signature" = "\\sampleserver\sampleshare\dbxupdates\april2021_x64\signature.p7"
28 "content" = "\\sampleserver\sampleshare\dbxupdates\april2021_x64\content.bin"
29 }
30 "October 2020" = @{
31 "signature" = "\\sampleserver\sampleshare\dbxupdates\october2020_x64\signature.p7"
32 "content" = "\\sampleserver\sampleshare\dbxupdates\october2020_x64\content.bin"
33 }
34 "July 2020" = @{
35 "signature" = "\\sampleserver\sampleshare\dbxupdates\july2020_x64\signature.p7"
36 "content" = "\\sampleserver\sampleshare\dbxupdates\july2020_x64\content.bin"
37 }
38 }
39 "x86" = @{
40 "April 2021" = @{
41 "signature" = "\\sampleserver\sampleshare\dbxupdates\april2021_x86\signature.p7"
42 "content" = "\\sampleserver\sampleshare\dbxupdates\april2021_x86\content.bin"
43 }
44 "July 2020" = @{
45 "signature" = "\\sampleserver\sampleshare\dbxupdates\july2020_x86\signature.p7"
46 "content" = "\\sampleserver\sampleshare\dbxupdates\july2020_x86\content.bin"
47 }
48 }
49 "arm" = @{
50 "April 2021" = @{
51 "signature" = "\\sampleserver\sampleshare\dbxupdates\april2021_arm64\signature.p7"
52 "content" = "\\sampleserver\sampleshare\dbxupdates\april2021_arm64\content.bin"
53 }
54 "July 2020" = @{
55 "signature" = "\\sampleserver\sampleshare\dbxupdates\july2020_arm64\signature.p7"
56 "content" = "\\sampleserver\sampleshare\dbxupdates\july2020_arm64\content.bin"
57 }
58 }
59}
60
61# Paste in Base64 encoded files below, both signature.p7 and content.bin
62# for each update and architecture as needed. Any left blank will not be applied.
63$DbxUpdateFiles = @{
64 "x64" = @{
65 "April 2021" = @{
66 "signature" = ""
67 "content" = ""
68 }
69 "October 2020" = @{
70 "signature" = ""
71 "content" = ""
72 }
73 "July 2020" = @{
74 "signature" = ""
75 "content" = ""
76 }
77 }
78 "x86" = @{
79 "April 2021" = @{
80 "signature" = ""
81 "content" = ""
82 }
83 "July 2020" = @{
84 "signature" = ""
85 "content" = ""
86 }
87 }
88 "arm" = @{
89 "April 2021" = @{
90 "signature" = ""
91 "content" = ""
92 }
93 "July 2020" = @{
94 "signature" = ""
95 "content" = ""
96 }
97 }
98}
99
100# CA Check adapted from https://github.com/synackcyber/BootHole_Fix/blob/main/boothole.ps1
101Write-Output "Checking for matching UEFI CA"
102$CAMatch = [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match 'Microsoft Corporation UEFI CA 2011'
103if(-not $CAMatch){
104 Write-Output "Microsoft Corporation UEFI CA 2011 was not found. Updates are not required on this system."
105 exit
106}
107Write-Output "Certificate found, continuing."
108
109# Check architecture
110$ArchitectureOptions = @{
111 0 = "x86"
112 1 = "MIPS"
113 2 = "Alpha"
114 3 = "PowerPC"
115 5 = "ARM"
116 6 = "IA64"
117 9 = "x64"
118}
119
120$Architecture = $ArchitectureOptions[[int](Get-WmiObject -Class Win32_Processor).Architecture]
121$SupportedArchitectures = @("x86", "x64", "arm")
122
123if($SupportedArchitectures -notcontains $Architecture) {
124 Write-Output "This script does not support $($Architecture) based PC's, and no dbx updates are available for this architecture."
125 exit
126}
127
128function Update-DbxVariable {
129 param(
130 $SignaturePath,
131 $ContentPath
132 )
133 Set-SecureBootUefi -Name dbx -SignedFilePath $SignaturePath -ContentFilePath $ContentPath -Time "2010-03-06T19:17:21Z" -AppendWrite
134}
135
136Write-Output "Updating UEFI dbx variable for $($Architecture) architecture."
137
138$UpdateFiles = @{}
139
140if($EmbeddedFiles) {
141 # Use the embedded files in this script
142
143 Write-Output "Using embedded update files, creating files on disk."
144 try {
145
146 $DbxUpdateFiles.$Architecture.GetEnumerator() | ForEach-Object {
147 $Release = $_.Name
148 $Content = $_.Value.Content
149 $Signature = $_.Value.Signature
150 $TempSigFile = "$($env:temp)\$($Release)_$($Architecture)_signature.p7"
151 $TempContentFile = "$($env:temp)\$($Release)_$($Architecture)_content.bin"
152
153 # Only copy data if signature and content are not null.
154 if($null -ne $Signature -and $null -ne $Content) {
155 $UpdateFiles.Add($Release, @{"Signature" = $TempSigFile; "Content" = $TempContentFile})
156
157 Set-Content -Path $TempSigFile -Value ([System.Convert]::FromBase64String($Signature)) -Encoding Byte -ErrorAction Stop
158 Write-Output "Created $($TempSigFile)"
159
160 Set-Content -Path $TempContentFile -Value ([System.Convert]::FromBase64String($Content)) -Encoding Byte -ErrorAction Stop
161 Write-Output "Created $($TempContentFile)"
162 }
163 }
164 } catch {
165 Write-Output "Error creating temporary files. Check permissions to $($env:temp)."
166 exit
167 }
168}else{
169 # Use the files from a file share location
170
171 Write-Output "Using update files from file share."
172
173 $DbxUpdatePaths.$Architecture.GetEnumerator() | ForEach-Object {
174 $Release = $_.Name
175 $ContentPath = $_.Value.Content
176 $SignaturePath = $_.Value.Signature
177
178 # Only add to the queue if both signature and content files are accessible
179 if((Test-Path -Path $ContentPath) -and (Test-Path -Path $SignaturePath)) {
180 Write-Output "`nPreparing: $($Release)`nSignature: $($SignaturePath)`nContent: $($ContentPath)"
181 $UpdateFiles.Add($Release, @{"Signature" = $SignaturePath; "Content" = $ContentPath})
182 }
183 }
184}
185
186$UpdateFiles.GetEnumerator() | ForEach-Object {
187 Write-Output "Applying $($_.Name) update..."
188 Update-DbxVariable -SignaturePath $_.Value.Signature -ContentPath $_.Value.Content
189}
190
191if($EmbeddedFiles) {
192 $UpdateFiles.Values.Values | ForEach-Object {
193 # Delete file from disk
194 Write-Output "Deleting on disk $($_)"
195 Remove-Item -Path $_ -ErrorAction SilentlyContinue
196 }
197}
References
- Windows Security Feature Bypass in Secure Boot (BootHole) | Tenable®
- ADV200011 - Security Update Guide - Microsoft - Microsoft Guidance for Addressing Security Feature Bypass in GRUB
- KB4535680: Security update for Secure Boot DBX: January 12, 2021
- Microsoft guidance for applying Secure Boot DBX update
- UEFI Revocation List File | Unified Extensible Firmware Interface Forum
- ARCHIVE - Prior Versions of DBX files | Unified Extensible Firmware Interface Forum