Cómo hacer que los ataques de inyección de bytes nulos funcionen con PHP 5.2.17

1

Estoy tratando de entender cómo los ataques de inyección de bytes nulos en el código PHP solían funcionar antes de ser parcheados en PHP 5.3.4. Tengo una página HTML de muestra que es una versión algo modificada de lo que se muestra aquí :

<?php
var_dump($_GET);
echo '<br>';
$file = $_GET['file'];
$path = '/var/www/' . $file . '.php';
echo $path;
if (file_exists($path)) {
    echo "file exists!";
    include $path;
}
?>

Este código se ejecuta en un sistema Ubuntu 12.04 que ejecuta PHP 5.2.17. Espero que una URL como http://localhost/?file=../../../etc/passwd%00 funcione, pero en cambio veo %code% impreso literalmente en la cadena:

array(1) { ["file"]=> string(21) "../../../etc/passwd
<?php
var_dump($_GET);
echo '<br>';
$file = $_GET['file'];
$path = '/var/www/' . $file . '.php';
echo $path;
if (file_exists($path)) {
    echo "file exists!";
    include $path;
}
?>
" } /var/www/../../../etc/passwd
array(1) { ["file"]=> string(21) "../../../etc/passwd%pre%" }
/var/www/../../../etc/passwd%pre%.php
.php

¿Qué estoy haciendo mal? ¿Cómo puedo hacer que los ataques de inyección de bytes nulos funcionen en mi máquina local?

    
pregunta gsingh2011 29.08.2014 - 18:20
fuente

1 respuesta

1

La salida de eco con el /var/www/../../../etc/passwd/var/www/../../../etc/passwd.php incluido se supone que debe suceder, nada de que preocuparse. Para comprender el ataque, debes saber cómo C y PHP almacenan las cadenas.

C

En C, una cadena es simplemente un puntero a una dirección de memoria donde el puntero apunta al comienzo de la cadena, y el carácter %code% indica el final. No se almacena ninguna longitud, todo el código que lee cadenas se lee hasta que se alcanza el carácter %code% . Una cadena C puede ser todo el tiempo que quiera.

PHP

En PHP, una cadena consta de dos partes: un entero y una matriz. El número entero denota la longitud de la cadena y la matriz, la matriz contiene la cadena en sí. Todo el código de manejo de cadenas en PHP lee ese número entero y sabe cuánto tiempo dura la cadena. Ignora el carácter %code% . El número entero tiene un límite superior, al igual que el length de la cadena .

El ataque

El ataque se basa en este diferente manejo de cadenas. Entonces, como puede incluir un carácter %code% en la cadena de PHP, la impresión de la cadena incluirá el carácter %code% . Así que tu salida será %code% . La magia sucede en el momento en que PHP le da esa cadena a C: C interpreta el carácter %code% como terminación de cadena y cree que obtuvo %code% . Y este archivo, por supuesto, existe.

La solución

De las notas de la versión :

  

Las rutas con NULL en ellas (foo \ 0bar.txt) ahora se consideran inválidas. (Rasmus)

La corrección consiste principalmente en agregar cláusulas if, comparar la longitud de la cadena con el método c ( izquierda) y el método php (derecha):

if (strlen(Z_STRVAL_PP(file)) != Z_STRLEN_PP(file)) {
    RETURN_FALSE;
}
    
respondido por el user10008 29.08.2014 - 19:28
fuente

Lea otras preguntas en las etiquetas