Categories
Seguridad Web WordPress XSS

Nueva vulnerabilidad de WordPress

Héctor comentaba sobre la liberación de una nueva versión de wordpress que corregía un bug presente en las ramas 2.0 y 2.1 de este CMS.

Este error se presenta en la función wp_nonce_ays (archivo wp-includes/functions.php), porque la variable $action no está correctamente validada y en algunos casos, ésta puede ser modificada por el cliente. Por ejemplo http://vulnerable.com/wp-admin/plugins.php?action=activate&plugin=<script>alert(/XSS/)<script> es un posible vector de ataque.

php:

function wp_nonce_ays($action) {
        global $pagenow, $menu, $submenu, $parent_file, $submenu_file;

        $adminurl = get_option('siteurl') . '/wp-admin';
        if ( wp_get_referer() )
                $adminurl = wp_get_referer();

        $title = __('WordPress Confirmation');
        // Remove extra layer of slashes.
        $_POST   = stripslashes_deep($_POST  );
        if ( $_POST ) {
                $q = http_build_query($_POST);
                $q = explode( ini_get('arg_separator.output'), $q);
                $html .= "\t<form method='post' action='$pagenow'>\n";
                foreach ( (array) $q as $a ) {
                        $v = substr(strstr($a, '='), 1);
                        $k = substr($a, 0, -(strlen($v)+1));
                        $html .= "\t\t<input type='hidden' name='" . attribute_escape(urldecode($k)) . "' value='" . attribute_escape(urldecode($v)) . "' />\n";
                }
                $html .= "\t\t<input type='hidden' name='_wpnonce' value='" . wp_create_nonce($action) . "' />\n";
X              $html .= "\t\t<div id='message' class='confirm fade'>\n\t\t<p>" . wp_explain_nonce($action) . "</p>\n\t\t<p><a href='$adminurl'>" . __('No') . "</a> <input type='submit' value='" . __('Yes') . "' /></p>\n\t\t</div>\n\t</form>\n";
        } else {
X              $html .= "\t<div id='message' class='confirm fade'>\n\t<p>" . wp_explain_nonce($action) . "</p>\n\t<p><a href='$adminurl'>" . __('No') . "</a> <a href='" . add_query_arg( '_wpnonce', wp_create_nonce($action), $_SERVER['REQUEST_URI'] ) . "'>" . __('Yes') . "</a></p>\n\t</div>\n";
        }
        $html .= "</body>\n</html>";
        wp_die($html, $title);
}

Para corregir este fallo, simplemente hay que aplicar la función wp_specialchars sobre la salida de wp_explain_nonce en las línes marcadas con X:

php:

wp_specialchars(wp_explain_nonce($action));

Aprovechando este suceso, finalmente actualicé el blog a la versión 2.1 de WordPress e instalé el plugin wp-cache; si notan algún error, les estaré muy agradecido si me lo hacen saber.

Categories
Desarrollo de Software Expresiones Regulares Web WordPress

Plugin de WordPress a la Lista Negra (Acronym Replacer Revisited)

Acronym Replacer Revisited, es un plugin modificado por Nicolás Fantino, que tiene la finalidad de reemplazar los acrónimos que aparecen en el contenido de una o más entradas.

Gracias a este plugin, he perdido unas cuantas horas intentando determinar porque el blog en el que estaba instalado demoraba mucho en cargar, incluso cuando intentaba validar el feed, el código de respuesta era : Server returned timed out.

A continuación los tiempos de respuesta con el plugin activado/desactivado:

code:

-- Plugin activado
Request Count:  1
Bytes Sent:     56
Bytes Received: 52,125

RESPONSE CODES
--------------
HTTP/200:       1

RESPONSE BYTES (by Content-Type)
--------------
 ~headers:      326
text/html:      51,799

PERFORMANCE
--------------
Time to First byte:     11,125ms
Time to Last byte:      13,547ms

code:

-- Plugin desactivado
Request Count:  1
Bytes Sent:     56
Bytes Received: 51,882

RESPONSE CODES
--------------
HTTP/200:       1

RESPONSE BYTES (by Content-Type)
--------------
 ~headers:      326
text/html:      51,556

PERFORMANCE
--------------
Time to First byte:     1,172ms
Time to Last byte:      1,453ms

Si se fijan los valores de Time to First byte y Time to Last byte se puede observar que hay una gran diferencia en los tiempos de respuesta.

No sé si a otros bloggers que usen este plugin les pase lo mismo, pero por mi parte no he intentado corregir el problema descrito -me dá la ligera impresión que es por el mal uso de expresiones regulares. Por otro lado, tampoco probé la versión original para ver si el problema se reproduce o no, pero por lo pronto es el primer plugin para WordPress que agrego a mi lista negra :D.

Categories
Seguridad WordPress

Cuidado con la codificación de los datos

En el anterior quiz, había puesto un bug existente en versiones anteriores de WordPress que permitía hacer SQL Injection.

Como agusti comentó, el problema se presenta al aplicar la función mysql_real_escape_string antes de hacer la conversión de un juego de caracteres X a UTF-8.

mysql_real_escape_string: Escapa todos los caracteres especiales en la cadena_no_escapada, tomando en cuenta el juego de caracteres actual de la conexión, de tal modo que sea seguro usarla con mysql_query()

Pues bien, para hacer posible el ataque es necesario usar un juego de caracteres en los que ' o \ puedan ser expresados como una secuencia de caracteres seguros; uno de éstos es UTF-7, ya que ' puede ser representado como +ACc- y \ como +AFw-.

Para obtener esas secuencias, pueden hacerlo manualmente en base a la documentación sobre UTF-7 o usando esta simple función:

php:

<?php
$table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

function mb64($match) {
    global $table;
   
    return $table[bindec($match[0])];
}
function utf7_char($char) {
    $bin = str_pad(decbin(ord($char)), 16, 0, STR_PAD_LEFT) . '00';
   
    return '+' . preg_replace_callback('/\d{6}/', 'mb64', $bin) . '-';
}
echo utf7_char("'");
?>

Ahora con las herramientas necesarias, lo único que queda es empezar a jugar con la consulta para obtener los resultados deseados, por ejemplo con los siguientes valores obtenemos todas las entradas (notar que sólo se necesita evadir '):

  • title=+ACc- or 1=1--+ACc- (equivale a ' or 1=1--')
  • charset=utf-7

Se deja como tarea para el lector probar otras consultas 🙂

Categories
Seguridad WordPress

Exploit para versiones de WordPress menores a 2.0.5

Si todavía eres uno de los que no ha migrado a la versión 2.0.6 de WordPress, es mejor que lo hagas cuanto antes, puesto que ha sido liberado el exploit que aprovecha las vulnerabilidades existentes en versiones anteriores (<= 2.0.5).

Este exploit obtiene las cookies (usuario y password) necesarios para entrar en un sitio vulnerable -con extensión mbstring habilitada y wordpress <= 2.0.5.

Categories
Quiz Seguridad Web WordPress

Un bug interesante en WordPress

El presente quiz está basado en un reciente bug de WordPress que fue corregido en la versión 2.0.6 de este CMS

php:

<?php

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

if ( empty($_POST['title']) ) {
        die('Parámetros no válidos');
}

// Conexión a la base de datos test
mysql_connect('localhost', 'root', '1234');
mysql_select_db('test');

// Escapar los valores
$title = mysql_real_escape_string($_POST['title']);

// Hacer la conversión si se envía el parámetro charset
if ( !empty($_POST['charset']) ) {
        // Verificar si la extensión mb_string está habilitada
        if ( function_exists('mb_convert_string') ) {
                $title = @mb_convert_encoding($title, 'UTF-8', $_POST['charset']);
        }
        // Verificar si la extensión iconv está habilitada
        elseif ( function_exists('iconv') ) {
                $title = @iconv($_POST['charset'], 'UTF-8', $title);
        }       
}

$sql = "SELECT * FROM wp_posts WHERE post_title = '$title'";

if ( $result = mysql_query($sql) ) {
        while ($row = mysql_fetch_assoc($result)) {
                print_r($row);
        }
       
        mysql_free_result($result);
}

/*
        Muestra el error intencionalmente
*/

if ( $error = mysql_error() ) {
        echo "MySQL: $error\nConsulta: $sql";
}

mysql_close();
?>

¿Dónde se encuentra el error? y ¿cómo explotarlo? (Si desean puedo colgar una página para que hagan las pruebas)