Skip to content
IRC-CodingIRC-Coding
SQL InjectionPrepared StatementsWeb SecurityBase de DatosOWASP

SQL Injection: Ataques, Defensas y Prevención

SQL Injection es una vulnerabilidad crítica. Aprenda cómo los atacantes inyectan comandos SQL maliciosos y cómo protegerse con Prepared Statements.

S

schutzgeist

11 min read
SQL Injection: Ataques, Defensas y Prevención

SQL Injection: Ataques, Medidas de Protección y Prevención

Este artículo es una explicación conceptual sobre ataques de SQL Injection, incluidas medidas de protección y buenas prácticas.

En Resumen

SQL Injection es una vulnerabilidad en aplicaciones web donde los atacantes inyectan comandos SQL manipulados en campos de entrada para obtener acceso no autorizado a bases de datos o modificar datos.

Descripción Técnica Compacta

SQL Injection es una de las vulnerabilidades de seguridad más peligrosas y frecuentes en aplicaciones web. Los atacantes explotan el procesamiento inseguro de entradas de usuario para ejecutar comandos SQL propios.

Vectores de ataque:

  • Formularios de login: Eludir autenticación
  • Campos de búsqueda: Extracción de datos de otras tablas
  • Parámetros de URL: Manipulación de consultas a la base de datos
  • Endpoints de API: Ejecución directa de comandos SQL

Peligros:

  • Robo de datos: Extracción de información sensible
  • Manipulación de datos: Modificación o eliminación de registros
  • Toma de control del sistema: Ejecución de comandos del sistema
  • Denegación de servicio: Destrucción de estructuras de base de datos

Puntos Clave para Exámenes

  • Objetivo: Acceso, modificación o destrucción de bases de datos
  • Causa: Paso inseguro de entradas de usuario a la base de datos
  • Vulnerabilidades típicas: Formularios de login, campos de búsqueda, parámetros de URL
  • Medidas de protección: Prepared Statements, validación de entrada, frameworks ORM
  • Ejemplo de ataque: admin' OR '1'='1 elude la verificación de contraseña
  • OWASP A03: Injection es el riesgo de seguridad Top 3
  • Principio de derechos: Sin acceso root para usuarios web
  • Relevante para IHK: Importante para arquitectura y desarrollo de software

Componentes Clave

  1. Consultas vulnerables: Concatenación directa de strings en SQL
  2. Prepared Statements: Consultas parametrizadas
  3. Validación de entrada: Whitelist y escaping
  4. Frameworks ORM: Hibernate, Entity Framework
  5. Least Privilege: Derechos mínimos de base de datos
  6. Manejo de errores: Sin exposición de errores de BD
  7. Testing de seguridad: Scanners automatizados
  8. Revisión de código: Inspección manual

Ejemplos Prácticos

Código Vulnerable

// MUY PELIGROSO - SQL Injection posible
public User login(String username, String password) {
    String query = "SELECT * FROM users WHERE username = '" + 
                   username + "' AND password = '" + password + "'";
    Statement stmt = connection.createStatement();
    ResultSet rs = stmt.executeQuery(query);
    
    if (rs.next()) {
        return new User(rs.getString("username"), rs.getString("role"));
    }
    return null;
}

// Ataque: username = "admin' OR '1'='1" -- "
// Resultado: SELECT * FROM users WHERE username = 'admin' OR '1'='1' -- ' AND password = ''
// Se devuelven todos los usuarios!

Alternativa Segura con Prepared Statements

// SEGURO - SQL Injection prevenido
public User login(String username, String password) {
    String query = "SELECT * FROM users WHERE username = ? AND password = ?";
    PreparedStatement stmt = connection.prepareStatement(query);
    stmt.setString(1, username);
    stmt.setString(2, password);
    ResultSet rs = stmt.executeQuery();
    
    if (rs.next()) {
        return new User(rs.getString("username"), rs.getString("role"));
    }
    return null;
}

Más Ejemplos de Ataques

-- Union-Based Injection
' UNION SELECT username, password FROM admins --

-- Blind Injection
' AND (SELECT COUNT(*) FROM users WHERE username='admin' AND password LIKE 'a%') > 0 --

-- Time-Based Injection
' AND (SELECT SLEEP(5)) --

-- StoredProcedure Injection
'; DROP TABLE users; --

Medidas de Protección

1. Prepared Statements (Consultas Parametrizadas)

// Java
String sql = "SELECT * FROM products WHERE name = ? AND price < ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, productName);
stmt.setDouble(2, maxPrice);

// PHP con PDO
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);

// Python
cursor.execute("SELECT * FROM users WHERE id = %s", [user_id])

2. Validación de Entrada y Escaping

// Validación Whitelist
public boolean isValidUsername(String username) {
    return username.matches("^[a-zA-Z0-9_]{3,20}$");
}

// HTML Escaping para salidas
String safeOutput = StringEscapeUtils.escapeHtml4(userInput);

3. Frameworks ORM

// JPA/Hibernate
@Entity
@Table(name="users")
public class User {
    @Id
    private String username;
    private String password;
    
    // Creación automática de SQL, seguro contra injection
}

public User findByUsername(String username) {
    return entityManager.createQuery(
        "SELECT u FROM User u WHERE u.username = :username", User.class)
        .setParameter("username", username)
        .getSingleResult();
}

4. Principio de Least Privilege

-- La aplicación web obtiene solo los derechos necesarios
GRANT SELECT, INSERT, UPDATE ON app_db.users TO 'webapp'@'localhost';
-- SIN derechos DROP, DELETE, ALTER!

Ventajas y Desventajas de las Medidas de Protección

Ventajas

  • Seguridad: Previene compromisos de base de datos
  • Cumplimiento: Satisface estándares de seguridad (GDPR, ISO 27001)
  • Confianza: Protege datos de usuarios y reputación empresarial
  • Eficiencia de costos: Evita incidentes de seguridad costosos

Desventajas

  • Performance: Los Prepared Statements pueden ser más lentos
  • Complejidad: Requiere esfuerzo de programación adicional
  • Curva de aprendizaje: Los desarrolladores deben aprender programación segura
  • Testing: Se requieren pruebas de seguridad adicionales

Preguntas Frecuentes en Exámenes

  1. ¿Qué es SQL Injection y cómo funciona? Inyección de código SQL a través de entradas de usuario mediante concatenación de strings insegura.

  2. ¿Cómo se previene SQL Injection de forma más efectiva? Mediante el uso de Prepared Statements o Parameterized Queries.

  3. ¿Por qué la validación de entrada por sí sola no es suficiente? La validación puede ser eludida, los Prepared Statements son más seguros.

  4. ¿Qué rol juega el principio de Least Privilege? Las aplicaciones web deben tener solo derechos mínimos de base de datos para limitar el daño.

Preguntas y Respuestas para Principiantes

¿Qué es SQL Injection explicado de forma muy simple?

Imagina que tienes un formulario de login. Normalmente, cuando escribes tu nombre, la web espera recibir solo un nombre. En un ataque de SQL Injection, un atacante ingresa código SQL especial que la base de datos ejecuta como un comando en lugar de tratarlo como texto normal.

¿Realmente puede ocurrir?

Sí. Muchos sitios web no están suficientemente protegidos. Los atacantes pueden robar contraseñas, eliminar datos o tomar control de la base de datos completa.

¿Cómo sé si mi sitio web está en riesgo?

Si integras entradas de usuario directamente en consultas SQL sin “limpiarlas”, estás en riesgo. Esto es especialmente común en formularios de login, campos de búsqueda o formularios de contacto.

¿Es complicado protegerse?

No. La regla más importante: siempre usa Prepared Statements. Es como un escudo que evita que las entradas de usuario se malinterpreten como comandos.

Guía práctica para sitios web normales

Paso 1: Identificar vulnerabilidades

Qué debes revisar:

  • Todos los formularios de login
  • Campos de búsqueda del sitio
  • Formularios de contacto
  • Formularios de registro
  • Parámetros en la URL (p. ej. ?id=123)

Prueba simple: Ingresa lo siguiente en un campo de búsqueda: ' OR '1'='1 Si el sitio muestra resultados extraños o todos los datos, podría ser vulnerable.

Paso 2: Herramientas para pruebas de seguridad

Para principiantes:

  • SQLMap (gratuito): Automatiza las pruebas de SQL Injection
  • Burp Suite Community (gratuito): Intercepta y analiza el tráfico web
  • OWASP ZAP (gratuito): Herramienta de seguridad para aplicaciones web

Para usuarios avanzados:

  • Burp Suite Professional (de pago): Funcionalidades extendidas
  • Acunetix (de pago): Escaneos de seguridad automatizados

Herramientas del navegador:

  • Herramientas de desarrollador (F12) en el navegador
  • Pestaña Network para analizar solicitudes

Paso 3: Ejecutar las pruebas

Procedimiento:

  1. Analiza el sitio web: Encuentra todos los formularios y parámetros
  2. Registra el tráfico: Usa Burp Suite o ZAP para ver las solicitudes
  3. Ingresa payloads de prueba: Prueba diferentes patrones de SQL Injection
  4. Observa las reacciones: Ten cuidado con los mensajes de error o resultados extraños

Payloads de prueba comunes:

' OR '1'='1
' UNION SELECT null,null--
' AND (SELECT COUNT(*) FROM users) > 0
'; DROP TABLE users--

' OR 'x'='x
' OR 1=1--
' OR 1=1#
' UNION SELECT username,password FROM users--
' UNION SELECT @@version--
' AND SLEEP(5)--
' WAITFOR DELAY '00:00:05'
' AND (SELECT * FROM (SELECT COUNT(*),CONCAT(version(),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)--
' AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT version()),0x7e))--
' AND (SELECT * FROM (SELECT COUNT(*),CONCAT((SELECT database()),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)--
' UNION SELECT 1,2,3,4,5,6,7,8,9,10--
' UNION SELECT 1,@@datadir,3,4--
' UNION SELECT SCHEMA_NAME,2 FROM INFORMATION_SCHEMA.SCHEMATA--
' UNION SELECT table_name,2 FROM INFORMATION_SCHEMA.TABLES--
' UNION SELECT column_name,2 FROM INFORMATION_SCHEMA.COLUMNS--
' AND 1=CONVERT(int,(SELECT @@version))
' AND 1=CONVERT(int,(SELECT top 1 name FROM sysobjects WHERE xtype='U'))

Paso 4: Documentar los resultados

Qué debes documentar:

Registro de pruebas:

Fecha: 04.06.2026
Tester: [Tu nombre]
Sitio web: https://bwww.IRC-Coding.de

Funciones probadas:
- Formulario de login (/login)
- Función de búsqueda (/search)
- Perfil de usuario (/profile?id=123)

Resultados:
- Formulario de login: Seguro (no se encontró SQL Injection)
- Función de búsqueda: VULNERABLE en parámetro 'q'
- Perfil de usuario: Seguro

Detalles de la vulnerabilidad:
URL: /search?q=test'
Mensaje de error: "SQL syntax error"
Recomendación: Implementar Prepared Statements

Reporte de vulnerabilidades:

Vulnerabilidad: SQL Injection en función de búsqueda
Severidad: Alta
Función afectada: /search?q=[parameter]
Prueba: Ingreso de ' OR '1'='1 muestra todos los resultados
Impacto: Es posible acceder a todo el contenido de la base de datos

Checklist de pruebas:

  • Todos los formularios probados
  • Parámetros de URL revisados
  • Mensajes de error documentados
  • Capturas de pantalla tomadas
  • Pasos de reproducción anotados

Paso 5: Reparación y verificación

Acciones inmediatas:

  1. Implementar Prepared Statements
  2. Agregar validación de entrada
  3. Mejorar el manejo de errores (no mostrar errores SQL)
  4. Restringir permisos de base de datos

Aseguramiento de calidad:

  • Prueba nuevamente después de cada cambio
  • Configura escaneos automatizados
  • Realiza auditorías de seguridad periódicas

Estrategia a largo plazo:

  • Capacita a los desarrolladores (programación segura)
  • Code reviews enfocados en seguridad
  • Pruebas de seguridad automatizadas en el proceso CI/CD

Cómo recibir notificaciones sobre ataques de SQL Injection

Configurar monitoreo en tiempo real

WAF (Web Application Firewall):

  • Cloudflare WAF: Bloquea automáticamente solicitudes sospechosas
  • AWS WAF: Integración con funciones Lambda para reglas personalizadas
  • ModSecurity: WAF de código abierto con reglas de SQL Injection

Herramientas de análisis de logs:

  • ELK Stack (Elasticsearch, Logstash, Kibana): Análisis centralizado de logs
  • Splunk: Solución SIEM empresarial para alertas de seguridad
  • Graylog: Gestión de logs de código abierto

Herramientas de seguridad especializadas:

  • Fail2Ban: Bloquea direcciones IP tras actividades sospechosas
  • OSSEC: Sistema de detección de intrusiones basado en host
  • Snort: Sistema de detección de intrusiones de red

Configuración de notificaciones:

# Ejemplo para Fail2Ban con detección de SQL Injection
[Definition]
failregex = ^.*SQL syntax.*SELECT.*FROM.*$
            ^.*Warning.*mysql_fetch_array().*$
ignoreregex =

# Acción: Correo electrónico y bloqueo de IP
action = %(action_mwl)s
         %(action_block)s

Configurar dashboard de monitoreo

Métricas importantes:

  • Número de intentos de SQL Injection por hora
  • Direcciones IP bloqueadas
  • Consultas SQL fallidas
  • Errores de conexión a la base de datos

Reglas de alerta:

  • Notificación inmediata si hay más de 10 intentos de SQL Injection
  • Reporte semanal sobre incidentes de seguridad
  • Alerta crítica en accesos exitosos a la base de datos

Aseguramiento específico de frameworks

Seguridad en WordPress

Medidas específicas para WordPress:

// En wp-config.php
define('FORCE_SSL_ADMIN', true);
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true);

// Prepared Statements en WordPress
global $wpdb;
$user_id = get_current_user_id();
$results = $wpdb->get_results( 
    $wpdb->prepare( 
        "SELECT * FROM {$wpdb->prefix}usermeta WHERE user_id = %d", 
        $user_id 
    ) 
);

Plugins importantes:

  • Wordfence Security: Firewall y escaneo de malware
  • Sucuri Security: Hardening y logs de auditoría
  • iThemes Security: Monitoreo de cambios de archivos

Mejores prácticas en WordPress:

  • Realiza actualizaciones regulares
  • Usa contraseñas fuertes para la base de datos
  • Restringe wp-admin por dirección IP
  • Deshabilita XML-RPC si no lo necesitas

Seguridad en Laravel

Características específicas de Laravel:

// Eloquent ORM (automáticamente seguro)
$users = User::where('email', $request->email)->get();

// Query Builder con parameter binding
$users = DB::select('SELECT * FROM users WHERE email = ?', [$email]);

// Raw Queries con binding
$users = DB::select('SELECT * FROM users WHERE name = :name', ['name' => $name]);

Paquetes de seguridad para Laravel:

  • Laravel Security: Reglas de validación adicionales
  • Laravel Firewall: Filtrado de solicitudes
  • Laravel Audit: Logging de actividades

Configuración:

// config/database.php
'mysql' => [
    'strict' => true,
    'options' => [
        PDO::ATTR_EMULATE_PREPARES => false,
    ],
],

Seguridad en Astro

Aspectos específicos de Astro:

  • Static Site Generation: Sin conexión dinámica a base de datos
  • API Routes: Asegurar funciones serverless
  • Environment Variables: No incluir datos sensibles en código del cliente

Aseguramiento de rutas API:

// src/pages/api/search.js
import { query } from '@astrojs/db';

export async function GET({ url }) {
  const searchTerm = url.searchParams.get('q');
  
  // Validación de entrada
  if (!searchTerm || searchTerm.length > 100) {
    return new Response('Invalid input', { status: 400 });
  }
  
  // Prepared Statement con Astro DB
  const results = await query(
    'SELECT * FROM posts WHERE title LIKE ? LIMIT 10',
    [`%${searchTerm}%`]
  );
  
  return Response.json(results);
}

Mejores prácticas de seguridad en Astro:

  • Configura headers de Content Security Policy (CSP)
  • Implementa limitación de tasa de solicitudes para APIs
  • Usa variables de entorno para credenciales de base de datos
  • Actualiza dependencias regularmente

Seguridad en Node.js/React/Next.js

Protección del backend con Node.js:

// mysql2 con Prepared Statements
const mysql = require('mysql2/promise');

async function searchUsers(searchTerm) {
  const connection = await mysql.createConnection({
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_NAME
  });
  
  // Prepared Statement
  const [rows] = await connection.execute(
    'SELECT * FROM users WHERE username LIKE ?',
    [`%${searchTerm}%`]
  );
  
  await connection.end();
  return rows;
}

API Routes en Next.js:

// pages/api/search.js
import { query } from '../../lib/db';

export default async function handler(req, res) {
  if (req.method !== 'GET') {
    return res.status(405).json({ message: 'Method not allowed' });
  }
  
  const { q } = req.query;
  
  // Validación de entrada
  if (!q || typeof q !== 'string' || q.length > 100) {
    return res.status(400).json({ message: 'Invalid search term' });
  }
  
  try {
    const results = await query({
      query: 'SELECT * FROM posts WHERE title LIKE ? LIMIT 10',
      values: [`%${q}%`]
    });
    
    res.status(200).json(results);
  } catch (error) {
    console.error('Database error:', error);
    res.status(500).json({ message: 'Internal server error' });
  }
}

Seguridad en el frontend con React:

// Llamadas a API con validación de entrada
const searchPosts = async (searchTerm) => {
  // Validación en el lado del cliente
  if (!searchTerm || searchTerm.length > 100) {
    throw new Error('Invalid search term');
  }
  
  const response = await fetch(`/api/search?q=${encodeURIComponent(searchTerm)}`);
  
  if (!response.ok) {
    throw new Error('Search failed');
  }
  
  return response.json();
};

Paquetes de seguridad para Node.js:

  • Helmet: Seguridad de headers HTTP
  • express-rate-limit: Limitación de velocidad
  • helmet-csp: Content Security Policy
  • bcrypt: Hash de contraseñas
  • jsonwebtoken: Autenticación con JWT

Configuración de seguridad en Next.js:

// next.config.js
const helmet = require('helmet');

module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'X-Frame-Options',
            value: 'DENY'
          },
          {
            key: 'X-Content-Type-Options',
            value: 'nosniff'
          },
          {
            key: 'Referrer-Policy',
            value: 'origin-when-cross-origin'
          }
        ]
      }
    ];
  }
};

Principales fuentes

  1. https://owasp.org/www-community/attacks/SQL_Injection
  2. https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
  3. https://portswigger.net/web-security/sql-injection

Más artículos sobre SQL

SQL y la seguridad de bases de datos son fundamentales para construir aplicaciones robustas. Los siguientes artículos te ayudarán a dominar todos los aspectos de SQL y seguridad.

Seguridad y protección

Volver al blog
Share:

Entradas relacionadas