- 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 195.195.5.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 195.195.5.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