Authentication

By default, GRUB is set to root access so that anyone can select and edit any menu entry, and go into command shell mode. For most system, this is sensible since introducing another identity access management can be cumbersome. However, in embedded application

However, in some environments, such as kiosks, it may be appropriate to lock down the boot loader to require authentication before performing certain operations.

GRUB is at best only one link in a secure boot chain. Even with GRUB password protection, GRUB itself cannot prevent someone with physical access to the machine from altering that machine’s firmware (e.g., Coreboot or BIOS) configuration to cause the machine to boot from a different (attacker-controlled) device.

Authentication in GRUB

Before we start, we should understand some parts of authentication elements inside GRUB.

User with Passwords

The password and password_pbkdf2 commands can be used to define user with an associated password.

  • password sets the password in plain text, requiring grub.cfg to be secure
  • password_pbkdf2 sets the password hashed using the Password-Based Key Derivation Function (RFC 2898), requiring the use of grub-mkpasswd-pbkdf2 to generate password hashes.

superusers Environment Variable

the ‘superusers’ environment variable must be set to a list of usernames, separated by any of spaces, commas, semicolons, pipes, or ampersands. Superusers are permitted to use the GRUB command line, edit menu entries, and execute any menu entry. If ‘superusers’ is set, then use of the command line and editing of menu entries are automatically restricted to superusers. Setting ‘superusers’ to empty string effectively disables both access to CLI and editing of menu entries.

Securing GRUB with User Authentication

By default, anyone with or without authentication may be allowed to edit a custom menus or entering the console mode. Hence, you want to secure the access for GRUB entries.

Creating Password

To create password, do check out grub-mkpasswd-pbkdf2 command. Make sure you only get the password hashes (and not the statement). Here is an example:

u0:~$ grub-mkpasswd-pbkdf2 
Enter password: 
Reenter password: 
PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.D7FB4E3767555859B770C38332D61D4F8E72808909119F5B6DF22CDB75BE67D87676D27C5C15C2C08A1D8D9023D5334EB626DDF0A8BFBA59DC92B2DF68AA7ECD.E161052CFEEF808CE5722BF9859CECD1624247A3C2703B3FD98F8F9C80BE69EC1F0F60F060D6A0B507996C2021F19CE478DFF1C10961C8B7E57AA9FD8D9C94E4

Add 01_users Grub Configurations

Once you generated your password hashes, you need to add it into the Grub fragment generators (/etc/grub.d) for Grub to assemble the configuration file. Fortunately, these fragment generators has enough flexibility for you to stretch in and most importantly, it can be done using just the shell script. Therefore, create a /etc/grub.d/01_users and add the following contents:

#!/bin/sh
set -e

cat << EOF
set superusers="<USERNAME>"
password_pbkdf2 <USERNAME> <PASSWORD_HASHES>

One example would be:

#!/bin/sh
set -e

cat << EOF
set superusers="root"
password_pbkdf2 root grub.pbkdf2.sha512.10000.D7FB4E3767555859B770C38332D61D4F8E72808909119F5B6DF22CDB75BE67D87676D27C5C15C2C08A1D8D9023D5334EB626DDF0A8BFBA59DC92B2DF68AA7ECD.E161052CFEEF808CE5722BF9859CECD1624247A3C2703B3FD98F8F9C80BE69EC1F0F60F060D6A0B507996C2021F19CE478DFF1C10961C8B7E57AA9FD8D9C94E4

Remember to give it execute permission.

$ chmod +x /etc/grub.d/01_users

Adjust Menuentry

Once the username and its corresponding password is implemented, by default, all executing, editing, or drop to console for menu entries now requires an user authentication. Hence, you need to need to set --users option for specific users or --unrestricted option for anyone to execute without needing user authentication.

One output example is:

set superusers="root"
password_pbkdf2 root grub.pbkdf2.sha512.10000.biglongstring
password user1 insecure

menuentry "May be run by any user" --unrestricted {
  set root=(hd0,1)
  linux /vmlinuz
}

menuentry "Superusers only" --users root {
  set root=(hd0,1)
  linux /vmlinuz single
}

menuentry "May be run by user1 or a superuser" --users user1 {
  set root=(hd0,2)
  chainloader +1
}

To achieve that, you need to edit /etc/grub.d/10_linux and look for:

  • echo "menuentry '$(echo "$os" | grub_quote)'

You only append --unrestricted to it in order to generate menuentry for no-authentication execution (but not edit). One editing example is:

echo "menuentry '$(echo "$os" | grub_quote)' --unrestricted ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"

That's all about GRUB identity access management.