miércoles, 26 de octubre de 2011

Agujeros de seguridad Parte 2

Creo que esto se debe de dividir en categorias generales:
  1. Principios generales
  2. Buscar agujeros en src
  3. Buscar en las distribuciones binarias
  4. Buscar en configuraciones especificas de sites.
Las siguientes clasificaciones generales sugieren por si mismas:
  1. SUID/SGID
  2. Return codes/error conditions
  3. unexpected input
  4. race conditions
  5. authentication
  6. implicit trust
  7. parameters
  8. permissions
  9. interrupts
  10. I/O
  11. symbolic links
  12. Daemons, particularly those taking user input.
  13. Kernel race conditions
  14. what else? - please add categories
(Division sugerida de lo de arriba en sub-categorias)
I: Suid binaries and scripts
  • unexpected user interactions
  • flawed liberary calls
  • implicit assumptions of external conditions (sym links, loc. paths)
  • race conditions
II: daemons running with priviliged uid's
  • race conditions
  • poor file protectons
  • implicit file protections
  • trust
  • authentication
III: Kernel problems
  • Kernel race conditions
  • device driver code
El siguiente metodo de 4 pasos fue creado por System Development Corporation, que da un indice de 65% de éxito en las hipotesis generadas. El hacer una busqueda detallada de imperfecciones en los sistemas operativos requiere 4 pasos:
Paso 1 Conocimiento de la estructura de control del sistema

Para encontrar agujeros de seguridad, e identificar debilidades de diseño es necesario entender la estructura de control del sistema, y las capas. Uno deberia ser capaz de listar:
  • objetos de seguridad: componentes que deben ser protegidos. Ej: un archivo de usuario
  • objetos de control: componentes que protegen objetos de seguridad. Ej: un i-node
  • objetos reciprocos: objetos de ambas clases. Ej: el archivo de password.
Con dicha lista, es posible el representar graficamente una jerarquia de control e identificar puntos potenciales de ataque. Hacer diagramas de flujo para dar un analisis visual de relaciones definitivamente ayuda. El leer los varios manuales de usuario, operadores, y administradores proveera dicha informacion.
Paso 2 Generar un inventario de desperfectos sospechosos
En particular queremos:
Historia de codigo:
De que UNIX deriva un defecto en particular? Esto es importante para proximas referencias (muy a menudo solo un vendedor parchea partes del codigo, que sera usado por otros en su "reencarnacion" sin parchear.Una referencia solida: Quien chequea que bugs hay, en que sistema operativo y en que versiones, nos previene de realizar una doble tarea.
Un buen comienzo seria el listar todos los binarios suid de las diferentes versiones de los sistemas operativos. Despues intentar averiguar por que cada programa es suid ej: rcp es suid root ya que debe usar un puerto privilegiado para autentificar nombres de usuario.A menudo, codigo que nunca fue diseñado para ser suid, se hace suid, para resolver problemas de acceso a ficheros. Necesitamos crear una base de datos que sea capaz de "mirar" a pares y trios de datos, especificamente:nombre del programa, suid, sgid, objeto accedido (por que es suid/sgid), version del sistema operativo. Alguna sugerencia de como implementar dicha base de datos

Paso 3 Confirmar hipotesis (testear y explotar los defectos)

Paso 4 Hacer generalizaciones de las debilidades del sistema, para las que los defectos representan un ejemplo especifico

Caja de herramientas
AGREP: Recomiendo a todo el mundo pillar e instalar agrep de: ftp cs.arizona.edu /agrep/agrep.tar.Z Agrep soporta "windowing" por lo que puede busacr rutinas, y subrutinas. Tambien soporta operadores logicos y es de esta forma ideal para automatizar la busqueda de muchos de estos defectos. Ej: agrep WINDOW {suid() NOT taintperl()} /usr/local/*.pl or agrep WINDOW {[suid() OR sgid()] AND [system() OR popen() OR execlp() OR execvp()]} /usr/local/src/*.c
PROGRAMA DE PERMUTACION: Otra herramienta que merece producir es un programa que genere todas las permutaciones posibles de los argumentos de la linea de comandos para asi descubrir caracteristicas indocumentadas, y tratar de producir errores.
TCOV:
CRASH: Posteado a USENET (que archivo FTP?)(descripcion?)
TEXTOS: Hay varios textos que tratan metodos sobre como encontrar defectos, y presentan series de tests

  1. Un estudio empirico de la seguridad de las utilidades UNIX, por Barton P. Miller, Lars Fredriksen, and Bryan So, Comm ACM, v33 n12, pp32-44,Diciembre 90. Describe una serie de tests para testear cadenas aleatorias de entradas. Los resultados indicaban que un 25% de los programas se colgaban, se venian abajo, o no actuaban como debian. En un caso el sistema operativo se vino abajo. El entendimiento de la composicion del buffer y el registro en el ambiente en cuestion, y la entrada esperada se entiende que dara los resultados esperados.
  2. El conjunto de herramientas Mothra, in Proceedings of the 22nd Hawaii International Conference on Systems and Software, pages 275-284, Kona, HI, January '89
  3. Extending Mutation Testing to Find Environmental Bugs, by Eugene H.Spafford, Software Practice and Experience, 20(2):181-189, Feb '90
  4. A paper by IBM was mentioned that was submitted to USENIX a few years ago. (Anyone have a citation?).
Defectos especificos que chequear
  1. Buscar rutinas que no hagan chequeos al limite, o verifiquen entradas. Ej:la familia de rutinas gets(), donde es posible sobreescribir el limite del buffer (sprintf()?, gets(), etc.)tambien: strcpy()
  2. Las rutinas SUID/SGID escritas en uno de los shells, en vez de C o PERL
  3. Las rutinas SUID/SGID escritas en PERL que no usan el programa "taintperl"
  4. Las rutinas SUID/SGID que usan las llamadas system(),popen(), execlp(), o execvp() para ejecutar otra cosa.
  5. Cualquier programa que use nombres relativos de ruta (path) dentro del programa
  6. El uso de nombres relativos de ruta para especificar librerias vinculadas dinamicamente.
  7. Rutinas que no chequean codigos de error devueltos por llamadas del sistema (Ej: fork(2), suid(2),setuid(), como en el famoso bug rcp)
  8. Los agujeros se pueden encontrar a menudo en codigo que:
    • es portado a un nuevo entorno
    • recibe entradas inesperadas
    • interactua con otro software local
    • accede a archivos de sistema como passwd, L.sys, etc
    • lee entradas de directorios o archivos publicos escribibles
    • programas de diagnostico que tipicamente no estan a prueba de usuarios
  9. Testear codigo para entradas inesperadas. Hay disponibles herramientas de testeo de proteccion, flujo de datos, y muacion.
  10. Buscar en los textos man, y guias de usuario las advertencias en contra de las X, y tratar variaciones de X. Hacer lo mismo con la seccion de bugs.
  11. Buscar comandos o funciones raramente usados o inusuales. En particular seria util buscar argumentos indocumentados. Buscar flags de distribuciones anteriores, o en versiones de otros sistemas operativos. Chequear las opciones que otros programas podrian usar. Por ejemplo, Telnet usa la opcion -h para conectarse...
  12. Buscar condiciones raciales.
  13. Fallos del software para verificar que realmente esta comunicandose con el software o modulo de hardware al que quiere acceder.
  14. Falta de deteccion de errores para resetear los mecanismos de proteccion siguientes al error.
  15. Implementacion pobre que da como resultado, por ejemplo, codigos de condicion testeados inapropiadamente
  16. Confianza inplicita: La rutina B asume que los parametros de la rutina A son correctos por que la rutina A es un proceso de sistema
  17. El sistema almacena sus datos o referencia parametros de usuario en el espacio disponible de las direcciones de usuarios
  18. Enterrar procesos de comunicación: condiciones de retorno (passwd OK, illegal parameter, segment error, etc) pueden proporcionar una brecha significativa cuando son combiandos con el paso 17
  19. Los parametros de usuario pueden no estar adecuadamente chequeados.
  20. Direcciones que sobrepasan o se refieren a areas del sistema
  21. Las comprobaciones de condicion de codigo pueden omitirse
  22. Fallo al anticiparse a parametros inusuales o extraordinarios
  23. Buscar niveles del sistema donde los modulos alli involucrados fueron escritos por programadores diferentes, o grupo de programadores - se suelen encontrar agujeros.
  24. Registros que apuntan a la localizacion de valores de parametros en vez de pasar el parametro el mismo.
  25. Cualquier programa ejecutandose con privilegios de sistema (a muchos programas se les da UID 0, para facilitar el acceso a ciertas tablas, etc)
  26. Archivos temporales, buffers leibles por grupos o por todo el mundo
  27. Carencia de valores de "umbral", y carencia de notificacion una vez se han accionado estos.
  28. Cambiar parametros de areas criticas del sistema antes de su ejecucion.
  29. Comprobacion inadecuada de los limites al compilar, por ejemplo, un usuario puede ser capaz de ejecutar codigo maquina disfrazado como datos en un area de datos (si las areas de texto y datos estan compartidas)
  30. Manipular incorrectamente interrupciones asincronas generadas por usuarios. Usuarios interrumpiendo un proceso, realizando una operación, o bien volviendo para continuar el proceso o comenzar otro dejaran a menudo el sistema en un estado de desproteccion. Archivos parcialmente escritos se dejan abiertos, escritura incorrecta de mensajes de infracciones de proteccion, puesta incorrecta de bits de proteccion, etc, suelen ocurrir.
  31. Codigo que usa fopen(3) sin poner la umask. (ej: at(1), etc.). En general, codigo que no resetea el UID real y efectivo antes de bifurcarse
  32. Tracear es muy util para ayudarte a descubrir que llamadas de sistema usa un programa
  33. Escanea los sistemas de archivos /usr/local de cerca. Muchos administradores instalaran software de la red. A menudo encontraras tcpdump, top, nfswatch,... suid root por su facilidad de uso.
  34. Comprobar que los programas suid fueron los que originalmente se pusieron en el sistema. Algunas veces los administradores reemplazaran el password por uno menos seguro que el de las distribuciones.
  35. Buscar programas que se usaran para instalar software o modulos de kernel
  36. Programas enlazados dinamicamente en general. Recuerda LD_PRELOAD, creo que esa era la variable.
  37. La programacion de canales de I/O (Entrada/Salida) es es un blanco primario. Busca errores logicos, inconsistencias, y omisiones.
  38. Ver si es posible que un programa de canales I/O pueda automodificarse, hacer un loop, y asi ejecutar el nuevo codigo modificado.
  39. Si los canales I/O actuan como procesadores independientes tendran acceso ilimitado a la memoria, y asi el codigo de sistema podria ser modificado en memoria previamene a su ejecucion.
  40. Buscar bugs que requieran errores en multiples partes del software,ej: di por ejemplo que el programa "a" puede usarse para cambiar el fichero de configuracion /etc/a , ahora el programa "b" asume que la informacion de a es correcta y esto lleva a resultados inesperados (solo mira cuantos programas confian en el fichero /etc/utmp)
  41. Cualquier programa, especialmente los suid/sgid, que permites "escapadas" a shell.

0 comentarios:

Publicar un comentario