Mitigación y Prevención de SQL Injection

📌 Introducción

Después de estudiar cómo ocurre y se explota una SQL Injection, es fundamental aprender cómo prevenirla y cómo mitigarla correctamente en nuestras aplicaciones. Las técnicas incluyen sanitización, validación, consultas parametrizadas, privilegios mínimos y controles adicionales como WAF.


🧹 Sanitización de entrada

Problema

Incluir directamente valores de entrada del usuario dentro de una consulta SQL permite que un atacante inyecte código.

Ejemplo vulnerable:

$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM logins WHERE username='". $username. "' 
          AND password = '" . $password . "';" ;

📌 Solución: escapar los caracteres especiales con mysqli_real_escape_string():

$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = mysqli_real_escape_string($conn, $_POST['password']);
Efecto

Escapa caracteres como ' y ", haciendo que pierdan su significado especial en SQL.


🧪 Validación de entrada

Otra defensa es validar que la entrada coincide con lo esperado.

Ejemplo vulnerable:

$q = "Select * from ports where port_code ilike '%" . $_GET["port_code"] . "%'";

Como port_code solo debería tener letras y espacios, se valida con regex:

$pattern = "/^[A-Za-z\s]+$/";
$code = $_GET["port_code"];

if(!preg_match($pattern, $code)) {
  die("Invalid input! Please try again.");
}
Patrón usado

  • [A-Za-z\s]+ → solo letras y espacios

  • Cualquier otro carácter → entrada rechazada


🔐 Privilegios del usuario

Principio clave

La cuenta conectada al DBMS debe tener el mínimo privilegio necesario.

Ejemplo de creación de un usuario seguro:

CREATE USER 'reader'@'localhost';
GRANT SELECT ON ilfreight.ports TO 'reader'@'localhost' 
IDENTIFIED BY 'p@ssw0Rd!!';

Al iniciar sesión como reader:

Ventaja

Incluso si existe SQL Injection, la explotación queda muy limitada por permisos.


🔥 Firewall de Aplicaciones Web (WAF)

Los WAF ayudan a detener ataques automáticamente, incluso cuando la lógica de la aplicación es insegura.

Ejemplos:

Importante

Un WAF no reemplaza una buena validación/sanitización interna, pero ayuda a bloquear cadenas sospechosas como:

  • INFORMATION_SCHEMA

  • UNION SELECT

  • ' OR 1=1 --


🔒 Consultas Parametrizadas (Prepared Statements)

Es la solución más efectiva para evitar SQL Injection.

Ejemplo seguro:

$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM logins WHERE username=? AND password=?";
$stmt = mysqli_prepare($conn, $query);
mysqli_stmt_bind_param($stmt, 'ss', $username, $password);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$row = mysqli_fetch_array($result);
mysqli_stmt_close($stmt);
Beneficio

Los valores no se interpretan como código SQL, sino como datos.


🏁 Conclusión