PHP: Uso adecuado de expresiones regulares

Actualización 17/04/2007: Al parecer el problema descrito ya no es válido en versiones recientes de PHP.

PHP incluye el soporte para expresiones regulares usando una sintáxis compatible con Perl (preg_match, preg_replace, preg_split, etc) y también las expresiones con sintáxis POSIX extendido (ereg, eregi, ereg_replace, eregi_replace, etc).

En esta oportunidad no hablaré de los problemas derivados del abuso o uso inadecuado de las expresiones regulares, sino un problema más específico para aquellos que usan las funciones POSIX-extendido de PHP, sobre el cual existe la siguiente advertencia en el manual de PHP:

Estas expresiones regulares no son seguras con material binario. Las Funciones PCRE lo son.

Bien, veamos un ejemplo en el que por usar este tipo de funciones, una aplicación puede llegar a sufrir problemas de XSS o Inyección de SQL (si es que sólo se usa este tipo de cosas para validar los parámetros):

php:
<?php
// re.php

header('Content-type: text/html; charset=utf-8');

if ( eregi('^[a-z0-9]{4}$', $_GET['key']) ) {
        echo $_GET['key'];
} else {
        echo 'Caracteres no válidos';
}

// ...
?>

La expresión regular definida para validar el parámetro key supuestamente debería considerar sólo aquellos valores constituidos por cuatro letras y/o números, pero debido a que éstas funciones no son seguras con material binario, es posible saltar fácilmente esa validación añadiendo el caracter \0 (fin de cadena en C/C++).

Por ejemplo, para el siguiente valor de key:

php:
<?php

header('Content-type: text/html; charset=utf-8');

$_GET['key'] = 'test' . chr(0) . '<script>alert("Texto no tomado en cuenta")</script>';

if ( eregi('^[a-z0-9]{4}$', $_GET['key']) ) {
        echo $_GET['key'];
} else {
        echo 'Caracteres no válidos';
}

// ...
?>

Se mostrará en el navegador lo siguiente:

code:
test?<script>alert("Texto no tomado en cuenta")</script>

Para conseguir este mismo resultado desde el navegador, sólo basta usar %00 en la URL para representar el caracter \0: key=test%00<foo>.

Si están usando este tipo de funciones, ya están advertidos de los problemas que podrían tener si se les olvida la recomendación del manual de PHP.

4 Replies to “PHP: Uso adecuado de expresiones regulares”

  1. Hola alex, ¿has conseguido realizar el null byte injection? He probado varias cosas, con tu código, con el mío, con el de php.net , con parámetros GET y POST, y con diversos navegadores pero no lo he conseguido.

  2. Si, hice las pruebas con PHP 4.4.2; pero al parecer en versiones recientes de PHP corrigieron este problema para esas funciones (lo que me extraña es que no hayan actualizado la documentación).

Comments are closed.