sudoers: Configurando la seguridad de sudo en GNU/Linux

Publicado por Diego Córdoba en

sudo es una excelente herramienta para administrar los privilegios de los usuarios creados en un sistema operativo GNU/Linux. Aquí aprenderemos a configurar un sudoers funcional.

Motivaciones: su, sudo y sudoers

En sistemas GNU/Linux históricamente se tuvieron dos tipos de usuario: el usuario común, y el superusuario, denominado root. El usuario común no puede realizar tareas administrativas (crear otros usuarios, instalar y desinstalar paquetes, administrar configuraciones globales, etc.), mientras que el usuario root tiene acceso a todo el sistema (o casi todo, para ser estrictos.

Ahora bien, para un usuario de escritorio, que necesita actualizar el sistema, siempre tenía la posibilidad de usar el comando su para acceder a la cuenta de root.

No obstante imaginemos la situación en la que entra otro administrador a nuestra computadora y necesita realizar algunas tareas privilegiadas… ¿vamos a darle nuestra contraseña de súper usuario? Definitivamente no.

Para esto es que existen herramientas como sudo, que permiten a un administrador darle la posibilidad a otros usuarios de acceder a ciertas tareas administrativas (o a todas, si se quiere) utilizando su propia contraseña de usuario común.

Veamos algunas formas de configurarlo en GNU/Linux.

Editando sudoers

Primero y principal hay que saber que el archivo de configuración de sudo en general es /etc/sudoers. Este archivo puede ser configurado por el superusuario del sistema, el usuario que instaló el GNU/Linux y que está habilitado por defecto en sudo (a los fines prácticos, ese usuario debemos ser nosotros :P).

La configuración puede editarse directamente mediante cualquier editor de textos llamado con sudo, o utilizando el comando visudo, que en general lanza el editor por defecto de nuestra terminal (por default si no me equivoco es vi, pero puede cambiarse… yo configuré vim).

Por defecto se utiliza vi. Una forma simple es cambiando el valor de la variable de entorno EDITOR, otra que me ha funcionado muy bien es editar por primera vez el sudoers con el editor por defecto, y agregar la siguiente línea de configuración por default. Luego guardar, cerrar y volver a ejecutar sudo visudo:

Defaults editor=/usr/bin/vim

Otra configuración posible y bastante utilizada es la que habilita la variable env_editor para que el visudo cargue el editor configurado en la variable SUDO_EDITOR. Si no hay ningún editor configurado utilizará los especificados en editor.

Para tener en cuenta los usuarios de Arch Linux: Arch gestiona de forma ligeramente diferente las variables de entorno respecto de la mayoría de las distros, por lo que si visudo no carga el editor que hemos configurado deberemos verificar si no existe ninguna variable o configuración que esté forzando un editor diferente.

Entre estos archivos con definiciones de variables se pueden encontrar

  • Configuraciones globales:
    • /etc/profile
    • /etc/locale.conf
    • /etc/profile
    • /etc/security/pam_env.conf
  • Configuraciones locales de usuario:
    • ~/.pam_environment
    • ~/.bashrc y configuraciones de la shell particular
    • ~/.config/environment.d/*.conf (systemd configura algunas variables de entorno en estos archivos)
  • Variables de entorno gráfico:
    • ~/.xinitrc
    • ~/.config/environment.d/envvars.conf

Para los lectores Archeros les recomiendo pasarse por este artículo en el que se detalla muy bien el tema de variables de entorno en esta gran distro.

Configurando sudoers

La configuración básica y la que casi todos hacemos la primera vez que instalamos un sistema y agregamos un nuevo usuario, es editar el /etc/sudoers, buscar esta línea:

##
## User privilege specification
##
root ALL=(ALL) ALL

Y agregamos una línea como esta:

diego ALL=(ALL) ALL

De esa forma ahora podremos usar el comando sudo para acceder a todas las funcionalidades del sistema desde el usuario diego.

Una cuestión no muy recomendable, pero que yo uso mucho en mi sistema de escritorio (aclaro, tengo acceso únicamente yo) es desactivar la solicitud de password para mi usuario, así no es necesario typear la contraseña de usuario reiteradamente. Para ello puede modificarse la línea anterior por esto:

diego ALL=(ALL) NOPASSWD:ALL

OJO: si es un sistema empresarial, servidor, o estación de trabajo, no recomiendo esta setting, ya que cualquiera que pase por nuestro escritorio podría tener acceso a todo el operativo.

Configuraciones: sintaxis de sudoers

Si bien lo anterior es útil, sudo permite muchísimas cosas más. A continuación veremos algunas interesantes que pueden resultar útiles.

Cada línea de especificación de usuario permite configurar los comandos que puede ejecutar un usuario particular, o un grupo de usuarios, o varios usuarios o grupos etiquetados bajo un mismo alias, alias que también deben definirse en el sudoers.

La especificación de sintaxis de una línea tiene este formato:

Nombre Equipo = (Correr_como) Comando

Cuando invocamos al comando sudo se verificarán todas las líneas del sudoers para otorgarnos los privilegios.

Esta línea se lee como El usuario Nombre puede ejecutar el comando Comando con los privilegios de. usuario Correr_como en el ordenador Equipo.

Usuarios y grupos

El Nombre hace referencia al nombre de usuario en el sistema, o también a un grupo si le anteponemos el símbolo porcentual. Es decir, podemos otorgar ciertos privilegios al usuario diego, o al grupo %administradores, por ejemplo.

El campo Equipo puede ser un nombre de host, una dirección IP, una red entera como 192.168.0.0/24, pero no puede ser la dirección IP de loopback (127.0.0.1).

El campo Correr_como también puede ser un username o un grupo con el prefijo %, y ambos pueden ser también UIDs o GIDs, por lo que en cualquiera de estas dos ubicaciones podríamos poner al usuario diego, o 1001, o al grupo %admin, o al grupo %104, según sean los nombres e ID’s que correspondan.

Cuando un usuario ejecuta un comando invocando a sudo, el comando se ejecutará como root. No obstante, el comando sudo permite especificar un usuario o grupo diferente de root para ejecutar un comando. Es decir, uno podría ejecutar sudo -u juan comando o sudo -g administradores comando para invocar al comando con los privilegios del usuario juan o el grupo administradores respectivamente.

Para que un usuario pueda ejecutar sudo utilizando las opciones -u o -g, es necesario que en el archivo sudoers le habilitemos los usuarios y grupos que puede invocar.

Esto puede hacerse mediante el argumento opcional Correr_como.

  • Si no se especifica ningún valor en el campo, el usuario únicamente podrá ejecutar el comando como usuario root, no se aceptará ni -u ni -g.
  • Si se especifica un nombre de usuario, por ejemplo, juan, únicamente se podrá usar la opción -u juan en la terminal. No se permitirá la opción -g ya que no se ha configurado ningún grupo válido.
  • Si se configura únicamente un valor para grupo, como :administradores, quien invoque el comando sudo podrá especificar -g y el nombre del grupo válido, pero lo hará con sus privilegios de usuario.
  • Si se especifican ambos, por ejemplo, juan:administradores, quien invoque a sudo podrá utilizar cualquier combinación de -u y -g utilizando los usuarios y grupos enumerados.

En general este campo puede encontrarse como (ALL:ALL), que indica que quien invoque a sudo podrá especificar -u y -g con cualquier combinación de todos los usuarios y grupos del sistema.

Comandos

Es conveniente especificar la ruta completa a los comandos que vamos a permitirle ejecutar al usuario. Se pueden especificar una lista de argumentos luego de cada comando, por ejemplo, /bin/df -h para permitirle al usuario la ejecución de los comandos únicamente con dichos argumentos. Igualmente, si en vez de argumentos se coloca un juego de comillas dobles, "", se impedirá al usuario usar cualquier tipo de argumento en el comando, por ejemplo, /bin/df "".

Además pueden especificarse varios comandos separados por coma.

Un comando interesante es sudoedit. En la línea de comandos puede especificarse, por ejemplo, sudoedit /etc/hosts. Esto le permitirá al usuario ejecutar, invocando con sudo, un editor de textos para editar el archivo /etc/hosts. Es necesario en este caso ya que, si el usuario ejecuta un editor con sudo para editar un archivo privilegiado, el editor va a correr con privilegios elevados, pero no va a poder modificar el archivo puesto que el usuario no tendrá privilegios sobre el mismo.

En otras palabras, si no especificamos sudoedit /etc/hosts y el usuario ejecuta «sudo vim /etc/hosts» ejecutará vim como superusuario, pero el acceso al archivo seguirá siendo restringido, y no se heredará, por lo que no podrá guardar los cambios.

Opciones

Antes de los comandos se pueden especificar algunas opciones de control a tener en cuenta durante la ejecución. Entre estas opciones se encuentran dos importantes:

  • NOPASSWD: permite que al usuario que invoca sudo no se le solicite la contraseña.
  • SETENV: permite al usuario que ejecuta sudo cargar variables de entorno personalizadas para la ejecución de su comando.

Existen otras opciones que pueden usarse, los invito a leer man 5 sudoers.

Alias

Los alias le dan a sudoers una flexibilidad enorme a la hora de configurar los privilegios. Hasta ahora hemos visto cómo especificar usuarios, grupos, equipos y comandos. Todos estos elementos pueden almacenarse en alias para poder utilizarlos.

La sintaxis de especificación de un alias es:

Tipo_alias NOMBRE = valor, valor : NOMBRE_2 = valor, valor, ...

Tipos de alias pueden ser:

  • User_Alias: para usuarios y grupos (anteponiendo %).
  • Runas_Alias: para usuarios y grupos en Correr_como.
  • Cmnd_Alias: para comandos.
  • Host_Alias: para nombres o direcciones IP de los equipos.

Nada mejor que algunos ejemplos para entenderlo.

Imaginemos que a los usuarios juan y pedro, y al grupo adm queremos darles privilegios de root para ejecutar los comandos /bin/insmod y /bin/modprobe, podríamos cargar un alias para esos usuarios, llamémosle «ADMINES«, y uno para los comandos, «CARGAMODULOS«.

User_Alias ADMINES = juan, pedro, %adm
Cmnd_Alias CARGAMODULOS = /usr/insmod, /bin/modprobe

Luego podremos colocar una línea de regla similar a esta:

ADMINES ALL = (ALL:ALL) CARGAMODULOS

A su vez, un alias puede incluir otros alias definidos previamente, por lo que podríamos definir un subconjunto de administradores que serán cargados como administradores generales, y a los que luego podríamos darle permisos para ejecutar otros comandos:

User_Alias DBADMIN = jose, raul
User_Alias ADMINES = juan, pedro, %adm, DBADMIN

Otro punto importante es la posibilidad de exclusión de elementos de las listas de aliases. Esto se realiza anteponiendo el símbolo "!" en el nombre del usuario, grupo, comando, etc. Supongamos que en el grupo ADMINES queremos incluir a los DBADMIN, pero no al usuario raul. Podríamos plantearlo de esta forma:

User_Alias DBADMIN = jose, raul
User_Alias ADMINES = juan, pedro, %adm, DBADMIN, !raul

Hay que aclarar que, si bien es un recurso interesante, en el man 5 sudoers advierte que sustraer elementos de una lista compuesta por ALL no es efectivo generalmente.

La misma negación puede ser utilizada para equipos también, restando hosts particulares desde una dirección de red, por ejemplo.

Defaults

El archivo sudoers mantiene un número de valores y opciones predeterminadas que pueden ser configuradas y sobreescritas para todos los usuarios, o para usuarios o grupos particulares, o incluso para comandos o equipos.

Estas opciones por defecto son críticas para el funcionamiento de sudoers, por lo que, salvo que se necesite para alguna configuración especial, no es conveniente modificarlas.

Las opciones predeterminadas comienzan con la palabra reservada Defaults. Veamos algunos ejemplos:

Defaults passwd_tries=5, insults
Defaults passprompt="Contrasenia para %p:"

Estas líneas especifican un máximo de 5 reintentos en la colocación de la contraseña por parte del usuario (por defecto son 3), activa los insultos (sí, los insultos por defecto están desactivados… activando esto se logra que sudo insulte al usuario que se equivoca en la password :D), y cambia el mensaje de solicitud de la contraseña.

Algunas consideraciones

Hemos visto que para poder cargar múltiples usuarios, o hosts, o comandos, en una misma regla, se pueden usar los alias. Ahora bien, podríamos omitir los alias y listar, separando por comas, cada uno de los elementos. Por ejemplo, al especificar un usuario podríamos colocar juan, luis, o en los hosts usar equipo1, 192.168.3.134.

Con este tipo de sintaxis pueden generarse confusiones y complicaciones si las listas son más grandes, por lo que mi recomendación, si es necesario especificar más de un usuario, host, comando, etc, siempre tender a los alias para facilitar la organización.

Otra cuestión MUY IMPORTANTE. Arriba mencioné que es recomendable usar el comando visudo para editar el archivo. Muchos me dirán «¿para qué usar visudo? y complicarme cambiando el editor si puedo hacer sudo vim /etc/sudoers o el editor que quiera?«

La respuesta es que si guardamos el archivo sudoers y quedó con errores de sintaxis, no podremos volver a editarlo usando «sudo mi_editor«, a tener en cuenta!

Más de una vez, por precaución, dejé una terminal de root (sudo su) abierta por las dudas, por si me equivocaba… o simplemente guardaba los cambios en el sudoers sin cerrar el editor. Una forma muchísimo más elegante es usar visudo, ya que al guardar el archivo e «intentar salir» visudo realiza una comprobación de syntaxis, y si hay errores lo notifica y nos permite volver a editar.

sudo sudoers su visudo

Directorio sudoers.d

Finalmente, si somos muy puntillosos, o estamos trabajando en sistemas grandes y tener muchas configuraciones en el archivo /etc/sudoers resulta difícil de administrar, sudo también lee configuración de archivos que se encuentren dentro de /etc/sudoers.d/, por lo que podríamos crear archivos con configuraciones específicas según el ambiente, y cargarlas en ese directorio.

Los archivos que carguemos en ese directorio se leerán en orden alfabético según su nombre, esto es importante tenerlo en cuenta si hay reglas que se pisan.

Por supuesto, el contenido de este directorio es leído porque en el archivo /etc/sudoers se encuentra, en general, esta línea:

## Read drop-in files from /etc/sudoers.d
## (the '#' here does not indicate a comment)
#includedir /etc/sudoers.d

Si esa línea no existe, podemos agregarla y crear el directorio /etc/sudoers.d con permisos 0440 para root:root.

Nótese que he usado #includedir. No es un comentario en este caso. Las versiones modernas de sudo utilizan la directiva @includedir, pero se mantiene la versión #includedir por compatibilidad, por lo que cualquiera debería funcionar bien.


Bueno, esto ha sido todo por hoy. Espero les guste y sirva! Cualquier sugerencia ya saben dónde encontrarme.

Hasta la próxima!

Fuentes:


¿Preguntas? ¿Comentarios?

Si tenés dudas, o querés dejarnos tus comentarios y consultas, sumate al grupo de Telegram de la comunidad JuncoTIC!
¡Te esperamos!

Categorías: InfoSecLinux

Diego Córdoba

- Ingeniero en Informática - Mg. Teleinformática - Tesis pendiente - Docente universitario - Investigador