Negaciones de servicio

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