sábado, 3 de julio de 2010

Inyección SQL en GHL Hoteles

GHL Hoteles es una cadena hotelera presente en varios paises latinoamericanos a la que pertenecen hoteles de prestígio como el Sheraton o el Four Points pero lamentablemente parece que no han puesto el mismo interes en la calidad de su página web como en sus hoteles.

La web de GHL Hoteles contiene errores de programación de manual en lo que se refiere a inyección SQL ya que con solo acceder a uno de los hoteles mediante una URL del tipo


podemos introducir código SQL junto con el parámetro id ya que no se realiza ningún tipo de filtrado de forma que si accedemos a la URL


Podemos ver el siguiente mensaje de error


lo que, además de confirmarnos que es posible la inyección de código SQL, nos da información sobre el contenido del servidor, como por ejemplo que una de las tablas del servidor se llama hotel y que, por lo menos contiene los campos nro_hotel, ghl y publicar.

Pero no es la única página en la que se puede hacer inyección sql, existe una sección llamada NotiHoteles desde la que se puede acceder a noticias relacionadas con los distintos hoteles de la cadena.
Las distintas noticias tienen urls del tipo:


y, como en el caso anterior el parámetro id tampoco tiene ningún tipo de filtrado de forma que es posible acceder a un mensaje de error similar al obtenido anteriormente utilizando la url


En esta ocasión se obtienen más datos sobre el servidor. Se conoce la existencia de las tablas noticia, seccion_noticias y modulo_noticias así como algunos campos de dichas tablas nombre, nro_modulo, ubicacion, site...

¿Podría modificar la consulta para escribir mi propia noticia? para ello existen varias opciones, una seria insertar información en la tabla noticia pero esto no lo voy a hacer ya que no quiero modificar datos de un servidor ajeno sin el consentimiento previo. La otra opción seria "forzar" que la instrucción select devolviese la información que quisieramos visualizar como noticia pero para ello necesitamos conocer los campos existentes en la tabla noticia para saber que campo almacena el título de la noticia, la fecha, el cuerpo de la noticia, etc.

Para conocer cuantos campos existen en la tabla noticia podemos hacerlo por el método de prueba y fallo intentando realizar un UNION de la consulta que se nos muestra con una consulta ficticia nuestra, por ejemplo:

SELECT n.*, m.nombre modulo, s.nombre seccion, m.nro modulo
FROM noticia n, seccion_noticias s, modulo_noticias m
WHERE n.nro_seccion = s.nro_seccion
AND s.nro_modulo = m.nro_modulo
AND n.nro_noticia = '2403' UNION SELECT 1 /*
AND n.publicar = 'S'
AND FIND_IN_SET('SECCION', n.ubicacion)>0
AND FIND_IN_SET('GHL', n.site)>0

En rojo he añadido la consulta que utilizaremos para saber cuantos campos tiene la tabla noticia.
He añadido también los caracteres /* para que SQL interprete el resto de la consulta (verde) como si fueran comentarios de forma que no se tendrán en cuenta.
De esta forma si añadimos ' UNION SELECT 1 /* al parámetro id de la url obtenemos un mensaje de error similar al anterior pero que nos indica que la nueva consulta select tiene diferente número de campos


Ahora solo nos queda ir añadiendo campos a nuestra consulta hasta que el servidor nos devuelva una respuesta positiva, por ejemplo:

http://www.ghlhoteles.com/noticia.php3?id=2403' UNION SELECT 1,2 /*
http://www.ghlhoteles.com/noticia.php3?id=2403' UNION SELECT 1,2,3 /*
....
http://www.ghlhoteles.com/noticia.php3?id=2403' UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28 /*

Si, hay que tener un poco de paciencia o valerse de algún programa que vaya generando las distintas url. En fin, el caso es que con 28 campos el servidor nos devuelve la noticia correcta.


Ahora ya sabemos que la consulta resultante es válida pero ¿porque no se muestran nuestros campos en la web?. Simplemente porque ahora se estan devolviendo dos noticias (la real y la falsa) pero la página web solo muestra la primera así que para anular el primer registro que es el que tiene la noticia real es suficiente con indicarle un id que no exista, por ejemplo -1, quedando así:

http://www.ghlhoteles.com/noticia.php3?id=-1' UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28 /*

En principio nos aparecen 4 de los 28 campos "falsos" que hemos introducido (la fecha 31/12/69 también es uno de los campos que ha sido convertido a DATE pero para no hacer demasiado largo el post no me detendré en él). Ahora ya sabemos que lo que escribamos en lugar del 3 aparecera como si fuera el título de la noticia, el 4 representa el "lugar" mientras que el 6 es el cuerpo de la noticia y, pese a que no se ve en la imagen adjunta, el campo 16 representa la imagen de forma que la siguiente URL muestra esta noticia tan sexy.


Pero vayamos un poco más allá, hasta el momento solo hemos utilizado la inyección SQL para modificar la visualización de la página como si de un simple XSS se tratara pero mediante inyección SQL podemos obtener la información contenida en las tablas del servidor. ¿Existirá alguna tabla interesante en este servidor?

Si continuamos navegando por la web de GHL vemos que también existe un formulario de contacto que, como era de esperar, tampoco realiza ningún tipo de filtrado sobre los campos del mismo de forma que con la ya famosa "comilla simple" y rellenando algunos campos obtenemos lo siguiente:


Con este nuevo mensaje de error vemos una nueva tabla que parece interesante, la tabla Contacto así como todos los campos que existen en ella de forma que podríamos visualizar la información de esta tabla en la página de noticias, es decir, en lugar de visualizar una noticia podríamos visualizar cualquier campo de la tabla Contacto.


Entendereis que no ponga la url exacta de como sacar esta información aunque creo que no resultará dificil de obtener si habeis leido el post completo.

A fecha de hoy existen 10912 registros en la tabla Contacto por lo que es de suponer que habrá 10912 direcciones de correo electrónico, teléfonos, nombres, direcciones... información muy sensible que no deberia ver la luz.

Esto es solo un pequeño ejemplo de la cantidad de información a la que se puede acceder pero existen otras muchas tablas accesibles (112 en total) con lo que el daño a la empresa y a los clientes puede ser muy elevado.

1 comentario:

  1. Fossie!

    Te agradezco mucho la explicación tan completa que me diste sobre el problema que te comenté. No sé qué decirte, pero el asunto se arregló solo... Jeje.

    Gracias igualmente!

    Fran.

    ResponderEliminar