2.7.3. Privilegios

En un principio (incluso históricamente hablando), en el sistema corren dos tipos de procesos: los procesos privilegiados y los procesos sin privilegios. Es, pues, una distinción dicotómica sin escala de grises: los primeros pueden hacer cualquier tipo de llamadas al kernel, mientras que para los segundos sólo es posible un conjunto de llamadas a nivel de usuario. Por ejemplo, manipular interfaces de red (crear interfaces virtuales, dar o borrar configuración a las interfaces, etc) son operaciones que requieren privilegio.

Nota

Téngase en cuenta que dentro de las llamadas no privilegiadas, también existen restricciones: las que se establecen a través de los permisos sobre archivos. Así, por ejemplo, no todos los procesos sin privilegios tienen la capacidad de formatear dispostivos; sino sólo aquellos cuyo ejecutante posea permisos para escribir sobre la representación en forma de archivo del dispositivo.

Un proceso ejecutado por el usuario de UID 0, esto es, por el administrador, es siempre un proceso privilegiado, de ahí que en un sistema UNIX pueda realizar cualquier acción. La pregunta entonces es, ¿existe alguna estrategia para que a un proceso iniciado por un usuario distinto a root, se le permita ejecutar una acción que requiera privilegios? Y la respuesta es sí, en concreto, hay dos estrategias a las que dedicaremos el resto del epígrafe.

Advertencia

El núcleo de Linux se desentiende del setuid y las capabilities definidas en ejecutables interpretados (p.e. un script de bash). Así pues, su definición sólo tiene sentido para programas compilados. Esta limitación, no obstante, no es común a todos los UNIX.

setuid

La solución tradicional en los sistemas Linux para que los usuarios sin privilegios puedan realizar acciones privilegidas es el setuid habilitado en un ejecutable cuyo propietario es el administrador. De este modo, el proceso corre como si fuera ejecutado por root. Basados en esta estrategia, hay cuatro maneras de que el usuario opere como administrador:

  1. Habilitar directamente el setuid sobre el archivo de un ejecutable que pertenece al administrador. De este modo, cualquier usuario con permisos de ejecución creará un proceso privilegiado al ejecutarlo.

  2. Utilizar su (o runuser) que es un programa con el setuid habilitado, que permite la ejecución de cualquier otro programa. De este modo, cualquier usuario que conozca la contraseña del administrador[1], podrá ejecutar programas de forma privilegiada, incluida una shell interactiva.

  3. Como variante del anterior, utilizar sudo, que también tiene habilitado su setuid y cuya principal aportación es ser mucho más configurable que su:

    • Para la autenticación permite la introducción de la propia contraseña del usuario, de la contraseña del administrador o ninguna.

    • Permite restringir, según cada usuario, cuáles son los programas que podrán ejecutarse en modo privilegiado.

  4. Polkit que es una herramienta que permite definir reglas de autorización para procesos sin privilegios. Este método permite limitar los privilegios que se conceden al proceso por lo que, a diferencia de los otros tres, no tendrá poderes omnímodos. Suele utilizarse en equipos de escritorio por ser la herramienta preferida por estos entornos para que el usuario habitual sea capaz de realizar acciones que en principio le están vedadas (como apagar la máquina).

Por lo general, para que un usuario acceda a una consola interactiva con la identidad de root, se usan su o sudo dependiendo de la distribución:

  • su viene de base en Debian y su uso ya se describió:

    $ su -
    

    Esta orden requiere la introducción de la contraseña de administrador[2], tras lo cual conseguiremos una sesión interactiva en la que nos convertiremos en el administrador.

  • sudo es la estrategia que han adoptado otras distribuciones como Ubuntu[3], y a cuya configuración y uso dedicaremos epígrafe aparte.

Sea como sea, esta estrategia tiene un problema principal: viola el principio de mínimo privilegio[4], lo cual propicia que cualquier programa se convierta en un peligro potencial de seguridad si contiene algún bug que permita a un usuario malintencionado explotarlo para escalar privilegios y hacer algo distinto para lo que originariamente fue diseñado.

Capacidades

Para no conculcar el principio de mínimo privilegio, Linux a partir de su versión 2.2 introdujo el concepto de capabilities(7), cuya filosofía es descomponer el poder para realizar acciones privilegiadas en múltiples capacidades independientes (unas 40 actualmente). cada una de las cuales habilita la realización de determinadas llamadas del núcleo, de modo que si, por ejemplo, se requiere que un proceso cree y configure alguna interfaz de red podemos, simplemente, deberá tener habilitada la capacidad CAP_NET_ADMIN, pero no las restantes.

Desde el punto de vista de las capacidades, ejecutar un procesos como root (que es lo que hace utlizando el setuid) equivale a dotar al proceso de todas las capacidades. Profundizaremos en el estudio de las capacidades, también en un epígrafe aparte.

Profundización

Notas al pie