|

Protecting GRUB on Ubuntu 22.04

GRUB2 password protection, secure Ubuntu boot loader, prevent unauthorised boot menu changes, enhance system security.

In previous posts in this blog I have explained how to protect the system by disk encryption with a password retrial from the TPM. In another post, I have given some wider overview of system security and protection, but there were a few topics not covered in details in these articles (only concepts) I feel that I need to go further into.

While looking for a way to protect Linux GRUB for Ubuntu, I found multiple articles, all without the answer I wanted. I will iterate: there are a few methods of protecting the boot loader:

  • Protect specific entries (you cannot use them unless you have the password)
  • Protect entry modifications (you can select a pre-existing entry, but you cannot modify its content, unless authenticated

In Ubuntu’s guides, the tendency is towards protecting all entries with a password, leaving the system is unable to boot into without the GRUB password.

As noted in my previous articles – I find typing password on every boot tiresome and limiting. I wanted something to be able to boot normally into the default entry, but, any modification of out-of-default selection would require a password.

I felt that password-protecting GRUB2 against an attempt to modify the boot menu was the best balance of security. When combined with encrypted disk and with BIOS password, this almost fully locks up a system against unauthorised access.

As a side note – I am not entirely happy with the process so far. It is missing some important chain-of-boot protection – the initial RAM disk should be signed and protected as well, but in the current tools available for us, I was still unable to do it correctly and without some major effort on every kernel update. So this is still open.

Back to the main dish – protecting GRUB against unauthorised change, while booting the defaults without prompting for password.

Initially, I followed Ubuntu GRUB2 password guide, which I found complex and inaccurate for the task described above. So I provide here a shorter and more to-the-point method, to allow for a quick and simple action.

Before everything

You need to run these tasks as root, so you can run ‘sudo bash’ beforehand to change your prompt to root.

Backing up your grub.cfg file, to a copy (you might have access to) in case we killed your grub conf, so run

cp /boot/grub/grub.cfg /boot/grub/grub.cfg.orig

Keep the disk and the BIOS passwords, in case of an emergency (such as booting into USB for recovery purposes).

Creating the Credentials

You will need to decide on the name of the GRUB2 admin user. Let’s call it ‘grubadmin’ in our example. It can be any name you desire (“root”, “grub”, “myself”, “admin”), but it is advisable to have a user you will remember (or document off-computer), while not having a too-easy-to-guess user.

Create the password by running the command:

grub-mkpasswd-pbkdf2

You will need to save everything starting at ‘grub.pbkdf2’ and until the end of the line. An example:

$ grub-mkpasswd-pbkdf2
Enter password: 
Reenter password: 
PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.13C23BB9579F19E265A20D29C628E0E1C0033152D3D9FA6F0A7F5EB00CB594CCA1CB7365F3797989664BC98F8C66F7DD3A163C5CCA0CB69F576E3415E4A97D79.C2B309B804EE42E510EB2793605FE5DBB7AC99CA70D97F2118F94508C2FDC655ED2AD81B8197478CFF1081C32980740A7F56CDBED0B4ED598A6748544C1F554B

The password is grub.pbkdf2.sha512.10000.13C23BB9579F19E265A20D29C628E0E1C0033152D3D9FA6F0A7F5EB00CB594CCA1CB7365F3797989664BC98F8C66F7DD3A163C5CCA0CB69F576E3415E4A97D79.C2B309B804EE42E510EB2793605FE5DBB7AC99CA70D97F2118F94508C2FDC655ED2AD81B8197478CFF1081C32980740A7F56CDBED0B4ED598A6748544C1F554B

Now, we need to create a file /etc/grub.d/00_credentials with the following contents:

cat << EOF
set superusers="grubadmin"
password_pbkdf2 grubadmin grub.pbkdf2.sha512.10000.13C23BB9579F19E265A20D29C628E0E1C0033152D3D9FA6F0A7F5EB00CB594CCA1CB7365F3797989664BC98F8C66F7DD3A163C5CCA0CB69F576E3415E4A97D79.C2B309B804EE42E510EB2793605FE5DBB7AC99CA70D97F2118F94508C2FDC655ED2AD81B8197478CFF1081C32980740A7F56CDBED0B4ED598A6748544C1F554B
EOF

Just to be clear – the file has 5 lines in total. The line starting with ‘password_pbkdf2 grubadmin’ continues with the hash provided by the previous command. If my blog formatting breaks this into two lines – do not break it yourself.

Give this file execution permissions, or else it will not work:

chmod +x /etc/grub.d/00_credentials

Enforcing password on every change

First – backup the file /etc/grub.d/10_linux to another directory – its backup should not reside in that directory, or else the entries might appear twice, with unknown result.

Then, edit the file. Find the line saying:

CLASS="--class gnu-linux --class gnu --class os"

and append to it (inside the quotes) ‘–unrestricted’. It should look like this:

CLASS="--class gnu-linux --class gnu --class os --unrestricted "

The result of this change is that existing entries will be handled without restriction, however – modifying an entry would require authentication.

Recreating GRUB configuration and testing

To finalise this task, we need to recreate GRUB configuration files, by running:

update-grub2

Following that, you can reboot and test. Note that unaltered boot should work successfully without any problem, however – an attempt to modify the entry (pressing Esc at the right time, and then trying to edit the entry) would require authentication.

Needless to say – keep the credentials safe outside the machine.

Recovery

If, for some reason, it doesn’t work as expected, the previous grub.cfg file still exists on your /boot. If you are unable to boot entirely, use a USB Linux (Ubuntu Live) to boot into the system, and copy the grub.cfg.orig to grub.cfg – overwriting the faulty file. It should allow you to boot back into your system and check the modifications, or revert them, if needed to.

Good luck, and drop a comment if things either work well or don’t.

Similar Posts

3 Comments

  1. Thank you, here is the automated version

    sed -i ‘s/CLASS=”–class gnu-linux –class gnu –class os”/CLASS=”–class gnu-linux –class gnu –class os –unrestricted “/’ /etc/grub.d/10_linux

    cat <> /etc/grub.d/40_custom
    set superusers=”admin”
    password_pbkdf2 admin grub.pbkdf2.sha512.10000.D609FD58A7856B6AE38691155E92658ED586B23A85AFEA4B6B0B462488770E1D70A0A6D7BEF174B9048A41DDAC55600AF8164F7AF680AA52F93244B31FB4FF73.27DBFC9E6EE9D19B75385B74F4C24A40AB9F4B61CC7538ECCE3CBC948D32978E6DD320A586F2A79A04780E5F46CFBC97014860807EF3DF1E9070417D9504C630
    EOF

    sed -i ‘s/^#GRUB_DISABLE_RECOVERY=”true”/GRUB_DISABLE_RECOVERY=”true”/’ /etc/default/grub

    password is admin

    1. Thank you. Just a word to the readers – due to how WP works – the special characters, like quotes and tags – are in Unicode, and will do wonders to your code. Make them into simple ASCII characters before actually running the code.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.