jueves, 29 de octubre de 2009

Bombas fork: Detección y prevención

Las bombas fork en GNU/Linux utilizan la implementación de funciones que ofrece Bash para consumir recursos del sistema hasta llegar al punto de dejarlo totalmente inestable y tumbarlo.

La idea es muy sencilla: se trata de definir una función recursiva y llamarla una vez, esto provocará que se llame a sí misma infinitamente. La clave está en que cada vez que se llama a sí mismo en background, hace una llamada a fork(). fork() es una función usada en programación que sirve para crear procesos hijo a partir de un proceso padre. Si juntamos todo esto tendremos un proceso padre que va generando procesos hijos, que a su vez van dando nietos al abuelo, y así hasta dejar el sistema sin memoria y colgarlo.

Vamos a la función en cuestión:

funcion()
{
    funcion | funcion &
}


Ahora ya está definida, en el momento que se llame es cuando viene el problema. Normalmente se ofuscan un poco dándoles como nombre cualquier carácter, y se definen y se llaman en una sola línea. Así si en vez de llamarle funcion la definimos como :  y le añadimos el punto y coma de salto de línea para llamarla después, tendremos la siguiente línea:

:(){:|:&};:

Detección


Las bombas fork cuelgan el sistema hasta tal punto que no queda registrada esta línea en el .bas_history del usuario y el administrador del sistema no podrá detectarlas. Esto es debido a que este fichero se escribe al hacer el logout de la sesión bash.


Podemos cambiar el comportamiento para que se escriba en el histórico después de cada comando, sin esperar a que se cierre la sesión, utilizando la variable PROMPT_COMMAND:

readonly PROMPT_COMMAND="history -a"

Ahora en el caso que una bomba fork cuelgue el sistema, quedará registrado en el histórico.
Pero como todos sabemos que estos históricos se pueden manipular, incluso saltarse la variable PROMPT_COMMAND, vamos a prevenir antes que tener que curar.

Prevención


Podemos prevenir que un usuario utilize una bomba limitando el número de procesos que puede tener abierto, así la función solamente se podrá llamar así mismo determinadas veces.
Para hacerlo tendremos que editar el fichero /etc/security/limits.conf, y por ejemplo limitar a 1000 procesos a todos los usuarios.

*   hard nproc  1000

Para comprobar si nuestro usuario tiene definido un límite lanzaremos desde un terminal:

ulimit -u

No hay comentarios: