Habitualmente, los permisos de los archivos en Unix se corresponden con un
número en octal que varía entre 000 y 777; sin embargo, existen unos
permisos especiales que hacen variar ese número entre 0000 y 7777: se trata
de los bits de permanencia (1000), SGID (2000) y SUID (4000).
El bit de SUID o setuid se activa sobre un fichero
añadiéndole 4000 a la
representación octal de los permisos del archivo y otorgándole además
permiso de ejecución al propietario del mismo; al hacer esto, en lugar de
la x en la primera terna de los permisos, aparecerá una s o una
S si no hemos otorgado el permiso de ejecución correspondiente (en
este caso el bit no tiene efecto):
anita:~# chmod 4777 /tmp/file1
anita:~# chmod 4444 /tmp/file2
anita:~# ls -l /tmp/file1
-rwsrwxrwx 1 root other 0 Feb 9 17:51 /tmp/file1*
anita:~# ls -l /tmp/file2
-r-Sr--r-- 1 root other 0 Feb 9 17:51 /tmp/file2*
anita:~#
El bit SUID activado sobre un fichero indica que todo aquél que
ejecute el archivo va a tener durante la ejecución los mismos privilegios que
quién lo creó; dicho de otra forma, si el administrador crea un fichero
y lo setuida, todo aquel usuario que lo ejecute va a disponer, hasta que
el programa finalice, de un nivel de privilegio total en el sistema. Podemos
verlo con el siguiente ejemplo:
luisa:/home/toni# cat testsuid.c
#include <stdio.h>
#include <unistd.h>
main(){
printf("UID: %d, EUID: %d\n",getuid(),geteuid());
}
luisa:/home/toni# cc -o testsuid testsuid.c
luisa:/home/toni# chmod u+s testsuid
luisa:/home/toni# ls -l testsuid
-rwsr-xr-x 1 root root 4305 Feb 10 02:34 testsuid
luisa:/home/toni# su toni
luisa:~$ id
uid=1000(toni) gid=100(users) groups=100(users)
luisa:~$ ./testsuid
UID: 1000, EUID: 0
luisa:~$
Podemos comprobar que el usuario toni, sin ningún privilegio
especial en el sistema, cuando ejecuta nuestro programa setuidado de
prueba está trabajando con un EUID (Effective UID) 0, lo que le
otorga todo el poder del administrador (fijémonos que éste último es
el propietario del ejecutable); si en lugar de este código el ejecutable
fuera una copia de un shell, el usuario toni tendría todos los
privilegios del root mientras no finalice la ejecución, es decir, hasta
que no se teclee exit en la línea de órdenes.
Todo lo que acabamos de comentar con respecto al bit setuid es aplicable
al bit setgid pero a nivel de grupo del fichero en lugar de propietario:
en lugar de trabajar con el EUID del propietario, todo usuario que
ejecute un programa setgidado tendrá los privilegios del grupo al que
pertenece el archivo. Para activar el bit de setgid sumaremos 2000 a la
representación octal del permiso del fichero y además habremos de darle
permiso de ejecución a la terna de grupo; si lo hacemos, la s o S
aparecerá en lugar de la x en esta terna. Si el fichero es un directorio
y no un archivo plano, el bit setgid afecta a los ficheros y
subdirectorios que se creen en él: estos tendrán como grupo propietario al
mismo que el directorio setgidado, siempre que el proceso que los cree
pertenezca a dicho grupo.
Pero, >cómo afecta todo esto a la seguridad del sistema? Muy sencillo:
los bits de setuid y setgid dan a Unix una gran flexibilidad, pero
constituyen al mismo tiempo la mayor fuente de ataques internos al sistema
(entendiendo por ataques internos aquellos realizados por un usuario -
autorizado o no - desde la propia máquina, generalmente con el objetivo de
aumentar su nivel de privilegio en la misma).
Cualquier sistema Unix tiene un cierto número de ejecutables setuidados y/o setgidados. Cada uno de ellos, como acabamos de comentar,
se ejecuta con los privilegios de quien lo creó (generalmente el root
u otro usuario con ciertos privilegios) lo que directamente implica que
cualquier usuario tiene la capacidad de lanzar tareas que escapen total o
parcialmente al control del sistema operativo: se ejecutan en modo privilegiado
si es el administrador quien creó los ejecutables. Evidentemente, estas
tareas han de estar controladas de una forma exhaustiva, ya que si una de ellas
se comporta de forma anormal (un simple core dump) puede causar
daños irreparables al sistema5.6; tanto es así que hay innumerables
documentos que definen, o lo intentan, pautas de programación considerada
`segura' (en la sección 5.5 se citan algunos de ellos y también
se explican algunas de estas técnicas). Si por cualquier motivo un programa
setuidado falla se asume inmediatamente que presenta un problema de
seguridad para la máquina, y se recomienda resetear el bit de setuid
cuanto antes.
Está claro que asegurar completamente el comportamiento correcto de un
programa es muy difícil, por no decir imposible; cada cierto tiempo suelen
aparecer fallos (bugs) en ficheros setuidados de los diferentes
clones de Unix que ponen en peligro la integridad del sistema. Entonces, >por
qué no se adopta una solución radical, como eliminar este tipo de archivos?
Hay una sencilla razón: el riesgo que presentan no se corre inútilmente,
para tentar al azar, sino que los archivos que se ejecutan con privilegios son
estrictamente necesarios en Unix, al menos algunos de ellos. Veamos un ejemplo:
un fichero setuidado clásico en cualquier clon es /bin/passwd,
la orden para que los usuarios puedan cambiar su contraseña de entrada al
sistema. No hace falta analizar con mucho detalle el funcionamiento de este
programa para darse cuenta que una de sus funciones consiste en modificar el
fichero de claves (/etc/passwd o /etc/shadow). Está claro que
un usuario per se no tiene el nivel de privilegio necesario para hacer
esto (incluso es posible que ni siquiera pueda leer el fichero de claves), por lo
que frente a este problema tan simple existen varias soluciones: podemos
asignar permiso de escritura para todo el mundo al fichero de contraseñas,
podemos denegar a los usuarios el cambio de clave o podemos obligarles a pasar
por la sala de operaciones cada vez que quieran cambiar su contraseña. Parece
obvio que ninguna de ellas es apropiada para la seguridad del sistema (quizás
la última lo sea, pero es impracticable en máquinas con un número de
usuarios considerable). Por tanto, debemos asumir que el bit de setuid en
/bin/passwd es imprescindible para un correcto funcionamiento del
sistema. Sin embargo, esto no siempre sucede así: en un sistema Unix
instalado out of the box el número de ficheros setuidados suele ser
mayor de cincuenta; sin perjudicar al correcto funcionamiento de la máquina,
este número se puede reducir a menos de cinco, lo que viene a indicar que
una de las tareas de un administrador sobre un sistema recién instalado es
minimizar el número de ficheros setuidados o setgidados. No
obstante, tampoco es conveniente eliminarlos, sino simplemente resetear su bit
de setuid mediante chmod:
luisa:~# ls -l /bin/ping
-r-sr-xr-x 1 root bin 14064 May 10 1999 /bin/ping*
luisa:~# chmod -s /bin/ping
luisa:~# ls -l /bin/ping
-r-xr-xr-x 1 root bin 14064 May 10 1999 /bin/ping*
luisa:~#
También hemos de estar atentos a nuevos ficheros de estas características
que se localicen en la máquina; demasiadas aplicaciones de Unix se instalan
por defecto con ejecutables setuidados cuando realmente este bit no es
necesario, por lo que a la hora de instalar nuevo software o actualizar
el existente hemos de acordarnos de resetear el bit de los ficheros que no lo
necesiten. Especialmente grave es la aparición de archivos setuidados
de los que el administrador no tenía constancia (ni son aplicaciones del
sistema ni un aplicaciones añadidas), ya que esto casi en el 100% de los
casos indica que nuestra máquina ha sido comprometida por un atacante. Para
localizar los ficheros con alguno de estos bits activos, podemos ejecutar la
siguiente orden:
luisa:~# find / \( -perm -4000 -o -perm -2000 \) -type f -print
Por otra parte, el sticky bit o bit de permanencia se activa sumándole
1000 a la
representación octal de los permisos de un determinado archivo y otorgándole
además permiso de ejecución; si hacemos esto, veremos que en lugar de una
x en la terna correspondiente al resto de usuarios aparece una t
(si no le hemos dado permiso de ejecución al archivo, aparecerá una T):
anita:~# chmod 1777 /tmp/file1
anita:~# chmod 1774 /tmp/file2
anita:~# ls -l /tmp/file1
-rwxrwxrwt 1 root other 0 Feb 9 17:51 /tmp/file1*
anita:~# ls -l /tmp/file2
-rwxrwxr-T 1 root other 0 Feb 9 17:51 /tmp/file2*
anita:~#
Si el bit de permanencia de un fichero está activado (recordemos que si
aparece una T no lo está) le estamos indicando al sistema operativo que
se trata de un archivo muy utilizado, por lo que es conveniente que permanezca
en memoria principal el mayor tiempo posible; esta opción se utilizaba en
sistemas antiguos que disponían de muy poca RAM, pero hoy en día
prácticamente no se utiliza. Lo que si que sigue vigente es el efecto del
sticky bit activado sobre un directorio: en este caso se indica al
sistema operativo que, aunque los permisos `normales' digan que cualquier
usuario pueda crear y eliminar ficheros (por ejemplo, un 777 octal), sólo el
propietario de cierto archivo y el administrador pueden borrar un archivo
guardado en un directorio con estas características. Este bit, que sólo
tiene efecto cuando es activado por el administrador (aunque cualquier
usuario puede hacer que aparezca una t o una T en sus ficheros y
directorios), se utiliza principalmente en directorios del sistema de ficheros
en los que interesa que todos puedan escribir pero que no todos puedan borrar
los datos escritos, como /tmp/ o /var/tmp/: si el equivalente octal
de los permisos de estos directorios fuera simplemente 777 en lugar de 1777,
cualquier usuario podría borrar los ficheros del resto. Si pensamos que
para evitar problemas podemos simplemente denegar la escritura en directorios
como los anteriores también estamos equivocados: muchos programas - como
compiladores, editores o gestores de correo - asumen que van a poder crear
ficheros en /tmp/ o /var/tmp/, de forma que si no se permite a los
usuarios hacerlo no van a funcionar correctamente; por tanto, es muy
recomendable para el buen funcionamiento del sistema que al menos el
directorio /tmp/ tenga el bit de permanencia activado.
Ya para finalizar, volvemos a lo que hemos comentado al principio de la
sección: el equivalente octal de los permisos en Unix puede variar entre 0000
y 7777. Hemos visto que podíamos sumar 4000, 2000 o 1000 a los permisos
`normales' para activar respectivamente los bits setuid, setgid o
sticky. Por supuesto, podemos activar varios de ellos a la vez simplemente
sumando sus valores: en la situación poco probable de que necesitáramos
todos los bits activos, sumaríamos 7000 a la terna octal 777:
luisa:~# chmod 0 /tmp/fichero
luisa:~# ls -l /tmp/fichero
---------- 1 root root 0 Feb 9 05:05 /tmp/fichero
luisa:~# chmod 7777 /tmp/fichero
luisa:~# ls -l /tmp/fichero
-rwsrwsrwt 1 root root 0 Feb 9 05:05 /tmp/fichero*
luisa:~#
Si en lugar de especificar el valor octal de los permisos queremos utilizar
la forma simbólica de chmod, utilizaremos +t para activar el
bit de permanencia, g+s para activar el de setgid y u+s para
hacer lo mismo con el de setuid; si queremos resetearlos, utilizamos un
signo `-' en lugar de un `+' en la línea de órdenes.
© 2002 Antonio Villalón Huerta