I always asked myself how to password protect GRUB entries on an encrypted notebook to lock down the boot loader and protect it from unauthorized access.
Password protect everything
Use grub-mkpasswd-pbkdf2
command to generate the password hash.
$ grub-mkpasswd-pbkdf2 Enter password: ******** Reenter password: ******** PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.800E[..].79C[..]
Define GRUB user (milosz
in the following example) using generated hash and declare it as a superuser inside /etc/grub.d/40_custom
configuration file.
#!/bin/sh exec tail -n +3 $0 # This file provides an easy way to add custom menu entries. Simply type the # menu entries you want to add after this comment. Be careful not to change # the 'exec tail' line above. # define superusers set superusers="milosz" #define users password_pbkdf2 milosz grub.pbkdf2.sha512.10000.800EF[..].7977C[..]
Install the modified configuration and test it afterward.
$ sudo grup-update
Password protect everything except specific menu entries
Define users and superusers inside /etc/grub.d/40_custom
configuration file.
#!/bin/sh exec tail -n +3 $0 # This file provides an easy way to add custom menu entries. Simply type the # menu entries you want to add after this comment. Be careful not to change # the 'exec tail' line above. # define superusers set superusers="r00t" #define users password_pbkdf2 r00t grub.pbkdf2.sha512.10000.800EF[..].7977C[..] password_pbkdf2 t00r grub.pbkdf2.sha512.10000.3A16C[..].34DF0[..] password_pbkdf2 t01r grub.pbkdf2.sha512.10000.5D042[..].A7B33[..]
At this moment, GRUB installation will enforce r00t
username and password for every action like boot, edit, and command-line.
GRUB configuration is generated automatically. The easiest way to alter it is to edit /etc/grub.d/30_os-prober
or /etc/grub.d/10_linux
file.
Look for menuentry
definition for the wanted class like gnu-linux
, osx
, windows
or hurd
.
Then modify that line to allow unrestricted access or selected users.
I will play with Debian GNU/Linux menu entry inside /etc/grub.d/10_linux
file.
else echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" fi if [ "$quick_boot" = 1 ]; then echo " recordfail" | sed "s/^/$submenu_indentation/" fi
To allow unrestricted boot access for Debian GNU/Linux add an --unrestricted
parameter.
else echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' --unrestricted {" | sed "s/^/$submenu_indentation/" fi if [ "$quick_boot" = 1 ]; then echo " recordfail" | sed "s/^/$submenu_indentation/" fi
To allow superusers and t00r
users to boot Debian GNU/Linux, add --users t00r
parameter. In this case, access for t01r
user will be denied.
else echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' --users t00r {" | sed "s/^/$submenu_indentation/" fi if [ "$quick_boot" = 1 ]; then echo " recordfail" | sed "s/^/$submenu_indentation/" fi
To allow superusers and t00r
, t01r
users to boot Debian GNU/Linux add an --users t00r,t01r
parameter.
else echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' --users t00r,t01r {" | sed "s/^/$submenu_indentation/" fi if [ "$quick_boot" = 1 ]; then echo " recordfail" | sed "s/^/$submenu_indentation/" fi
To allow unrestricted boot access for MS Windows found on /dev/sda1
device add an --unrestricted
parameter using an if
statement inside /etc/grub.d/30_os-prober
file.
found_other_os=1 onstr="$(gettext_printf "(on %s)" "${DEVICE}")" cat <<EOF menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' { EOF save_default_entry | grub_add_tab prepare_grub_to_access_device ${DEVICE} | grub_add_tab
found_other_os=1 onstr="$(gettext_printf "(on %s)" "${DEVICE}")" if [ ${DEVICE} = "/dev/sda1" ]; then cat << EOF menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' --unrestricted { EOF else cat << EOF menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' { EOF fi save_default_entry | grub_add_tab prepare_grub_to_access_device ${DEVICE} | grub_add_tab
Generate and install the modified configuration.
$ sudo grup-update
Use this method to change default settings for other classes and menus.
grub-mkpasswd.sh shell script
Command grub-mkpasswd-pbkdf2
works only in interactive mode, so use expect
utility to automate it a bit.
#!/bin/sh # generate hash password given as an parameter # example: grub-mkpasswd.sh "my password" expect=$(which expect); mkpasswd=$(which grub-mkpasswd-pbkdf2) expect_script(){ cat << EOF log_user 0 spawn ${mkpasswd} sleep 0.33 expect "Enter password: " { send "$1" send "\n" } sleep 0.33 expect "Reenter password: " { send "$1" send "\n" } sleep 0.33 expect eof { puts "\$expect_out(buffer)" } exit 0 EOF } if [ -n "$1" ]; then expect_script "$1" | $expect | sed -e "/^\r$/d" -e "/^$/d" -e "s/.* \(.*\)/\1/" fi
Ending notes
For further information, read the GNU GRUB manual and inspect the mentioned shell scripts.