- Cierre de servicios ofrecidos por inetd
Cada servicio ofrecido en nuestro sistema se convierte en una potencial puerta
de acceso al mismo, por lo que hemos de minimizar su número: se recomienda
cerrar cualquier servicio que no se vaya a utilizar, y todos aquellos de los
que no conozcamos su utilidad (si más tarde son necesarios, los podemos
volver a abrir).
Para cerrar un servicio ofrecido desde inetd, en el fichero /etc/inetd.conf debemos comentar la línea correspondiente a ese servicio,
de forma que una entrada como
telnet stream tcp nowait root /usr/sbin/in.telnetd
se convierta en una como
#telnet stream tcp nowait root /usr/sbin/in.telnetd
Tras efectuar esta operación, debemos reiniciar el demonio inetd para
que relea su configuración; esto lo conseguimos, por ejemplo, con la orden
anita:/# pkill -HUP inetd
o, si no disponemos de un comando para enviar señales a procesos a partir de
su nombre, con la orden
anita:/# kill -HUP `ps -ef|grep -w inetd|awk '{print $2}'`
- Cierre de servicios ofrecidos en el arranque de máquina
Existen una serie de demonios que ofrecen ciertos servicios, como sendmail, que no se procesan a través de inetd sino que se lanzan
como procesos independientes al arrancar la máquina. Para detener este tipo
de demonios hemos de comentar las líneas de nuestros ficheros de arranque
encargadas de lanzarlos (generalmente en directorios como /etc/rc?.d/ o
/etc/rc.d/): de esta forma conseguimos que la próxima vez que el sistema
se inicie, los demonios no se ejecuten. Aparte de esto, hemos de detener los
demonios en la sesión actual, ya que en estos momentos seguramente están
funcionando; para ello les enviamos la señal SIGKILL mediante el
comando kill.
Por ejemplo, en el caso de Solaris, sendmail se lanza desde el archivo
/etc/rc2.d/S88sendmail; en este fichero tendremos unas líneas
similares a estas:
if [ -f /usr/lib/sendmail -a -f /etc/mail/sendmail.cf ]; then
if [ ! -d /var/spool/mqueue ]; then
/usr/bin/mkdir -m 0750 /var/spool/mqueue
/usr/bin/chown root:bin /var/spool/mqueue
fi
/usr/lib/sendmail -bd -q15m &
fi
Podemos renombrar este archivo como disabled.S88sendmail o comentar estas
líneas de la forma siguiente:
#if [ -f /usr/lib/sendmail -a -f /etc/mail/sendmail.cf ]; then
# if [ ! -d /var/spool/mqueue ]; then
# /usr/bin/mkdir -m 0750 /var/spool/mqueue
# /usr/bin/chown root:bin /var/spool/mqueue
# fi
# /usr/lib/sendmail -bd -q15m &
#fi
Y a continuación eliminaremos el proceso sendmail enviándole la
señal SIGKILL:
anita:/# ps -ef |grep sendmail
root 215 1 0 01:00:38 ? 0:00 /usr/lib/sendmail -bd -q15m
anita:/# kill -9 215
- Instalación de wrappers
A pesar de haber cerrado muchos servicios siguiendo los puntos anteriores,
existen algunos que no podremos dejar de ofrecer, como telnet o ftp, ya que los usuarios van a necesitar conectar al sistema de forma remota o
transferir ficheros. En estos casos es muy conveniente instalar wrappers
para los demonios que sigan recibiendo conexiones; mediante el uso de estos
programas vamos a poder restringir los lugares desde los que nuestro equipo
va a aceptar peticiones de servicio. Especialmente recomendable es el
programa TCP-Wrapper para controlar las conexiones servidas por inetd (incluso sendmail se puede controlar por inetd, lo cual es
muy útil si queremos restringir los lugares desde los que nos pueda llegar
correo).
Por ejemplo, si no utilizamos wrappers para controlar el servicio de telnet, cualquier máquina de Internet puede intentar el acceso a nuestro
sistema:
luisa:~$ telnet anita
Trying 192.168.0.3...
Connected to anita.
Escape character is '^]'.
SunOS 5.7
login:
Sin embargo, configurando TCP-Wrapper para que no admita conexiones desde
fuera de la universidad, si alguien intenta lo mismo obtendrá un resultado
similar al siguiente:
luisa:~$ telnet anita
Trying 192.168.0.3...
Connected to anita.
Escape character is '^]'.
Connection closed by foreign host.
luisa:~$
De esta forma, incluso si el atacante conociera un nombre de usuario y su clave
le sería más difícil acceder a nuestro equipo por telnet.
- Ficheros setuidados y setgidados
En un sistema Unix recién instalado podemos tener incluso más de cincuenta
ficheros con los modos setuid o setgid activados; cualquiera de
estos programas representa un potencial agujero a la seguridad de nuestro
sistema, y aunque muchos son necesarios (como /bin/passwd en la
mayoría de situaciones), de otros se puede prescindir. Para localizar los
ficheros setuidados podemos utilizar la orden
anita:/# find / -perm -4000 -type f -print
mientras que para localizar los setgidados podemos utilizar
anita:/# find / -perm -2000 -type f -print
Es conveniente que reduzcamos al mínimo el número de estos archivos, pero
tampoco se recomienda borrarlos del sistema de ficheros; es mucho más habitual
resetear el bit de setuid o setgid, y en caso de que sea necesario
volverlo a activar. Para desactivar estos bits podemos usar la orden chmod -s, mientras que para activarlos utilizaremos chmod u+s o chmod g+s.
Por ejemplo, si el fichero /usr/lib/fs/ufs/ufsdump está setuidado,
un listado largo del mismo nos mostrará una s en el campo de ejecución
para propietario, mientras que si está setgidado aparecerá una s en el campo de ejecución para grupo; podemos resetear los dos bits con
la orden vista anteriormente:
anita:/# ls -l /usr/lib/fs/ufs/ufsdump
-r-sr-sr-x 1 root tty 144608 Oct 6 1998 /usr/lib/fs/ufs/ufsdump
anita:/# chmod -s /usr/lib/fs/ufs/ufsdump
anita:/# ls -l /usr/lib/fs/ufs/ufsdump
-r-xr-xr-x 1 root tty 144608 Oct 6 1998 /usr/lib/fs/ufs/ufsdump
- Cifrado de datos
El principal problema de las claves viajando en texto claro por la red es que
cualquier atacante puede leerlas: si usamos telnet, rlogin o ftp, cualquier persona situada entre nuestra estación de trabajo y el
servidor al que conectamos puede `esnifar' los paquetes que circulan por la
red y obtener así nuestro nombre de usuario y nuestro password.
Para evitar este problema es conveniente utilizar software que implemente
protocolos cifrados para conectar; el más habitual hoy en día es SSH (Secure Shell). Por una parte, tenemos el programa servidor sshd, que se ha de instalar en el equipo al que conectamos, y por otra
programas clientes (ssh para sustituir a rsh/rlogin y scp
para sustituir a rcp).
Una vez instalado, este software es transparente al usuario: simplemente
ha de recordar su clave, igual que si conectara por telnet o rlogin.
- Relaciones de confianza
En el fichero /etc/hosts.equiv se indican, una en cada línea, las
máquinas confiables.
>Qué significa confiables? Básicamente que confiamos en su seguridad
tanto como en la nuestra, por lo que para facilitar la compartición de
recursos, no se van a pedir contraseñas a los usuarios que quieran conectar
desde estas máquinas con el mismo login, utilizando las órdenes
BSD r (rlogin, rsh, rcp...). Por ejemplo, si en el
fichero /etc/hosts.equiv del servidor anita hay una entrada
para el nombre
de host luisa, cualquier usuarioA.1 de este sistema puede ejecutar una orden como la siguiente para
conectar a anita <sin necesidad de ninguna clave!:
luisa:~$ rlogin anita
Last login: Sun Oct 31 08:27:54 from localhost
Sun Microsystems Inc. SunOS 5.7 Generic October 1998
anita:~$
Obviamente, esto supone un gran problema de seguridad, por lo que lo más
recomendable es que el fichero /etc/hosts.equiv esté vacío o no
exista. De la misma forma, los usuarios pueden crear ficheros $HOME/.rhosts para establecer un mecanismo de confiabilidad bastante similar
al de /etc/hosts.equiv; es importante para la seguridad de nuestro
sistema el controlar la existencia y el contenido de estos archivos .rhosts. Por ejemplo, podemos aprovechar las facilidades de planificación de
tareas de Unix para, cada cierto tiempo, chequear los directorios $HOME
de los usuarios en busca de estos ficheros, eliminándolos si los
encontramos. Un shellscript que hace esto puede ser el siguiente:
#!/bin/sh
for i in `cat /etc/passwd |awk -F: '{print $6}'`; do
cd $i
if [ -f .rhosts ]; then
echo "$i/.rhosts detectado"|mail -s "rhosts" root
rm -f $i/.rhosts
fi
done
Este programa envía un correo al root en caso de encontrar un
fichero .rhosts, y lo elimina; podemos planificarlo mediante cron
para que se ejecute, por ejemplo, cada cinco minutos. La forma de planificarlo
depende del clon de Unix en el que trabajemos, por lo que se recomienda
consultar la página del manual de cron o crond; en el caso de
Solaris, para que se ejecute cada vez que cron despierte, y suponiendo
que el script se llame /usr/local/sbin/busca, pondríamos
en nuestro crontab (con crontab -e) una línea como
* * * * * /usr/local/sbin/busca 2>&1 >/dev/null
Hemos de estar atentos a la carga que este tipo de actividades periódicas
puede introducir en el sistema; la orden anterior se va a ejecutar cada vez
que cron despierta, generalmente una vez por minuto, lo que implica que
en máquinas con un gran número de usuarios puede introducir un factor
importante de operaciones de I/O. Una solución más adecuada en estas
situaciones sería planificar el programa para que se ejecute cada cinco o
diez minutos, o el tiempo que estimemos necesario en nuestro equipo.
- Política de cuentas
Muchos clones de Unix se instalan con cuentas consideradas `del sistema', es
decir, que no corresponden a ningún usuario concreto sino que existen por
cuestiones de compatibilidad o para la correcta ejecución de algunos
programas. Algunas de estas cuentas no tienen contraseña, o tienen una
conocida por todo el mundo, por lo que representan una grave amenaza a la
seguridad: hemos de deshabilitarlas para evitar que alguien pueda conectar
a nuestro equipo mediante ellas. Algunos ejemplos de este tipo de cuentas
son guest, demo, uucp, games, 4DGifts o lp.
Para deshabilitar una cuenta, en Unix no tenemos más que insertar un asterisco
en el campo passwd en la línea correspondiente del fichero de claves
(generalmente /etc/passwd o
/etc/shadow). De esta forma, una
entrada como
toni:7atzxSJlPVVaQ:1001:10:Toni Villalon:/export/home/toni:/bin/sh
pasaría a convertirse en
toni:*7atzxSJlPVVaQ:1001:10:Toni Villalon:/export/home/toni:/bin/sh
Aparte de este tipo de cuentas, hemos de tener un especial cuidado con las
cuentas de usuario que no tienen contraseña o que tienen una clave débil;
para detectar este último problema podemos utilizar programas adivinadores
como Crack, mientras que para evitarlo podemos utilizar NPasswd o
Passwd+, además de sistemas Shadow Password para que los usuarios
no puedan leer las claves cifradas. Para detectar cuentas sin contraseña
(aunque también Crack nos
las indicará), podemos utilizar la siguiente orden, obviamente sustituyendo
/etc/passwd por el fichero de claves de nuestro sistema:
anita:~# awk -F: '$2=="" {print $1}' /etc/passwd
Por último, hay que decir que una correcta política de cuentas pasa por
deshabilitar la entrada de usuarios que no utilicen el sistema en un tiempo
prudencial; por ejemplo, podemos cancelar las cuentas de usuarios que no
hayan conectado a la máquina en los últimos dos meses, ya que son firmes
candidatas a que un pirata las aproveche para atacarnos; la orden finger
nos puede ayudar a detectar este tipo de usuarios.
- Negaciones de servicio
Un tipo de ataque que ni siquiera suele necesitar de un acceso al sistema es el
conocido como la negación de servicio (Denial of Service). Consiste
básicamente en perjudicar total o parcialmente la disponibilidad de un
recurso, por ejemplo utilizando grandes cantidades de CPU, ocupando toda la
memoria del sistema o incluso deteniendo una máquina. Obviamente las
negaciones de servicio más peligrosas son las que detienen el sistema o
alguno de sus servicios de forma remota:
Las paradas de máquina
son, por norma general, fruto de un fallo en la implementación de red del
núcleo: por ejemplo, la llegada de un paquete con una cabecera extraña, de
una longitud determinada, o con una cierta prioridad, puede llegar a detener la
máquina si ese paquete no se trata correctamente en la implementación del
sistema de red. La mejor forma de prevenir estos ataques (que no suelen dejar
ningún rastro en los ficheros de log) es actualizar el núcleo de
nuestro Unix periódicamente, manteniendo siempre la última versión
estable.
En el caso de la detención de servicios determinados, habitualmente los
ofrecidos desde inetd, la negación de servicio suele ser fruto de un
excesivo número de peticiones `falsas' al demonio correspondiente; por
ejemplo, un atacante enmascara su dirección IP para sobrecargar de peticiones
un demonio como in.telnetd hasta detenerlo. Para evitar estos ataques
podemos incrementar el número de peticiones simultáneas que un demonio
acepta (en la opción wait de la línea correspondiente en el
fichero /etc/inetd.conf), aunque esto también implica peligros de
negación de servicio (puede aumentar demasiado el tiempo de respuesta del
equipo); una forma mucho más recomendable de actuar no es prevenir estos
ataques sino minimizar sus efectos: si enviamos una señal SIGHUP al
demonio inetd éste relee su configuración, por lo que el servicio
bloqueado vuelve a funcionarA.2. Por tanto, es recomendable enviar una de estas
señales de forma automática cada cierto tiempo; podemos planificar esta
acción para que cron la ejecute cada vez que despierte, incluyendo en
nuestro archivo crontab una línea como la siguiente:
* * * * * /usr/bin/pkill -HUP inetd 2>&1 >/dev/null