# SQL Injection

En un ataque de inyección, el atacante inserta o _inyecta_ consultas SQL parciales o completas a través de la aplicación web. El atacante inyecta comandos SQL en campos de entrada de una aplicación o una URL para ejecutar comandos SQL predefinidos.

**Una breve introducción a SQL**

Como sabrá, las siguientes son algunas de las sentencias (comandos) SQL más comunes:

* **SELECT:** Se utiliza para obtener datos de una base de datos.
* **UPDATE:** Se utiliza para actualizar datos en una base de datos.
* **DELETE:** Se utiliza para eliminar datos de una base de datos.
* **INSERT INTO:** Se utiliza para insertar nuevos datos en una base de datos.
* **CREATE DATABASE:** Se utiliza para crear una nueva base de datos.
* **ALTER DATABASE:** Se utiliza para modificar una base de datos.
* **CREATE TABLE:** Se utiliza para crear una nueva tabla.
* **ALTER TABLE:** Se utiliza para modificar una tabla.
* **DROP TABLE:** Se utiliza para eliminar una tabla.
* **CREATE INDEX:** Se utiliza para crear un índice o un elemento clave de búsqueda.
* **DROP INDEX:** Se utiliza para eliminar un índice.

Normalmente, las declaraciones SQL se dividen en las siguientes categorías:

* Declaraciones del lenguaje de definición de datos (DDL)
* Declaraciones del lenguaje de manipulación de datos (DML)
* Declaraciones de control de transacciones
* Declaraciones de control de sesión
* Declaraciones de control del sistema
* Sentencias SQL incorporadas



Uno de los primeros pasos cuando encuentra vulnerabilidades de inyección SQL es comprender cuándo interactúa la aplicación con una base de datos. Normalmente, esto se hace con formularios de autenticación web, motores de búsqueda y sitios interactivos, como sitios de comercio electrónico.

Puede hacer una lista de todos los campos de entrada cuyos valores podrían usarse para elaborar una consulta SQL válida. Esto incluye intentar identificar y manipular campos ocultos de solicitudes **POST** y luego probarlos por separado, intentando interferir con la consulta y generar un error. Como parte de las pruebas de penetración, debes prestar atención a los encabezados **HTTP** y las **cookies.**

Como probador de penetración, puede comenzar agregando una comilla simple **(')** o un punto y coma **( ; )** al campo o parámetro en un formulario web. La comilla simple se utiliza en SQL como terminador de cadena. Si la aplicación no lo filtra correctamente, es posible que pueda recuperar registros o información adicional que pueda ayudar a mejorar su consulta o declaración.

También puede utilizar delimitadores de comentarios (como **--** o **/\* \*/** ), así como otras palabras clave SQL, incluidos los operadores **AND** y **OR** . Otra prueba sencilla es insertar una cadena donde se espera un número.

> Se monitorear todas las respuestas de una aplicación. Esto incluye inspeccionar el código fuente HTML o JavaScript. En algunos casos, los errores que regresan de la aplicación están dentro del código fuente y se muestran al usuario.

**Categorías de inyección SQL**

Los ataques de inyección SQL se pueden dividir en las siguientes categorías:

* **Inyección SQL en banda:** Con este tipo de inyección, el atacante obtiene los datos utilizando el mismo canal que se utiliza para inyectar el código SQL. Esta es la forma más básica de ataque de inyección SQL, donde los datos se vuelcan directamente en una aplicación web (o página web).
* **Inyección SQL fuera de banda:** con este tipo de inyección, el atacante recupera datos utilizando un canal diferente. Por ejemplo, se podría enviar al atacante un correo electrónico, un texto o un mensaje instantáneo con los resultados de la consulta; o el atacante podría enviar los datos comprometidos a otro sistema.
* **Inyección SQL ciega (o inferencial):** Con este tipo de inyección, el atacante no hace que la aplicación muestre ni transfiera ningún dato; más bien, el atacante puede reconstruir la información enviando declaraciones específicas y discerniendo el comportamiento de la aplicación y la base de datos.



Existen cinco técnicas que se pueden utilizar para explotar las vulnerabilidades de inyección SQL:

* **Operador de unión:** normalmente se utiliza cuando una vulnerabilidad de inyección SQL permite que una instrucción **SELECT** combine dos consultas en un único resultado o un conjunto de resultados.
* **Booleano:** se utiliza para verificar si ciertas condiciones son verdaderas o falsas.
* **Técnica basada en errores:** se utiliza para forzar a la base de datos a generar un error con el fin de mejorar y refinar un ataque (inyección).
* **Técnica fuera de banda:** normalmente se utiliza para obtener registros de la base de datos utilizando un canal diferente. Por ejemplo, es posible realizar una conexión HTTP para enviar los resultados a un servidor web diferente o a una máquina local que ejecute un servicio web.
* **Retraso de tiempo:** es posible utilizar comandos de la base de datos para retrasar las respuestas. Un atacante puede utilizar esta técnica cuando no obtiene resultados o mensajes de error de la aplicación.

La inyección SQL también se puede aprovechar manipulando una cadena de consulta URL, como se demuestra aquí:

```
.php?id=99 AND 1=2
```

Esta aplicación vulnerable luego realiza la siguiente consulta SQL:

```
SELECT * FROM products WHERE product_id=99 AND 1=2
```

Luego, el atacante puede ver un mensaje que especifica que no hay contenido disponible o que hay una página en blanco. Luego, el atacante puede enviar una consulta válida para ver si la aplicación arroja algún resultado, como se muestra aquí:

```
.php?id=99 AND 1=1
```

Algunos marcos de aplicaciones web permiten múltiples consultas a la vez. Un atacante puede aprovechar esa capacidad para realizar exploits adicionales, como agregar registros. La siguiente declaración, por ejemplo, agrega un nuevo usuario a la tabla de usuarios de la base de datos:

```
.php?id=99; INSERT INTO users(username) VALUES ('user')
```

**Huellas digitales de bases de datos**

Para ejecutar con éxito consultas complejas y explotar diferentes combinaciones de inyecciones SQL, primero debe tomar huellas digitales de la base de datos. El lenguaje SQL está definido en el estándar ISO/IEC 9075. Sin embargo, las bases de datos se diferencian entre sí en términos de su capacidad para ejecutar comandos adicionales, el uso de funciones para recuperar datos y otras características. Al realizar ataques de inyección SQL más avanzados, un atacante necesita saber qué base de datos back-end utiliza la aplicación (por ejemplo, Oracle, MariaDB, MySQL, PostgreSQL).

Una de las formas más sencillas de tomar huellas dactilares de una base de datos es prestar mucha atención a cualquier error que devuelva la aplicación, como se demuestra en el siguiente mensaje de error de sintaxis de una base de datos MySQL:

```
  Error 1064 de MySQL
```

Si está intentando tomar huellas digitales de una base de datos y no aparece ningún mensaje de error en la base de datos, puede intentar usar la concatenación.

```sqf
MySQL: 'finger' + 'printing'
SQL Server: 'finger' 'printing'
Oracle: 'finger'||'printing'
PostgreSQL: 'finger'||'printing'
```

**La técnica de explotación de la UNIÓN**

El operador SQL **UNION** se utiliza para combinar los conjuntos de resultados de dos o más declaraciones **SELECT** , como se muestra aquí:

```
SELECT zipcode FROM hacker_customers
UNION
SELECT zipcode FROM hacker_suppliers;
```

De forma predeterminada, el operador **UNION** selecciona solo valores distintos. Puede utilizar el operador **UNION ALL** si desea permitir valores duplicados.

Los atacantes pueden utilizar el operador **UNION** en ataques de inyecciones SQL para unir consultas. El objetivo principal de esta estrategia es obtener los valores de columnas de otras tablas. El siguiente es un ejemplo de un ataque de inyección SQL basado en **UNION** :

```
SELECT zipcode FROM hacker_customers WHERE zip=1 UNION ALL
SELECT creditcard FROM payments
```

En este ejemplo, el atacante une el resultado de la consulta original con todos los números de tarjetas de crédito en la tabla de pagos.

El ejemplo muestra la siguiente cadena ingresada en el formulario.

```
user' UNION SELECT 1,user_name,password,'1','1','1',1 FROM user_system_data -
```

El siguiente es un ejemplo de un ataque de inyección SQL basado en **UNION** utilizando una URL:

```
.php?id=1234' UNION SELECT 1, user_name,password,'1','1','1',1 FROM user_system_data --
```

**Booleanos en ataques de inyección SQL**

La técnica booleana se utiliza normalmente en ataques de inyección SQL ciega. En las vulnerabilidades de inyección SQL ciega, la aplicación vulnerable normalmente no devuelve un error de SQL, pero podría devolver un mensaje HTTP 500, un mensaje 404 o una redirección. Es posible utilizar consultas booleanas en una aplicación para intentar comprender el motivo de dichos códigos de error

**Explotación fuera de banda**

La técnica de explotación fuera de banda es muy útil cuando se explota una vulnerabilidad de inyección SQL ciega. Puede utilizar las funciones del sistema de gestión de bases de datos (DBMS) para ejecutar una conexión fuera de banda para obtener los resultados del ataque de inyección SQL ciega.

**Consultas apiladas**

En una consulta SQL normal, puede utilizar un punto y coma para especificar que se ha llegado al final de una declaración y lo que sigue es una nueva. Esta técnica le permite ejecutar múltiples declaraciones en la misma llamada a la base de datos. **Las consultas UNION** utilizadas en ataques de inyección SQL se limitan a declaraciones **SELECT .** Sin embargo, _**las consultas apiladas**_ se pueden utilizar para ejecutar cualquier instrucción o procedimiento SQL. Un ataque típico que utilice esta técnica podría especificar una declaración de entrada maliciosa como la siguiente:

```
1; DELETE FROM clientes;
```

La aplicación y la base de datos vulnerables procesan esta declaración como la siguiente consulta SQL:

```
SELECT * FROM clientes WHERE customer_id = 1; DELETE FROM clientes;
```

**La técnica de inyección SQL con retardo de tiempo**

Cuando se intenta explotar una inyección SQL ciega, la técnica booleana es muy útil. Otro truco consiste en inducir también un retraso en la respuesta, lo que indica que el resultado de la consulta condicional es verdadero.

El siguiente es un ejemplo del uso de la técnica de retardo de tiempo contra un servidor MySQL:

**Examinar una inyección SQL de procedimiento almacenado**

Un procedimiento almacenado es una o más declaraciones SQL o una referencia a un servidor SQL. Los procedimientos almacenados pueden aceptar parámetros de entrada y devolver múltiples valores en forma de parámetros de salida al programa que realiza la llamada. También pueden contener declaraciones de programación que ejecutan operaciones en la base de datos.

Si un servidor SQL no desinfecta la entrada del usuario, es posible ingresar declaraciones SQL maliciosas que se ejecutarán dentro del procedimiento almacenado. El siguiente ejemplo ilustra el concepto de procedimiento almacenado:

```
 Create procedure user_login @username varchar(20), @passwd varchar(20) As Declare @sqlstring varchar(250)
  Set @sqlstring = ' Select 1 from users Where username = ' + @username + ' and passwd = ' + @passwd exec(@sqlstring) Go
```

Al ingresar user or 1=1' somepassword en una aplicación vulnerable donde la entrada no está desinfectada, un atacante podría obtener la contraseña y otra información confidencial de la base de datos.

**Mitigaciones de inyección SQL**

La validación de entradas es una parte importante para mitigar los ataques de inyección SQL. La mejor mitigación para las vulnerabilidades de inyección SQL es utilizar consultas inmutables, como las siguientes:

* consultas estáticas
* Consultas parametrizadas
* Procedimientos almacenados (si no generan SQL dinámico)

Las consultas inmutables no contienen datos que puedan interpretarse. En algunos casos, procesan los datos como una entidad única vinculada a una columna sin interpretación.

Los siguientes son dos ejemplos de consultas estáticas:

```
select * from contacts;
select * from users where user = "user";
```

Los siguientes son ejemplos de consultas parametrizadas:

<pre><code><strong>String query = "SELECT * FROM users WHERE name = ?";
</strong>PreparedStatement statement =
connection.prepareStatement(query);
statement.setString(1, username);
ResultSet results = statement.executeQuery();
</code></pre>



<mark style="color:red;">**Recursos**</mark>

{% embed url="https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html" %}

{% embed url="https://portswigger.net/web-security/sql-injection" %}

{% embed url="https://owasp.org/www-community/attacks/SQL_Injection" %}

{% embed url="https://learn.microsoft.com/en-us/sql/relational-databases/security/sql-injection?view=sql-server-ver16" %}
