SQL Injection en CompraEntradas.com : SQL Injection en una web real

Escrito por David García Martín
Seguridad
8

Es bien conocido por todos aquellos adeptos a la red que existen fallos de seguridad en páginas de internet. Dichos fallos de seguridad se dan en muchos casos por ignorar prácticas mínimas en cuanto al desarrollo web y otras veces son simplemente el fruto de un descuido o un bug inimaginable en la tecnología utilizada para el desarrollo.

Lo primero que RedesZone quiere destacar es que la mencionada página es completamente segura y fiable: un fallo no constituye una generalidad y en este caso la compra de entradas (finalidad última de la página) no se ve alterada en absoluto, siendo la seguridad una constante patente e innegable.

Así mismo, este artículo no tiene como propósito enseñar ni motivar la violación de páginas web en ninguna medida, sino mas bien todo lo contrario: mostrar donde se encuentra el agujero de seguridad para que futuros desarrolladores de páginas web realicen proyectos mas fiables y seguros.

Con esos objetivos en mente, las consultas, la información que pudiera ser de carácter vital para la seguridad de la página o cualquier dato sensible han sido ocultados y/o cambiados.

Por supuesto, el fallo que se recogía en esta página ya ha sido solucionado: RedesZone nunca ha publicado ni publicará o divulgará bajo ningún motivo fallos que puedan ser explotados.

Vamos a explicar la naturaleza del fallo de la página y su solución.

Si visitamos la siguiente URL: www.compraentradas.com, vemos que podemos escoger para pinchar y continuar la navegación una serie de enlaces. Navegando un poco por la página llegamos a una cuyos parámetros contienen un campo, ID=10, dando como resultado esta página: (se ha ocultado la información que podría resultar sensible)

SQL Injection Prueba real

Observemos por un momento la URL de la página:

http://www.compraentradas.com/paginaPropia.php?parametro1 =4&parametro2=XX

Como se puede observar, la página contiene una serie de parámetros que se pasan por dicha URL y que van a ser el objeto de nuestro ataque.

Lo primero que debemos hacer para comprobar que la página es vulnerable a un ataque de SQL Injection. Para ello vamos a poner en el parámetro parametro1 un ID que no exista, por ejemplo:

http://www.compraentradas.com/paginaPropia.php?parametro1=43132313132123&parametro2=XX

Dicha consulta da como resultado la siguiente página: (se ha ocultado la información que podría resultar sensible).

SQL Injection Prueba real

En este caso, todo parece normal, es decir, al poner una URL que no existe, la página muestra como resultado un marco en blanco.

El siguiente paso sería poner algo que un motor de SQL no fuera capaz de entender. Si el resultado de esta prueba es satisfactoria, la página sería vulnerable puesto que no sería capaz de filtrar el contenido que se le ha puesto para la ejecución de la consulta.

Vamos a poner algo como esto (damos por hecho que la consulta sólo admite números en el parámetro1.

Sería algo como esto:

http://www.compraentradas.com/paginaPropia.php?parametro1=4313KKK&parametro2=XX

Si utilizamos esta consulta, da como resultado la siguiente página: (se ha ocultado la información que podría resultar sensible para evitar a los Script Kiddies).

SQL Injection Prueba real

En este caso, ya hemos comprobado que la consulta no filtra los parámetros y que podría ser vulnerable a una inyección. Lo siguiente que un hacker comprobaría sería algo como esto:

http://www.compraentradas.com/paginaPropia.php?parametro1=4313KKK+and+(select+count(*)+from+tabla)>0&parametro2=XX

Si la consulta devuelve una página correcta, significaría que la tabla que hemos puesto existe y la consulta es verdadera y fiable.

Si pusiéramos una consulta que contuviera errores o cuyos campos no fueran correctos, saldría de nuevo la siguiente página o alguna parecida (se omite información que puede resultar sensible)

Jugando un poco con los parámetros de dicha consulta, se llegaría al resultado siguiente:

http://www.compraentradas.com/paginaPropia.php?parametro1=4313+and+(select+count(*)+from+tabla+where+id_tabla_columna=1+and+substring(campo,1,1)>0X129)>0&parametro2=XX

Si esta consulta da como resultado una página correcta, significaría que la posición 1 del campo campo de la tabla tabla tiene es igual a 0X129.

Automatizando este tipo de ataque (existen automatizadores para ello ya escritos) se podrían obtener los datos de cualquier usuario de la web, con lo que el ataque llegaría a obtener datos que serían de carácter personal.

SOLUCIÓN DEL ERROR

En el caso que ocupa a nuestro artículo, el fallo de SQL Injection fue posible debido al no filtrado de algunos parámetros de la aplicación. La corrección de dicho fallo atiende al principio siguiente:

Todo lo que sea de carácter público debe ser filtrado.

Con esta sencilla premisa, el 90% de los ataques pueden evitarse.

Desde RedesZone, queremos agradecerle al director general propietario de compraentradas, Juan Manuel Heredia Gallardo, su amabilidad en el trato y  que nos haya permitido publicar este error de seguridad.


Continúa leyendo
  • Anónimo

    ethiel, todo muy didáctico y muy bien explicado, espero que sigas en esta linea en las siguientes publicaciones.

    Un Saludo.

    PD: El error ya habrá sido subsanado no?.

  • Gracias por tu comentario.
    El error fue subsanado antes de publicar.

  • Anónimo

    No entiendo bien lo de “Todo lo que sea de carácter público debe ser filtrado.”.

    Entiendo que se tiene que hacer algún tipo de filtro a la hora de aceptar/recibir parámetros según pareces indicar, pero ¿cómo se solucionaría de forma práctica?

    Decir que los artículos son muy didácticos pero habría que ahondar también un poco dando un ejemplo de las soluciones que se proponen para hacer los artículos totalmente redondos.

    Saludos!

  • Te explico lo que quería decir:
    cuando realizas una aplicación cuya entrada depende de datos que se le envían desde fuera de ella, todos ellos sin excepción deben recibir un tratamiento; porque no puedes asegurar la veracidad ni la integridad de los mismos.
    Si los datos provienen de un método de tu propia clase no has de validarlos, puesto que eres tú mismo quien se los ha enviado y no nada del exterior y por lo tanto estarán validados en el primer filtro.
    Hablando de JAVA; por ejemplo, sería lo asiguiente:
    valida todo lo que tenga carácter public.
    no haca falta que valides todo lo que tenga caracter private.
    Cuando digo validar, quiero decir que los datos de entrada deben recibir un tratamiento, es decir, si tu esperas recibir un entero, controla que lo que te venga sea un entero, por que si yo como usuario mando una cadena, tu aplicación fallará y podría ocasionar y derivar en fallos de SQL injection.

  • Anónimo

    Tienes muy buena intención pero yo creo que deberias elaborar un poco más las explicaciones porque son demasiado breves y hay que intuir muchos detalles que omites, cosa complicada para el que no entiende del tema. Por poner un ejemplo:

    “Si la consulta devuelve una página correcta, significaría que la tabla que hemos puesto existe y la consulta es verdadera y fiable.”

    No dices que la palabra “tabla” que sale en “+and+(select+count(*)+from+tabla” es el nombre de la tabla de la base de datos que quieres atacar y que lo has obtenido en la pantalla de error anterior.

    O otro ejemplo:

    “Si esta consulta da como resultado una página correcta, significaría que la posición 1 del campo campo de la tabla tabla tiene es igual a 0X129.”

    Esta fatal redactado, eso de “campo campo” parece un error tipográfico, y lo del misterioso 0x129 di que es un número en hexadecimal representando un caracter ASCII extendido.

    En fin, que me gusta mucho lo que estás haciendo pero creo que puedes mejorar mucho. Espero que no te enfades por mis críticas, las hago no por molestar sino con la mejor intención.

  • Ante todo, en absoluto me molestan las críticas constructivas hacia mi trabajo; no te preocupes.
    No puedo publicar todos los detalles del error porque implicaría dejárselo fácil a cualquier pirata que quisiera reventar una página o a cualquier script kiddie que sólo siga tutoriales.

    De todos modos, tomo nota de tu sugerencia y voy a ampliar el artículo con mas explicaciones.

    Gracias por tus comentarios. 😀

  • miguelito

    Es increible esta pagina, todos los articulos son interesantisimos y la verdad que no me pierdo ninguno sin mirar a fondo. Estais haciendo un magnifico trabajo, muchas gracias!!