Categories
Expresiones Regulares PHP Seguridad XSS

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.

Categories
Desarrollo de Software Miniposts Seguridad

Why Security Testing is Hard

Interesante artículo publicado en un journal de IEEE (Julio-Agosto de 2004) donde Martin Stytz y James Whittaker explican la razón de porque los fallos de seguridad son más difíciles de encontrar que los fallos funcionales.

Pueden descargar este artículo de manera gratuita desde http://tinyurl.com/2jrmph (PDF, 81.3 KB)

Categories
Seguridad Web WordPress

WordPress 2.0.10 y 2.1.3

A estas alturas del día, seguramente ya están al tanto de que el equipo de WordPress anunció la liberación de las versiones 2.0.10 y 2.1.3 de este CMS. Los problemas de seguridad que corrigen estas versiones son (se reportaron unos cuantos problemas más pero no tienen un ticket correspondiente para ponerlo):

Lo que me preocupa de estas nuevas versiones, es que todavía siguen incluyendo la versión vulnerable a XSS del plugin akismet.

Categories
Seguridad Web WordPress XSS

Problemas de seguridad con WordPress 2.x y el plugin pagebar

Debido a unos cambios hechos en la función get_pagenum_link de las ramas 2.0 y 2.1 de WordPress, varios blogs que usan el plugin pagebar son vulnerables a XSS.

Si alguno de ustedes usa el mencionado plugin y se muestra algún mensaje con la siguientes direcciones URL, entonces necesitan modificar ciertas cosas:

code:

http://tublog.com/index.php?"><script>alert(/XSS/)</script><&paged=2
http://tublog.com/index.php/"><script>alert(/XSS/)</script><&paged=2

Para corregir el problema descrito en el plugin pagebar, tienen que escapar el valor devuelto por get_pagenum_link con las funciones attribute_escape o clean_url. Por si alguien desea, puede bajar la versión modificada o aplicar el parche que corrige estos problemas.

Categories
PHP Seguridad Sql Injection Web

Ejercicio de fin de Semana: Evitar SQL Injection con PHP

A través de tweako (visto hace algunos minutos en menéame) llegué a un artículo -en inglés- que explica como protegerse de ataques de Inyección de SQL con PHP. En el mencionado artículo, en la última parte aparecen las siguientes dos porciones de código:

php:

<?php

# Ok, so I'm going to oversecure a query to the database that selects an article
# by using the given article ID.
# Here is the code.

//Database connection is present
//Make sure that the id is actually given

if (isset($_GET['id']))
{
        $id = $_GET['id'];
}
else
{
        die('Please provide an article ID');
}
 
//Make sure that its an integer
if (is_integer($id))
{
        die('Please enter a valid article ID');
}
 
//Validate that its in between the ranges 1 and 10,000
if ($id < 1 || $id > 10000)
{
        die('Please enter a valid artile ID');
}
 
//Construct the query
$SQL = "SELECT * FROM posts WHERE postID = '".$id."'";

echo $SQL; // Línea agregada

?>

php:

<?php

# This next one will validate a username before its entered into the database.

//Database connection is present
//Make sure that the id is actually given
if (isset($_GET['username']))
{
        $username = $_GET['username'];
}
else
{
        die('Please provide a username');
}
//Get the length of the username
$length = strlen($username);
//Validate the length
if ($length < 3 || $length > 20) // parte modificada
{
        die('Please enter a username between 3 and 20 characters long');
}
//Make sure that its safe to enter the database.
$username = mysql_real_escape_string($username);
//Construct the query
$SQL = "SELECT * FROM username WHERE username = '".$username."'";
//Show the username
echo 'Username: '.stripslashes($username);
//Send the query and close the connection to the database

?>

Los códigos mostrados ¿son correctos? si no es así, ¿qué errores tiene?.