Las negaciones de servicio (conocidas como DoS, Denial of Service) son
ataques dirigidos contra un recurso informático (generalmente una máquina o
una red, pero también podría tratarse de una simple impresora o una
terminal) con el objetivo de degradar total o parcialmente los servicios
prestados por ese recurso a sus usuarios legítimos; constituyen en muchos
casos uno de los ataques más sencillos y contundentes contra todo tipo de
servicios, y en entornos donde la disponibilidad es valorada por encima de otros
parámetros de la seguridad global puede convertirse en un serio problema, ya
que un pirata puede interrumpir constantemente un servicio sin necesidad de
grandes conocimientos o recursos, utilizando simplemente sencillos programas y
un módem y un PC caseros.
Las negaciones de servicio más habituales suelen consistir en la
inhabilitación total de un determinado servicio o de un sistema completo, bien
porque ha sido realmente bloqueado por el atacante o bien porque está tan
degradado que es incapaz de ofrecer un servicio a sus usuarios. En la mayor
parte de sistemas, un usuario con acceso shell no tendría muchas
dificultades en causar una negación de servicio que tirara abajo la máquina
o la ralentizara enormemente; esto no tiene porqué ser - y de hecho en muchos
casos no lo es - un ataque intencionado, sino que puede deberse a un simple
error de programación. Por ejemplo, pensemos en el siguiente shellscript (funciona en Linux):
luisa:~# cat /usr/local/bin/lanzador
#!/bin/sh
ps -ef|grep calcula|grep -v grep 2>&1 >/dev/null
if [ $? -eq 1 ]; then
/usr/local/bin/calcula &
fi
luisa:~#
Como podemos ver, este script comprueba si un determinado programa
está lanzado en la máquina, y si no lo está lo lanza él; algo
completamente inofensivo a primera vista, y planificado habitualmente en muchos
sistemas para que se ejecute - por ejemplo, cada cinco minutos - desde crond. Sin embargo, nos podemos parar a pensar qué sucedería bajo
algunas circunstancias anormales: >y si en el arranque de la máquina, por el
motivo que sea, no se ha montado correctamente el directorio /proc/? Si
esto sucede, la orden `ps' generará un error, la condición se
cumplirá siempre, y cada cinco minutos se lanzará una copia de calcula; si este programa consume mucha CPU, al poco tiempo tendremos un
elevado número de copias que cargarán enormemente el sistema hasta hacerlo
inutilizable. Un ejemplo perfecto de negación de servicio.
Por fortuna, como ya hemos visto en capítulos anteriores, todos los
sistemas Unix ofrecen mecanismos para evitar que un usuario normal pueda tirar
abajo una máquina de esta forma; incluso si no los ofrecieran, en la mayor
parte de los casos el responsable podría ser disciplinado fuera del
sistema operativo, por otros medios, como dijo Dennis Ritchie. El problema
real no es que usuarios legítimos de un entorno causen, intencionada o
inintencionadamente, negaciones de servicio: el mayor problema es que esas
negaciones sean causadas de forma remota por piratas ajenos por completo a
nuestra organización, capaces de tumbar un servidor de millones de pesetas
con sencillos programas, sin dejar ningún rastro y lo peor, sin ser muchas
veces conscientes del daño que están haciendo.
Estos ataques remotos de negación de servicio son considerados negativos
incluso por muchos de los propios piratas - especialmente los más
experimentados -, ya que realmente no suelen demostrar nada positivo de quien
los lanza (si es que algún ataque demuestra algo positivo de alguien, lo cual
sería muy discutible...): generalmente se trata de un script-kiddie ejecutando un programa que ni ha hecho, ni entiende, ni será
capaz de entender. En la mayor parte de los casos la negación de servicio
tiene éxito porque el objetivo utiliza versiones no actualizadas de demonios
(si se para un servicio concreto) o del propio núcleo del sistema operativo,
si se detiene o degrada por completo la máquina. Para evitar esto, la norma a
seguir es evidente: mantener siempre actualizados nuestros sistemas, tanto en
lo referente al nivel de parcheado o versiones del núcleo, como en lo
referente a programas críticos encargados de ofrecer un determinado
servicio (demonios, por norma general: sendmail, httpd, pop3d...).
De un tiempo a esta parte - en concreto, desde 1999 - se ha popularizado
mucho el término `negación de servicio distribuida' (Distributed
Denial of Service, DDoS): en este ataque un pirata compromete en primer lugar
un determinado número de máquinas y, en un determinado momento, hace que
todas ellas ataquen masiva y simultaneamente al objetivo u objetivos reales
enviándoles diferentes tipos de
paquetes; por muy grandes que sean los recursos de la víctima, el gran
número de tramas que reciben hará que tarde o temprano dichos recursos sean
incapaces de ofrecer un servicio, con lo que el ataque habrá sido exitoso.
Si en lugar de cientos o miles de equipos atacando a la vez lo hiciera uno
sólo las posibilidades de éxito serían casi inexistentes, pero es
justamente el elevado número de `pequeños' atacantes lo que hace muy
difícil evitar este tipo de negaciones de servicio.
Según el CERT ([HW01]) los ataques de negación de servicio
distribuidos más habituales consisten en el envío de un gran número de
paquetes a un determinado objetivo por parte de múltiples hosts, lo que
se conoce como packet flooding (en función del tipo de paquetes
utilizados se habla de ping flood, de SYN flood...).
Defenderse de este tipo de ataques es difícil: en primer lugar, uno piensa
en bloquear de alguna forma (probablemente en un cortafuegos o en un router) todo el tráfico proveniente de los atacantes; pero >qué sucede
cuando tenemos miles de ordenadores atacando desde un gran número de redes
diferentes? >Los bloqueamos uno a uno? Esto supondría un gran esfuerzo que
difícilmente ayudaría, ya que lo más probable es que en el tiempo
que nos cueste bloquear el tráfico de una determinada máquina, dos o tres
nuevas nos comiencen a atacar. Entonces, >bloqueamos todo el tráfico dirigido
hacia el objetivo? Si hacemos esto, estamos justamente ayudando al atacante, ya
que somos nosotros mismos los que causamos una negación en el servicio a los
usuarios legítimos de nuestro sistema...
Como vemos, la defensa ante una negación de servicio distribuida no es
inmediata; en cualquier caso, podemos tomar ciertas medidas preventivas que nos
ayudarán a limitar el alcance de uno de estos ataques (y en general de las
negaciones de servicio remotas, distribuidas o no). De entrada, un correcto
filtrado del tráfico dirigido a nuestras máquinas es vital para garantizar
nuestra seguridad: no hay que responder a pings externos a nuestra red, es
necesario activar el antispoofing en nuestros cortafuegos y en los
elementos de electrónica de red que lo permitan, etc. Establecer
correctamente límites a la utilización de nuestros recursos, como ya
hemos visto, es también una importante medida preventiva; es posible limitar
el ancho de banda dedicado a una determinada aplicación o a un protocolo, de
forma que las utilizaciones por encima del margen son negadas. También
podemos limitar los recursos del sistema (CPU, memoria, disco...) que puede
consumir en global una determinada aplicación servidora (por ejemplo, un
demonio sirviendo páginas web), además de restringir sus recursos por
cliente simultáneo (en base, por ejemplo, a la dirección origen de ese
cliente).
A pesar de las dificultades con las que nos podemos encontrar a la hora de
prevenir ataques de negación de servicio, una serie de medidas sencillas
pueden ayudarnos de forma relativa en esa tarea; las negaciones de servicio son
por desgracia cada día más frecuentes, y ninguna organización está
a salvo de las mismas. Especialmente en los ataques distribuidos, la seguridad
de cualquier usuario conectado a Internet (aunque sea con un sencillo PC y un
módem) es un eslabón importante en la seguridad global de la red, ya que
esos usuarios se convierten muchas veces sin saberlo en satélites que
colaboran en un ataque masivo contra organizaciones de cualquier tipo. Cuanto
más difícil se lo pongamos cada uno de nosotros a los piratas, mucho
mejor para todos.
© 2002 Antonio Villalón Huerta