03 marzo 2008

Falsificación de timestamps

Recientemente tuve que hacer el análisis forense de un servidor de mi organización que había sufrido una intrusión.

El vector de entrada resultó evidente en cuanto pude cruzar unas cuantas palabras con el administrador de la máquina... una vez más, una enorme inversión en infraestructura de seguridad había sido anulada por un administrador que había pasado de nuestras recomendaciones y había utilizado una palabra de diccionario como contraseña. El ataque había sido de manual. Los logs anunciaban una fase de ataque de fuerza bruta, seguidas finalmente por "logueos" desde direcciones IP de otros países. Pronto localicé en un directorio oculto un paquete de herramientas de escaneo de redes y de ataques de fuerza bruta. Por los que pudimos ver no parecía que les hubiese dado tiempo a utilizar el servidor comprometido como puente hacia nuestra red.

Visto lo visto decidimos formatear la máquina, reinstalarla, parchearla, limitar al máximo los servicios que corría y asegurarnos de que el administrador ponía una contraseña solvente... sin contar con hacer un poco más exigentes los umbrales de nuestro IDS/IPS.

Nada se salía de la rutina... y eso fue lo que me hizo darle vueltas a la posibilidad de que todo aquello no hubiera sido más que un señuelo. Todo estaba tan claro desde que el administrador me había dicho su contraseña que cuando encontré la carpeta oculta e hice una búsqueda de timestamps "demasiado actuales" en el sistema (sin resultado) dí por cerrada la investigación (otras cosas urgían). El problema es que los "timestamps" o marcas temporales de modificación de los ficheros no son nada fiables. A pesar de eso, muchos programas de análisis forense como Autopsy/SleuthKit o Forensics Toolkit utilizan las marcas de tiempo de los ficheros para elaborar los llamados timelines que permiten seguir el rastro de modificaciones que va realizando el intruso. En el caso del ataque que me tocó investigar había un rastro de marcas de tiempo muy claro. Sin embargo, pensándolo en frío, aquel rastro denotaba o bien que el atacante era muy descuidado o que dejó una pista falsa para que la siguiese.

Al fin y al cabo, falsificar la marca de tiempo de un fichero no es nada difícil. Por ejemplo, si creamos un fichero, este tendrá como marca de tiempo la fecha y la hora de nuestro equipo en ese momento. Cada vez que modifiquemos el fichero la marca de tiempo se actualizará a la fecha y hora a la que se realice la modificación. Teniendo en cuenta que gran parte de los ficheros de un servidor permanecen sin modificarse largos periodos de tiempo sus marcas de tiempo suelen ser muy antiguas, por eso una modificación reciente por parte de un intruso suele llamar poderosamente la atención. Sin embargo, si el atacante es cuidadoso utilizará la orden touch para poner su antigua marca de tiempo a todos los archivos que vaya modificando. Veamos un ejemplo, supongamos que creamos un fichero de prueba:

dante@dante-desktop:~/pruebas$ echo prueba > test.txt dante@dante-desktop:~/pruebas$ ls -l test.txt -rw-r--r-- 1 dante dante 7 2008-03-01 06:18 test.txt

Tras unos minutos modificamos el fichero que acabamos de crear:

dante@dante-desktop:~/pruebas$ echo prueba2 >> test.txt dante@dante-desktop:~/pruebas$ ls -l test.txt -rw-r--r-- 1 dante dante 15 2008-03-01 06:22 test.txt

Como se puede ver, la marca de tiempo se ha actualizado.Si quisiéramos ocultar esta modificación falsificando la marca de tiempos no tendríamos más que usar el comando touch:

dante@dante-desktop:~/pruebas$ touch -t 03010618 test.txt dante@dante-desktop:~/pruebas$ ls -l test.txt -rw-r--r-- 1 dante dante 15 2008-03-01 06:18 test.txt

Esta funcionalidad es fácilmente integrable en scripts que permitan restaurar las marcas de tiempo de directorios enteros. Como demostración de ello desarrollé en su momento TSpoofer, una herramienta hecha en python que permite recopilar las marcas de tiempo de los ficheros y directorios que cuelguen del que definamos de tal manera que se puedan restablecer dichas marcas de tiempo tras realizar modificaciones los ficheros anulando con ello el rastro que captarían los timelines.

Queda demostrado que es muy fácil falsificar las marcas de tiempo de los ficheros anulando con ello la utilidad de los timelines de las herramientas forenses. Será necesario tenerlo muy presente a la hora de hacer estudios forenses: los timelines ayudan pero sólo con los atacantes menos cuidadosos.



Actualización del 19 de marzo de 2008--> Algo estupendo de la seguridad informática es que siempre se están aprendiendo cosas nuevas. En ese sentido he descubierto que utilizar un "ls -l" es sólo una manera muy superficial de comprobar el timestamp de modificación de un fichero, ya que sólo muestra el mtime del inodo. Me explico, los timestamps constan de 3 componentes: mtime, atime y ctime. El mtime marca la la fecha y hora de la última escritura en el fichero, atime la última lectura del fichero y ctime el último cambio del fichero. Hay que tener en cuenta una confusión muy habitual, en la que debo incluirme hasta hoy, por la cual muchos creen que ctime corresponde a creation-time cuando en realidad se refiere, al menos en linux, change-time. ¿Cual es la diferencia entre mtime y ctime? pues que ctime es un superconjunto de mtime, es decir, cuando mtime se actualiza lo hace ctime, pero hay veces en que ctime se actualiza pero mtime no. Eso ocurre en los casos en los que el fichero se actualiza pero no su contenido, por ejemplo al cambiar los permisos asociados al fichero.
Como demostración vamos a realizar las mismas pruebas de antes pero esta vez usando el comando find para visualizar los timestamps.

dante@dante-desktop:~/pruebas$ date mié mar 19 13:53:23 CET 2008 dante@dante-desktop:~/pruebas$ echo prueba > prueba.txt dante@dante-desktop:~/pruebas$ find ./ -printf "%m; %Ax;%AT; %Tx;%TT; %Cx;%CT; %U;%U;%G;%s;%p\n" | grep prueba.txt 644; 19/03/08;13:53:27; 19/03/08;13:53:27; 19/03/08;13:53:27; 1000;1000;1000;7;./prueba.txt
Gracias a find podemos visualizar el timestamp completo, la primera terna (fecha;hora) correspondería al atime, la segunda al mtime y la tercera al ctime.

dante@dante-desktop:~/pruebas$ echo prueba2 >> prueba.txt dante@dante-desktop:~/pruebas$ find ./ -printf "%m; %Ax;%AT; %Tx;%TT; %Cx;%CT; %U;%U;%G;%s;%p\n" | grep prueba.txt 644; 19/03/08;13:53:27; 19/03/08;14:00:14; 19/03/08;14:00:14; 1000;1000;1000;15;./prueba.txt

Se puede ver que el atime sigue igual ya que no he leido el fichero sino que he introducido datos en él, pero tanto el mtime como el atime se ha actualizado al escribir en el fichero.

dante@dante-desktop:~/pruebas$ chmod 666 ./prueba.txt dante@dante-desktop:~/pruebas$ find ./ -printf "%m; %Ax;%AT; %Tx;%TT; %Cx;%CT; %U;%U;%G;%s;%p\n" | grep prueba.txt 666; 19/03/08;13:53:27; 19/03/08;14:00:14; 19/03/08;14:08:05; 1000;1000;1000;15;./prueba.txt

Esta prueba demuestra la diferencia entre mtime y ctime. Hemos cambiado el fichero al alterar sus permisos, lo que queda grabado en el ctime, pero como dicho cambio no suponía escribir datos en el fichero el mtime sigue igual. De ahí la diferencia de 8 segundos que aparece entre el mtime y el ctime.

Queda ver qué pasará al usar el comando touch.

dante@dante-desktop:~/pruebas$ echo prueba3 >> prueba.txt dante@dante-desktop:~/pruebas$ find ./ -printf "%m; %Ax;%AT; %Tx;%TT; %Cx;%CT; %U;%U;%G;%s;%p\n" | grep prueba.txt 666; 19/03/08;13:53:27; 19/03/08;14:14:56; 19/03/08;14:14:56; 1000;1000;1000;23;./prueba.txt dante@dante-desktop:~/pruebas$touch -t 03081400.14 ./prueba.txt dante@dante-desktop:~/pruebas$ find ./ -printf "%m; %Ax;%AT; %Tx;%TT; %Cx;%CT; %U;%U;%G;%s;%p\n" | grep prueba.txt 666; 08/03/08;14:00:14; 08/03/08;14:00:14; 19/03/08;14:18:43; 1000;1000;1000;23;./prueba.txt

Parece que "touch -t" modifica tanto el atime, como el mtime, para corregir el atime se usa "touch -a -t".

dante@dante-desktop:~/pruebas$ touch -a -t 03081353.27 ./prueba.txt dante@dante-desktop:~/pruebas$ find ./ -printf "%m; %Ax;%AT; %Tx;%TT; %Cx;%CT; %U;%U;%G;%s;%p\n" | grep prueba.txt 666; 08/03/08;13:53:27; 08/03/08;14:00:14; 19/03/08;14:21:00; 1000;1000;1000;23;./prueba.txt dante@dante-desktop:~/pruebas$ ls -l ./prueba.txt -rw-rw-rw- 1 dante dante 23 2008-03-08 14:00 ./prueba.txt

El problema es que touch no cuenta con ninguna posibilidad para modificar el ctime. Usando esta herramienta un intruso puede engañar a un administrador que se limitase a examinar su sistema de ficheros con un "ls -l" pero no a uno más concienzudo que utilizase find o un "ls -l --time=ctime".

¿Debemos cantar victoria?... aún no. Si bien un intruso no podría contar con touch para borrar sus huellas sí que podría usar una herramienta de bajo nivel llamada debugfs (para sistemas ext2/ext3, para sistemas reiser tenemos debugfs.reiser4) para modificar el ctime del fichero. Esta herramienta requiere de privilegios de superusuario, es muy delicada ya que un fallo puede corromper la tabla de ficheros, resulta más difícil de integrar en un script y por lo que he podido ver, necesita que se reinicie el sistema para que se muestren los cambios si estos se realizan sobre un sistema de ficheros vivo. Su uso sería el siguiente:

dante@dante-desktop:~/pruebas$ ls -li total 28 96984 -rw-rw-rw- 1 dante dante 23 2008-03-08 14:00 prueba.txt dante@dante-desktop:~/pruebas$ sudo debugfs -w /dev/sda1 debugfs 1.40.2 (12-Jul-2007) debugfs: mi <96984> Mode [0100666] User ID [1000] Group ID [1000] Size [23] Creation time [1205932874] 1204981214 Modification time [1204981214] Access time [1204980807] Deletion time [0] Link count [1] Block count high [0] Block count [8] File flags [0x0] Generation [0x4091865b] File acl [0] High 32bits of size [0] Fragment address [0] Direct Block #0 [204803] Direct Block #1 [0] Direct Block #2 [0] Direct Block #3 [0] Direct Block #4 [0] Direct Block #5 [0] Direct Block #6 [0] Direct Block #7 [0] Direct Block #8 [0] Direct Block #9 [0] Direct Block #10 [0] Direct Block #11 [0] Indirect Block [0] Double Indirect Block [0] Triple Indirect Block [0] debugfs: debugfs: close debugfs: quit dante@dante-desktop:~/pruebas$ find ./ -printf "%m; %Ax;%AT; %Tx;%TT; %Cx;%CT; %U;%U;%G;%s;%p\n" | grep prueba.txt 666; 08/03/08;13:53:27; 08/03/08;14:00:14; 19/03/08;14:21:00; 1000;1000;1000;23;./prueba.txt dante@dante-desktop:~/pruebas$ sudo shutdown -r now Emitir mensajes desde dante@dante-desktop (/dev/pts/0) en 17:10 ... ¡El sistema se va a apagar por reboot AHORA! (...) dante@dante-desktop:~/pruebas$ find ./ -printf "%m; %Ax;%AT; %Tx;%TT; %Cx;%CT; %U;%U;%G;%s;%p\n" | grep prueba.txt 666; 08/03/08;13:53:27; 08/03/08;14:00:14; 08/03/08;14:00:14; 1000;1000;1000;23;./prueba.txt

Resulta notable que una herramienta como debugfs confunde también el sentido de ctime y pregunta por el "Creation time", pero como ya se ha mencionado se trata de un error muy común (piense en qué sentido tendría un creation-time que cambiase con cada modificación del fichero). De todos modos, como se puede ver, ahora sí que se ha modificado el valor del ctime borrando por completo el rastro dejado en los timestamps...