Keep Walking

El poder de sudo

Posted in Linux, open source, shell, Sistemas by Martín on diciembre 27, 2007

sudoSi bien usando el comando su podemos cambiar al modo root, esta es una práctica peligrosa. Sobre todo en ambientes multiusuario, porque implicaría entregar la contraseña del usuario root a todos los que la necesiten (y me cago en la seguridad).

Sudo se basa en una lista de control (que se encuentra en el archivo /etc/sudoers) para permitir (o no) la ejecución a un determinado usuario de un comando que es propiedad de otro usuario, generalmente del administrador del sistema (root).

Consideremos aquí las tres partes que componen esta suite de seguridad:

  • sudo: es el comando con permisos SUID que los usuarios utilizan para ejecutar otros comandos que, por seguridad o por otros motivos, no se les permite correr directamente. Sudo (SUperuser DO) lo ejecuta un usuario normal y requiere que éste último se autentique escribiendo su contraseña antes de la ejecución del comando al que se invoca. (Esto se puede cambiar en el archivo de configuración sudoers, como veremos más adelante). Por defecto, luego de dicha ejecución, el usuario dispondrá de cinco minutos de gracia para volver a correr el comando sin necesidad de autenticarse nuevamente. Dos opciones interesantes son sudo -l (lista qué comandos podemos ejecutar con sudo) y sudo -e (nos permite editar archivos de texto que sólo tienen permisos para el root).
  • visudo : es el comando que permite al administrador modificar el archivo /etc/sudoers. Si bien también se puede hacer con vi, es recomendable el uso de visudo ya que bloquea el archivo para su edición. Otra característica interesante de visudo es que antes de cerrar el archivo verifica que esté bien configurado y detecta los errores de sintaxis.
  • sudoers (o /etc/sudoers): es el archivo de configuración que le indica a sudo qué usuarios ejecutan cuáles comandos.

Configuración

Como ya dijimos el archivo de configuración de sudo es /etc/sudoers. Este se divide en tres secciones:

  1. Definiciones de Alias
  2. Ajuste de las opciones por defecto
  3. Reglas de acceso

Definiciones de Alias

La forma general de una definición de alias es:

Tipo_Alias NOMBRE_ALIAS = elemento1, elemento2, elemento3, …

El tipo de alias puede ser uno de los siguientes:

Cmnd_Alias: para definir alias de comandos

User_Alias: para definir alias de usuarios “normales”

Runas_Alias: para definir alias de usuarios “privilegiados”

Host_Alias: para definir alias de hosts

Nombre_Alias es el nombre que le daremos al alias. Su composición debe seguir las siguientes normas: debe ser una cadena compuesta exclusivamente por letras mayúsculas, números y guiones bajos; debe necesariamente comenzar con una letra mayúscula; es recomendable utilizar sólo letras mayúsculas.

El nombre de alias se extiende a un elemento o lista de elementos. Cada uno de estos puede, a su vez, ser un alias en una definición anterior (del mismo tipo, claro).

Alias de usuarios

Un ejemplo para la definición de una lista de usuarios sería:

User_List INVITADOS = asd53, delfin, %impresora, +robinsones, REDACTORES

Lo que esta definición establece es lo siguiente: el alias INVITADOS comprende a los usuarios asd53 y delfin, a los usuarios del grupo (system-group, se distingue por el %) impresora, a los usuarios del grupo (net-group, se distingue por el +) robinsones y a los usuarios definidos en el alias REDACTORES.

Alias de usuarios privilegiados

Se utiliza Runas_List en vez de User_List y es muy similar al anterior, salvo que aquí además podemos utilizar un uid con el prefijo #, en la lista de elementos.

Alias de hosts

La sintaxis es similar a las anteriores, salvo que cada elemento de la lista puede ser un nombre de host, una dirección IP, un número de red (este se puede seguir con una barra y su máscara, de lo contrario sudo aplicará por defecto la máscara configurada en la interface de red), un nombre de grupo de red (precedido por el signo +), u otro alias de host.

Alias de comandos

Se utiliza Cmnd_List (o Cmnd_Alias, como en cualquiera de los casos anteriores). Cada uno de los elementos que esta lista puede contener puede ser un nombre de comando, un nombre de comando y sus argumentos, un nombre de comando seguido de wildcards (comodines), un directorio, el comando sudoedit, u otro alias definido anteriormente.

Cuando se especifica un nombre de comando en la lista de elementos, se debe escribir su ruta completa. Cuando junto con el comando se especifiquen los argumentos o wildcards, el usuario sólo podrá utilizar los argumentos especificados. Si se escribe guión bajo como argumento de comando, se indica que éste sólo puede ejecutarse sin argumentos.

Cuando en lugar de un comando se especifica un directorio, el usuario puede ejecutar cualquier binario que se encuentre en el directorio epecificado. Un directorio es un path, completo y válido, acabado en /.

El comando especial sudoedit se utiliza para permitir al usuario la ejecución de sudo -e. Como cualquier comando, puede tambien especificarse con argumentos.

Cmnd_List AVANZADOS = /bin/kill, /bin/passwd, /bin/hostname, BASICOS , /usr/local/bin/

La línea anterior especifica lo siguiente: el usuario podria ejecutar los comandos kill, passwd, hostname, todos los ejecutables contenidos en el directorio /usr/local/bin/ y los comandos correspondientes al alias BASICOS.

Definiendo alias en EBNF sería así:

Alias ::= ‘User_Alias’ User_Alias (‘:’ User_Alias)* |
‘Runas_Alias’ Runas_Alias (‘:’ Runas_Alias)* |
‘Host_Alias’ Host_Alias (‘:’ Host_Alias)* |
‘Cmnd_Alias’ Cmnd_Alias (‘:’ Cmnd_Alias)*

User_Alias ::= NAME ‘=’ User_List

Runas_Alias ::= NAME ‘=’ Runas_List

Host_Alias ::= NAME ‘=’ Host_List

Cmnd_Alias ::= NAME ‘=’ Cmnd_List

NAME ::= [A-Z]([A-Z][0-9]_)*

User_List ::= User |
User ‘,’ User_List

User ::= ‘!’* username |
‘!’* ‘%’group |
‘!’* ‘+’netgroup |
‘!’* User_Alias

Runas_List ::= Runas_User |
Runas_User ‘,’ Runas_List

Runas_User ::= ‘!’* username |
‘!’* ‘#’uid |
‘!’* ‘%’group |
‘!’* +netgroup |
‘!’* Runas_Alias

Host_List ::= Host |
Host ‘,’ Host_List

Host ::= ‘!’* hostname |
‘!’* ip_addr |
‘!’* network(/netmask)? |
‘!’* ‘+’netgroup |
‘!’* Host_Alias

Cmnd_List ::= Cmnd |
Cmnd ‘,’ Cmnd_List

commandname ::= filename |
filename args |
filename ‘””‘

Cmnd ::= ‘!’* commandname |
‘!’* directory |
‘!’* “sudoedit” |
‘!’* Cmnd_Alias

Ajuste de las opciones por defecto

Pueden modificarse ciertas opciones de configuración mediante una o más líneas Defaults en el archivo /etc/sudoers.

Podemos definir las opciones:

  1. globalmente
  2. por usuario
  3. por usuario privilegiado
  4. por host

La sintaxis para cada uno sería:

  1. Defaults lista_opciones
  2. Defaults:usuario lista_opciones
  3. Defaults>usuario_privilegiado lista_opciones
  4. Defaults@host lista_opciones


Las listas de opciones están constituídas por un conjunto de opciones separadas por comas. Podemos considerar cuatro tipos de opciones: Booleanos, Enteros, Cadenas y Listas.

Booleanos : se activan con el nombre de la opción. Se desactivan con el signo ! delante.

La línea siguiente:

Defaults>root !set_logname

Desacttiva la opción set_logname para el usuario root.

Enteros : toman la forma: nombre_opcion = valor

Cadenas : toman la forma: nombre_opcion = cadena

Listas : toman la forma: nombre_opcion = valor1,valor2,…

En las listas el operador = puede ser reemplazado por += o -= , para añadir o quitar elementos.

No es mi intención profundizar más en las opciones por defecto de las que se disponen, ya que el sudo no es complejo pero si completo y bastante flexible. Una lista de las opciones de configuración con una pequeña descripción puede hallarse aquí.

Reglas de acceso

Mediante las reglas de acceso se define:

  • Los usuarios a los que permitimos utilizar sudo
  • Los comandos que dichos usuarios podrán ejecutar
  • En calidad de qué usuarios privilegiados podrán ejecutarlos
  • En qué host podrán hacerlo

La sintaxis básica es:

usuario host = (usuario_privilegiado) comando

Cada uno de los elementos anteriores puede ser un Alias o una lista de elementos.

El elemento usuario_privilegiado es opcional. Por defecto se toma root .
Un ejemplo de regla de acceso con root como usuario_privilegiado seria:

USUARIO HOST = comando1, comando2,…..

Cuando se especifique un comando siempre debe ponerse la ruta completa al ejecutable. (Cuando ejecutemos sudo no es necesario, bastará con el nombre del ejecutable).

USUARIO HOST = /usr/bin/ls

En ejemplo anterior, los usuarios de alias USUARIO, en las máquinas de alias HOST podrian ejecutar, como root el comando ls.

Como se comentó anteriormente , debemos tener en cuenta que en lugar de ejecutables pueden configurarse rutas a directorios para indicar que cualquier binario de dicho directorio se incluye en la Regla de Acceso; bastará con finalizar la ruta con / y se entenderá como un directorio. Un ejemplo:

USUARIO HOST = (operador) /usr/local/bin/

En este ejemplo los usuarios de alias USUARIO, en las máquinas de alias HOST podrian ejecutar con los privilegios del usuario operador los ejecutables que se hallen en el directorio /usr/local/bin/.

Pueden especificarse mas de un usuario_privilegiado. En este caso, cada usuario_privilegiado especificado toma efecto a todos los comandos especificados a partir de el. Veamos un eljemplo:

USUARIO HOST = (operador) comando1, comando2, (root) comado3, comando4

En la anterior regla de acceso se autoriza a los usuarios de alias USUARIO, en las máquinas de alias HOST ejecutar los comandos comando1 y comando2 como usuario operador y los comandos comando3 y comando4 como usuario root.
En este caso se obtendria el mismo resultado con la siguiente regla de acceso:

USUARIO HOST = comando3,comando4, (operador) comando1, comando2

Etiquetas de comando

Mediante éstas etiquetas se pueden modificar las condiciones en las que el usuario puede ejecutar los diversos comandos definidos. Un comando puede definirse con sero o más etiquetas asociadas a él.

En el caso de utilizar etiquetas de comando, la sintaxis podría ser:

usuario host = (usuario_privilegiado) ETIQUETA:comando, …

Se dispone de cuatro valores posibles para la etiqueta:

  • NOPASSWD
  • PASSWD
  • EXEC
  • NOEXEC

Una vez se ha asociado una etiqueta a un comando, los siguientes comandos de la lista de comandos heredan el valor de la etiqueta asociada, salvo que sea “anulada” por una etiqueta con valor opuesto.

Por defecto, sudo requiere que el usuario se autentifique mediante su contraseña antes de ejecutar un comando. Esto puede modificarse mediante la etiqueta NOPASSWD.

Al aplicar la etiqueta NOPASSWD a un comando de una lista, todos los comandos subsiguientes “heredarán” esta propiedad. Podemos desactivar la “herencia” con PASSWD . Veamos esto con un ejemplo:

jose1 hosto = (operador) NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lpr

La anterior definición nos dice que el usuario jose1, en el host hosto, en calidad de usuario_privilegiado operator, puede ejecutar sin necesidad de autentificarse los comandos /bin/kill, /bin/ls, y /usr/bin/lpr.

Si deseáramos que solo pudiera ejecutar /bin/kill sin necesidad de autentificarse, desactivariamos NOPASSWD para /bin/ls y /usr/bin/lpr, mediante PASSWD :

jose1 hosto = (operador) NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lpr

Si quisiéramos que /bin/ls fuera el único comando que pudiera ejecutarse sin autentificación, la sintaxis deberia ser:

jose1 hosto = (operador) /bin/kill, NOPASSWD: /bin/ls, PASSWD: /usr/bin/lpr

Una vez sudo ejecuta un perograma, dicho programa es libre de realizar cualquier operación que le sea propia, incluida la ejecución de otro programa. Esto puede plantear una cuestión de seguridad, ya que no es infrecuente que un programa permita shell escapes, lo que posibilita al usuario “puentear” las restricciones de sudo .

La funcionalidad noexec de sudo puede utilizarse para prevenir que con un programa que se haya ejecutado através de sudo pueda ejecutarse cualquier otro programa. Debe tenerse en cuenta, sin embargo, que esto es sólo posible con ejecutables dinamicamente enlazados (dynamically-linked). Con ejecutables estaticamente enlazados ( statically-linked) no tiene efecto.

En el siguiente ejemplo habilitamos al usuario asd53 , sobre el host host3 ejecurar como root los comandos les y pine , con noexec activado:

asd53 host3 = NOEXEC : /usr/bin/less , /usr/bin/pine

Fuentes

Este documento no está completo ni mucho menos. De hecho, los últimos párrafos están casi textuales de fuente porque ya estaba hasta los huevos de escribir. El sudo es una herramienta muy completa. No es la panacea en lo que a seguridad se refiere, pero es su flexibilidad lo que me gusta. Para profundizar se puede consultar los siguientes enlaces:

2 comentarios

Subscribe to comments with RSS.

  1. Felipe Leonardo said, on diciembre 27, 2007 at 1:25 am

    El articulo, muy bueno y muy completo, la caricatura muy usada pero es lo demenos, de verdad buen articulo.

    Saludos

  2. […] multix wrote an interesting post today onHere’s a quick excerptSi bien usando el comando su podemos cambiar al modo root, esta es una práctica peligrosa. Sobre todo en ambientes multiusuario, porque implicaría entregar la contraseña del usuario root a todos los que la necesiten (y me cago en la seguridad). Sudo se basa en una lista de control (que se encuentra en el archivo /etc/sudoers) para permitir (o no) la ejecución a un determinado usuario de un comando que es propiedad de otro usuario, generalmente del administrador del sistema (root). Consideremos aquí las tres partes que componen esta suite de seguridad: […]


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: