Defensa contra Inyección SQL: Mecanismo, tipos, técnicas de explotación y más

Comparte

La inyección SQL es una vulnerabilidad común en aplicaciones web que permite a atacantes inyectar código SQL malicioso en los campos de entrada de una aplicación, explotando la confianza que el desarrollador deposita en la entrada del usuario. Esta técnica, al ser relativamente sencilla de ejecutar y con un potencial de daño significativo, se ha convertido en una de las principales amenazas para la seguridad de las aplicaciones web por lo que en este artículo hablaré en profundidad sobre este tipo de ataque, así que prepárate para una lectura extensa.

Mecanismo de Ataque Detallado

El ataque se produce cuando una aplicación web construye dinámicamente una consulta SQL concatenando directamente los datos proporcionados por el usuario. Al no filtrar ni escapar estos datos de forma adecuada, el atacante puede introducir código SQL que altere la semántica original de la consulta. Al hablar de “escapar” me refiero a la capacidad de modificar ciertos caracteres especiales dentro de una cadena de texto para que pierdan su significado al momento de ser usados en consultas SQL.

Ejemplo:

Consideremos una aplicación que permite a los usuarios buscar productos por nombre. La consulta SQL podría ser:

SELECT * FROM productos WHERE nombre = 'nombre_introducido';

Si un atacante introduce como nombre:

'; DROP TABLE productos; --

La consulta resultante sería:

SELECT * FROM productos WHERE nombre = ''; DROP TABLE productos; --';

La primera parte de la consulta (SELECT * FROM productos WHERE nombre = '';) no devuelve ningún resultado, pero la segunda parte (DROP TABLE productos;) elimina completamente la tabla de productos de la base de datos. Esto genera una vulnerabilidad crítica en nuestra aplicación ya que el atacante podría eliminar nuestros datos, cambiar contraseñas, consultar información sensible, etc. A continuación detallaré, tanto los tipos de inyección, como sus técnicas, mitigaciones y defensas en profundidad.

Tipos de Inyección SQL

  • En línea (In-band): El ataque se lleva a cabo dentro de la misma respuesta de la aplicación, permitiendo al atacante ver los resultados de la consulta maliciosa directamente en la página web.
--Consulta original:
SELECT * FROM usuarios WHERE nombre = 'nombre_introducido';
-- Payload: ' OR 1=1 --
-- Consulta resultante:
SELECT * FROM usuarios WHERE nombre = '' OR 1=1 --';

Esto devolverá todos los registros de la tabla “usuarios” ya que la condición 1=1 siempre es verdadera.

  • Fuera de banda (Out-of-band): El atacante redirecciona la salida de la consulta a un servidor controlado por él, permitiendo extraer información de forma más discreta.

Ejemplo de payload: 

' UNION SELECT '<?php system($_GET['cmd']); ?>' INTO OUTFILE '/tmp/backdoor.php' -- 

Este payload crea un archivo PHP en el servidor web que puede ser ejecutado para ejecutar comandos del sistema operativo.

  • Error basado (Error-based): Se aprovecha la información contenida en los mensajes de error devueltos por la base de datos para inferir la estructura de la base de datos.

Ejemplo: Al inyectar un carácter especial como una comilla simple (‘), si la aplicación no está preparada para manejarlo (validación), puede devolver un mensaje de error indicando que se esperaba un valor numérico o una cadena.

  • Tiempo basado (Time-based): Se introducen retrasos en la ejecución de la consulta para determinar si ciertas condiciones son verdaderas o falsas.

Ejemplo de payload: 

' AND IF(SUBSTRING(password,1,1)='a',SLEEP(5),0) 

Si el primer carácter de la contraseña es ‘a’, la consulta se demorará 5 segundos en ejecutarse.

  • Unión (Union): Se utiliza la cláusula UNION para combinar los resultados de múltiples consultas, permitiendo al atacante extraer datos de diferentes tablas.

Ejemplo de payload: 

' UNION SELECT username, password FROM usuarios -- 

Este payload permite al atacante obtener los nombres de usuario y contraseñas de todos los usuarios almacenados en la tabla «usuarios».

Técnicas de Explotación

  • Enumeración de columnas: Identificar el número y los tipos de columnas en una tabla.

Técnica: Se utiliza la cláusula ORDER BY para probar diferentes números de columnas hasta encontrar una que cause un error.

' ORDER BY 1 --
' ORDER BY 2 --
' ORDER BY 3 --
  • Enumeración de tablas: Obtener una lista de todas las tablas en la base de datos.

Ténica: Se utiliza la cláusula UNION SELECT para extraer los datos directamente de las tablas.

' UNION SELECT username, password FROM usuarios --
  • Extracción de datos: Acceder a datos sensibles como contraseñas, números de tarjetas de crédito, etc.

Ténica: Se utilizan funciones específicas de la base de datos para ejecutar comandos del sistema operativo. Esto depende del sistema de gestión de bases de datos utilizado.

' UNION SELECT '<?php system($_GET['cmd']); ?>' INTO OUTFILE '/tmp/backdoor.php' --
  • Ejecución de comandos del sistema operativo: En algunos casos, es posible ejecutar comandos del sistema operativo a través de la base de datos.

Técnica: Se utilizan sentencias SQL como UPDATEDELETE o INSERT para modificar los datos.

' UPDATE usuarios SET password='nueva_contrasena' --

Mitigación

  • Parametrización: Utilizar parámetros para representar los valores de entrada en las consultas SQL. Los DBMS modernos proporcionan mecanismos para escapar automáticamente los parámetros, evitando la inyección.

Mitigación: En lugar de concatenar directamente los valores de entrada en la consulta, se utilizan parámetros que son escapados automáticamente por el motor de base de datos.

Ejemplo en PHP con PDO:

$stmt = $pdo->prepare("SELECT * FROM usuarios WHERE nombre = :nombre");
$stmt->bindParam(':nombre', $nombre, PDO::PARAM_STR);
$stmt->execute();

Ejemplo en Java con JDBC:

PreparedStatement stmt = conn.prepareStatement("SELECT * FROM usuarios WHERE nombre = ?");
stmt.setString(1, nombre);
ResultSet rs = stmt.executeQuery();
  • Stored Procedures: Almacenar procedimientos precompilados que encapsulan la lógica de acceso a la base de datos.

Mitigación: Crear procedimientos almacenados en la base de datos que encapsulen la lógica de acceso a los datos y validan los parámetros de entrada.

Ejemplo en SQL Server:

CREATE PROCEDURE ObtenerUsuario
@Nombre nvarchar(50)
AS
BEGIN
SELECT * FROM usuarios WHERE nombre = @Nombre
END
  • Listas Blancas: Permitir solo un conjunto predefinido de caracteres válidos en los campos de entrada.

Mitigación: Se define un conjunto de caracteres permitidos y se valida que todos los caracteres de la entrada estén dentro de este conjunto.

Ejemplo en PHP:

function validarNombre($nombre) {
if (!preg_match('/^[a-zA-Z ]+$/', $nombre)) {
return false; // Nombre contiene caracteres inválidos
}
return true;
}
  • WAF (Web Application Firewall): Implementar un WAF para filtrar las solicitudes HTTP y detectar patrones de ataque típicos.

Mitigación: Un WAF analiza el tráfico HTTP entrante y bloquea las solicitudes que contienen patrones de ataque conocidos, como inyecciones SQL.

Ejemplo en ModSecurity: Regla simple para detectar inyecciones SQL

SecRule REQUEST_COOKIES "!^([a-zA-Z0-9_-])$" "id:1,phase:2,t:lowercase,msg:'SQL Injection Attack',deny,log"
  • Oráculos de seguridad: Utilizar herramientas de análisis de código estático y dinámico para detectar vulnerabilidades de inyección SQL en el código fuente como SonarQube Fortify.
  • Principio de menor privilegio: Conceder a los usuarios solo los permisos necesarios para realizar sus tareas.
  • Auditar las bases de datos: Monitorear la actividad de la base de datos para detectar anomalías.

Defensas en profundidad y consideraciones adicionales

Si bien las medidas de mitigación anteriormente mencionadas son una opción dependiendo del esceneario en el que te encuentres como cibserdefensor, es importante combinar múltiples capas de seguridad para protegerse de la inyección SQL de una manera más profunda. Una defensa en profundidad implicaría además:

  • Pruebas de seguridad: Realizar pruebas de penetración y escaneos de vulnerabilidades de forma regular.
  • Gestión de parches: Aplicar de manera oportuna los parches de seguridad para los sistemas operativos, bases de datos y aplicaciones.
  • Capacitación de los desarrolladores: Educar a los desarrolladores sobre las mejores prácticas de seguridad.

Pruebas de Seguridad

  • Pruebas de penetración manuales: Simular ataques de inyección SQL para identificar vulnerabilidades en la aplicación.
  • Escaneos automatizados: Utilizar herramientas de escaneo de vulnerabilidades para detectar de forma rápida y eficiente las vulnerabilidades.
  • Fuzzing: Introducir datos aleatorios o mal formados en las entradas de la aplicación para provocar errores y descubrir vulnerabilidades.

Gestión de Parches

  • Mantener actualizados los sistemas operativos: Aplicar los parches de seguridad para corregir vulnerabilidades conocidas.
  • Actualizar los sistemas de gestión de bases de datos: Instalar los parches de seguridad para las bases de datos utilizadas.
  • Actualizar las aplicaciones: Aplicar los parches de seguridad para las aplicaciones, especialmente si se han identificado vulnerabilidades.

Capacitación de Desarrolladores

  • Cursos y talleres: Organizar sesiones de capacitación para enseñar a los desarrolladores las mejores prácticas de seguridad.
  • Guías de estilo de codificación: Establecer guías de estilo de codificación que incluyan recomendaciones para prevenir la inyección SQL.
  • Revisión de código: Realizar revisiones de código para identificar y corregir posibles vulnerabilidades.

Finalmente, la defensa contra la inyección SQL implica una combinación de medidas técnicas y organizacionales. Al implementar una combinación de parametrización de consultas, pruebas de penetración regulares, gestión de parches rigurosa y capacitación continua de los desarrolladores, las organizaciones pueden establecer una defensa sólida contra esta persistente amenaza que atenta contra la información de tus usuarios o clientes.

Deja una respuesta

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

Volver arriba