Categories
PHP Quiz Seguridad Web WordPress

PHP: Uso adecuado de parse_str

La siguiente porción de código es una práctica muy extendida en WordPress, sirve para que las funciones puedan tener un buen número de parámetros opcionales sin que el código sea visualmente feo:

php:

<?php
/* Funciones de WordPress */
function stripslashes_deep($value) {
         $value = is_array($value) ?
                 array_map('stripslashes_deep', $value) :
                 stripslashes($value);

         return $value;
}
function wp_parse_str( $string, &$array ) {
        parse_str( $string, $array );
        if ( get_magic_quotes_gpc() )
                $array = stripslashes_deep( $array );
        return $array;
}
/* Fin */

function get_posts( $args = '' ) {
        $defaults = array(
                'limit' => 5,
                'post_type' => ''
        );
        $args = wp_parse_str($args, $defaults);
       
        extract($args, EXTR_SKIP);
       
        $where = '';
        if ( !empty($post_type) )

                $where = "WHERE post_type = '$post_type'";

       
        $sql = "SELECT * FROM posts $where LIMIT $limit";
        // ejecutar la consulta en una base de datos MySQL
        echo htmlspecialchars($sql);
}

$limit = empty($_GET['limit']) ? 5 : (int) $_GET['limit'];

if (get_magic_quotes_gpc())
        $_GET['type'] = stripslashes($_GET['type']);
// Se usa addslashes sólo para el ejemplo.
// $type = mysql_real_escape_string($_GET['type']);
$type = addslashes($_GET['type']);
get_posts("limit=$limit&post_type=$type");
?>

Sobre el ejemplo mostrado:

  1. ¿Tiene algún problema de seguridad?
  2. ¿Qué pasa si cambiamos la línea resaltada por esta otra, tiene algún problema de seguridad?
    php:

    $where = "WHERE post_type = '". addslashes($post_type) . "'";

Para los interesados en este pequeño quiz, subí una página en la que pueden realizar sus pruebas.

Categories
.NET ASP.NET Miniposts PHP Seguridad Sql Injection Web XSS

Versión estable de PHPIDS (Intrusion Detection System)

Hoy acaban de anunciar que ya existe un versión estable de PHPIDS, un sistema de detección de intrusos basado en expresiones regulares. Pueden descargar el código desde el repositorio o hacer pruebas para ver como funciona esta pequeña librería.

Por otro lado, también existe .NETIDS, que es una versión en .NET -- realizada por Martin Hinks -- de PHPIDS.

Categories
CSRF PHP Seguridad Sql Injection Web XSS

PHP IDS (Intrusion Detection System)

Mario.Heiderich y Christian vienen desarrollando un sistema de detección de intrusos en PHP 5, el cual funciona en base a un conjunto de filtros definidos en un archivo XML, que detectan posibles parámetros peligrosos en las peticiones que se hacen sobre un servidor web.

xml:

<?xml version="1.0" encoding="iso-8859-1" ?>

<filters>
        <filter>
                <rule><![CDATA[(@import|;base64|alert[\s]?\(|expression[\s]?\(|urn[\s]?\(|fromCharcode[\s]?\(|decodeURIComponent[\s]?\(|eval[\s]?\(|Execute[\s]?\()]]></rule>
                <description>detects imported poisoned stylesheets, base64 attacks, vbscript probings and typical js injections</description>
        <tags>
                        <tag>xss</tag>
                        <tag>csrf</tag>
                        <tag>id</tag>
                        <tag>rfe</tag>
                </tags>
        <impact>4</impact>
        </filter>   
        <filter>
                <rule><![CDATA[(SELECT|INSERT|CREATE|DELETE|FROM|WHERE|LIKE|EXEC|SP_|XP_|SQL|ROWSET|OPEN|BEGIN|END|DECLARE|UNION|NULL)]]></rule>
                <description>detects common sql keywords</description>
        <tags>
                        <tag>sqli</tag>
            <tag>id</tag>
                </tags>
        <impact>2</impact>
        </filter>   
</filters>

El modo de uso es el siguiente:

php:

<?php
/**
 *      Cargar las clases
 */

require_once './phpids/ids.php';
require_once './phpids/storage.php';

try {
        /**
         *      Cargar los filtros por omisión distribuidos en el código fuente
         */

        $storage = new Filter_Storage();
        $storage->getFilterFromXML('./phpids/default_filter.xml');

        /**
         *      Instanciar el IDS y empezar a buscar elementos sospechosos
         *
         */

        $get = new IDS_Monitor($_GET, $storage); // $_POST, $_REQUEST, etc
        $result = $get->run();
       
        /**
         *      Mostrar los resultados en el navegador
         *
         * (Lo ideal sería enviar el resultado a otro archivo)
         */

        header('Content-type: text/plain; charset=utf-8');
        print_r($result);
} catch (Exception $e) {
        printf(
                'An error occured: %s',
                $e->getMessage()
        );
}
?>

En las pocas pruebas que hice, pude notar que en algunos casos se pueden saltar los filtros que vienen por omisión, por otro lado también se reportan muchos falsos positivos en cadenas de caracteres totalmente inofensivas -- en mi opinión, es consecuencia del uso de expresiones regulares.

Más allá de las limitaciones (y posibles problemas de rendimiento) que pueda tener, es una alternativa para aquellos servidores donde no está instalado mod_security.

Categories
PHP Seguridad Web

PHP: 20 aplicaciones más vulnerables

Ed Finkler, en base a los datos de National Vulnerability Database, publicó una lista de las 20 aplicaciones -desarrolladas en PHP- que más vulnerabilidades tuvieron en el periodo Abril de 2006 - Abril de 2007

20 aplicaciones más vulnerables en PHP

Tal como se comenta en el artículo original, WordPress empezó mal este año y es por eso que está dentro de las cinco aplicaciones más vulnerables para el periodo seleccionado.

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.