Saltar la navegación

Contraseña para grub2

En seguridad, lo primero que debemos hacer para proteger un sistema informático es impedir su acceso físico a las personas que no tienen permiso para ello. Los servidores deberían estar en una sala monitorizada con acceso mediante tarjeta o sistemas biométricos. A partir de esta seguridad física, podemos construir la seguridad lógica, donde un papel fundamental lo tendrá la política de contraseñas. Es muy habitual, que los usuarios elijan contraseñas débiles para recordarlas fácilmente, por lo que podríamos poner una serie de exigencias en relación a la construcción de claves, como por ejemplo:

  • Longitud mínima.
  • Caducidad de contraseñas.
  • La renovación de la contraseña no puede coincidir con contraseñas anteriores.
  • Que las contraseñas obligatoriamente contengan caracteres minúsculas, mayúsculas, dígitos y otros símbolos.
  • Combinar las contraseñas con tarjetas de seguridad, así exigimos que el usuario sepa algo (contraseña) y que tenga algo (tarjeta).
  • Auditar todos los accesos de los usuarios y sus cambios de contraseñas.

Las dos primeras contraseñas que deberíamos configurar para proteger el acceso a los servidores son las de la BIOS, pues sin ellas un atacante que hubiera conseguido el acceso físico al sistema podría hacer bastante daño, ya que entre otras cosas, podría arrancar el sistema operativo desde un Live-CD o similar, y manipular el sistema instalado en el disco duro del servidor.

Las contraseñas fundamentales de la BIOS son dos, la del usuario, que permite el arranque del sistema, y la del supervisor, que permite entrar en la propia BIOS. Existen BIOS que protegen con contraseña la posibilidad de arrancar de un dispositivo o de otro.

Contraseñas de la BIOS

También se puede establecer un control de acceso a través de la contraseña del cargador de arranque, por ejemplo, el GRUB, que es uno de los más utilizados.

GRUB 2

La imagen muestra el menú del GRUB versión 2. La versión del grub se muestra en la parte superior de la imagen, concretamente es la 2.06-13+deb12u1, donde la parte fundamental de la versión es el 2.06, es decir, versión 2, el resto nos indica que es el grub de la distribución Debian. Puede consultarse también la versión desde la terminal usando el siguiente comando:

# grub-install --version
grub-install (GRUB) 2.06-13+deb12u1

El GRUB puede proteger individualmente con contraseña cada una de las entradas del menú, y también todas las entradas de una vez.

El primer paso a llevar a cabo es la creación de los usuarios del GRUB y sus contraseñas. Estos usuarios no tienen que coincidir con los usuarios del sistema operativo, son usuarios del GRUB.

Debe existir al menos un usuario, el superusuario. Definido este, al seleccionarse cualquier entrada del menú, se pedirá su login y contraseña. Además, las opciones de edición (e) y de línea de comando (c), solo estarán permitidas al superusuario del grub.

Las parejas usuario/contraseña se crean en el fichero /etc/grub.d/00_header escribiendo líneas con el siguiente formato:

password <usuario> <contraseña>

y el superusuario se identifica con una línea como la siguiente:

set superusers="<usuario>"

la cual también permite una lista de superusuarios separados por comas:

set superusers="<usuario>,<usuario>,......"

Por ejemplo, si queremos proteger todo el menú del GRUB del servidor, para que solo el administrador pueda arrancar el sistema, crearíamos únicamente un usuario que sería el superusuario. Elegimos root como login, pass como clave, y al final del fichero /etc/grub.d/00_header añadimos las siguientes líneas:

cat << EOF
set superusers="root"
password root pass
EOF

Lo último que falta, es instalar estas modificaciones, para que en el siguiente reinicio del sistema surtan efecto. Para ello ejecutaremos:

# update-grub2

Si quisiéramos permitir el acceso a más de un usuario, cada uno con su login y contraseña, tan solo tendremos que añadir más líneas password. Estos nuevos usuarios pueden definirse como superusuarios, o bien, como usuarios que solo pueden elegir determinadas opciones del menú que tendremos que especificar. Las entradas e (edición) y c (línea de comando), son exclusivas del o de los superusuarios.

Ejemplo:

cat << EOF
set superusers="root,juan"
password root pass
password juan abcdef
password pepe 1a2b
EOF

Vemos que las contraseñas van en claro, y eso no es lo ideal, pues un atacante podría llegar a ver el contenido del fichero /etc/grub.d/00_header, por lo que sería mejor guardarlas cifradas, y para conseguirlo, lo que debemos hacer es ejecutar el comando grub-mkpasswd-pbkdf2, que nos devuelve una cadena hash generada a partir de una contraseña que introduciremos:

# grub-mkpasswd-pbkdf2 
Introduzca la contraseña:
Reintroduzca la contraseña:
El hash PBKDF2 de su contraseña es grub.pbkdf2.sha512.10000.2F865AB7ECA17DE9B5ED03893984555473A5AFA992007E36B7590F118747FBDC6E9973AB433BA1EAB081ECCD599B94DE9C0C4A9AEB84BC5548460ED1E65DE888.C29B276EE24DDC62F9F4D86C6DDE7E1D36FA564F1DDF5BFDE2CAEB2AA9ED571CE4C67D0731373F0947E3042744E8FF70615D94C08D8078AF0B6F25D23AC644FE

A continuación, debemos sustituir las líneas password en /etc/grub.d/00_header por líneas password_pbkdf2:

password_pbkdf2 <usuario> <contraseña-cifrada-pbkdf2>

Por lo tanto, el mismo ejemplo anterior, con la misma contraseña pero cifrada, quedaría así:

cat << EOF
set superusers="root"
password_pbkdf2 root grub.pbkdf2.sha512.10000.2F865AB7ECA17DE9B5ED03893984555473A5AFA992007E36B7590F118747FBDC6E9973AB433BA1EAB081ECCD599B94DE9C0C4A9AEB84BC5548460ED1E65DE888.C29B276EE24DDC62F9F4D86C6DDE7E1D36FA564F1DDF5BFDE2CAEB2AA9ED571CE4C67D0731373F0947E3042744E8FF70615D94C08D8078AF0B6F25D23AC644FE
password_pbkdf2 juan grub.pbkdf2.sha512.10000.90ECD01F1499F8B172079E9368085138AB69C0B9D696D346F41A44C3A0540C1B75458B0F7D6B4736EB7409D0316BE166BFC507B7F750FED8558340BEDBA7FD0D.5FF4ACFED451F1DE3077F89AE2162BB31EB106D2D503FBAECFD0AC088072359900A5918DC5C118458610403A4E910B11DC35620BCDB731D239A5725150F644A7
password_pbkdf2 pepe grub.pbkdf2.sha512.10000.7616EB04B653C6B61C78B7BE0F52FADFDC5FDD334F82CEEB990D20CB4EDF24ABDE4394BDA11330D3BAA1B191F93D78749CE978BD519F5546611504EBA1552840.4FD4117A2ECDFA8EF24D7DE8CD54381317D9173B74F364458ABFF6F4716E29A32D21D17EFAC914EA732528FD57E8F670A3855EC0D83920420FBB7F47AB2BC7EA
EOF

Tener varios usuarios es interesante, pues si por ejemplo, juan dejara de tener acceso al sistema, tan solo habría que quitar su línea. Lo cual sería mejor que tener un solo usuario, con lo que se estaría obligado a que todos supieran la única contraseña, y para el caso de juan, habría que cambiar la contraseña e informar a todos del cambio.

También puede interesar tener varios usuarios para permitirle a unos seleccionar unas opciones del menú y a otros otras, e incluso se puede tener alguna opción sin protección, para que la puedan seleccionar todos los usuarios.

Con el ejemplo anterior, lo que se pretende es que los usuarios root y juan tengan acceso a todo el grub, pero a pepe se le va a permitir una o varias entradas solamente. Veamos qué más hay que hacer para conseguir esto último.

Las opciones del menú del GRUB se definen con secciones menuentry en el fichero /boot/grub/grub.cfg:

menuentry 'Texto de la opción' ... {
valores
}

a las que podemos añadirle determinadas opciones para indicar quién puede usarlas.

Para añadir protección a una opción de menú, tendremos que escribir en su línea menuentry alguno de los siguientes valores:

  • Para que una opción no tenga protección y pueda ser elegida por todos:
menuentry --unrestricted ...
  • Para que solo pueda elegirla un usuario (el superusuario siempre podrá elegir cualquier opción):
menuentry --users <usuario> ...
  • Para que puedan seleccionarla varios usuarios:
menuentry --users <usuario>,<usuario>,... ...

Las secciones menuentry están, como se mencionó anteriormente, en el fichero de configuración /boot/grub/grub.cfg, y también, en los scripts /etc/grub.d/10_linux y /etc/grub.d/30_os-probe que se utilizan para generar grub.cfg.

El menú actual del grub siempre se encuentra en grub.cfg, y podríamos modificarlo directamente, pero es mejor modificar los script, pues al usar update-grub2, solo se traslada a grub.cfg lo que se encuentre en los scripts, y cualquier cosa que se haya escrito directamente sobre grub.cfg se perderá. Nosotros decidimos dónde hacer las modificaciones, de todas formas, el grub no suele modificarse muchas veces en un equipo.

Si decidimos modificar /boot/grub/grub.cfg, tan solo hay que localizar la sección menuentry que nos interese y añadirle alguno de los valores que se explicaron anteriormente. No hay que ejecutar el comando update-grub2, simplemente reiniciando el equipo, las modificaciones tendrán efecto.

Por ejemplo, vamos a permitir que el usuario del grub "pepe" pueda elegir la opción de título "Debian GNU/Linux". La sección en Debian tendría un aspecto como este:

menuentry 'Debian GNU/Linux' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-77e0926d-cd32-4437-ae69-85d156ec26da' {
load_video
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_msdos
insmod ext2
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 77e0926d-cd32-4437-ae69-85d156ec26da
else
search --no-floppy --fs-uuid --set=root 77e0926d-cd32-4437-ae69-85d156ec26da
fi
echo 'Loading Linux 6.1.0-13-amd64 ...'
linux /boot/vmlinuz-6.1.0-13-amd64 root=UUID=77e0926d-cd32-4437-ae69-85d156ec26da ro quiet
echo 'Loading initial ramdisk ...'
initrd /boot/initrd.img-6.1.0-13-amd64
}

Modificando la sección menuentry quedaría así:

menuentry --users pepe 'Debian GNU/Linux' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-77e0926d-cd32-4437-ae69-85d156ec26da' {
load_video
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_msdos
insmod ext2
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 77e0926d-cd32-4437-ae69-85d156ec26da
else
search --no-floppy --fs-uuid --set=root 77e0926d-cd32-4437-ae69-85d156ec26da
fi
echo 'Loading Linux 6.1.0-13-amd64 ...'
linux /boot/vmlinuz-6.1.0-13-amd64 root=UUID=77e0926d-cd32-4437-ae69-85d156ec26da ro quiet
echo 'Loading initial ramdisk ...'
initrd /boot/initrd.img-6.1.0-13-amd64
}

Ahora solo queda guardar los cambios y reiniciar el equipo.

La otra opción es modificar los scripts /etc/grub.d/10_linux y/o /etc/grub.d/30_os-probe.

En el fichero /etc/grub.d/10_linux se encuentran las entradas del sistema operativo principal que ha instalado el grub, que es Debian para los ejemplos. Las líneas menuentry que hay que localizar son las siguientes:

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

Estas líneas hacen referencia a la opción de título "Debian GNU/Linux". Si queremos que sea seleccionada por el usuario del grub "pepe", pasaríamos a tener lo siguiente:

...
echo "menuentry --users pepe '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
else
echo "menuentry --users pepe '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
...

La opción titulada "Advanced options for Debian GNU/Linux" es un submenú con varias opciones de arranque de Debian con diferentes versiones del kernel. La línea que controla este submenú es la siguiente:

  echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"

Para hacer, como en el caso anterior, que el usuario pepe sea el que pueda acceder a esta opción del menú, pasaríamos a lo siguiente:

  echo "submenu --users pepe '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"

En el fichero /etc/grub.d/30_os-probe se encuentran las entradas del resto de sistemas operativos que tengamos instalados, distintos al principal. Las líneas menuentry que hay que modificar en el mismo sentido que las anteriores, tienen distinto formato en función del tipo de sistema operativo. Así para sistemas operativos del tipo GNU/Linux llevan la opción --class gnu-linux:

menuentry ... --class gnu-linux ...

Para sistemas operativos Windows:

menuentry ... --class windows ...

Para sistemas operativos Mac OS X:

menuentry ... --class osx ...

Hechas las modificaciones en los scripts, el siguiente paso es generar el fichero grub.cfg y actualizar el grub con la siguiente orden que ya se ha usado:

# update-grub2