Sanitización de entrada de usuario en PHP: errores y protección

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

«Yo solo escapo las comillas»: por qué tu código es vulnerable

\n\n

Si alguna vez has buscado en Google «How can I sanitize user input with PHP?», no estás solo. Esta pregunta en Stack Overflow acumula cientos de miles de visitas. Y no es para menos: la seguridad es uno de los temas más candentes en el desarrollo web.

\n\n

Pero aquí está la paradoja: la mayoría de las respuestas a esa pregunta están desactualizadas o son peligrosas. Los desarrolladores todavía escriben cosas como mysql_real_escape_string() (que desapareció hace 10 años) o simplemente eliminan caracteres «peligrosos». Spoiler: eso no funciona.

\n\n

En este artículo analizaremos los 5 errores principales de sanitización de entrada de usuario en PHP que convierten tu sitio en un colador, y te mostraremos cómo solucionarlos de una vez por todas.

\n\n

Error #1: Creer ciegamente en la «sanitización» como solución universal

\n\n

El error más grande es pensar que existe una función que «limpiará» cualquier tipo de dato. Este es el código típico de un principiante:

\n\n
<?php\n$name = $_POST['name'];\n$name = strip_tags($name);\n$name = addslashes($name);\n// ¿Ahora los datos son seguros? ¡No!\n?>
\n\n

El problema es que diferentes contextos requieren diferentes tratamientos. Validación (verificar el formato) y sanitización (limpiar) no son lo mismo. Y además está el escape de salida, que ocurre en otro lugar completamente distinto.

\n\n

Cómo hacerlo bien: Define qué haces con los datos en cada etapa. Para la base de datos es una cosa, para HTML es otra, para JSON es una tercera.

\n\n

Error #2: Usar funciones obsoletas (o aplicarlas incorrectamente)

\n\n

Repasemos los «dinosaurios» de la seguridad en PHP:

\n\n
    \n
  • mysql_real_escape_string() — eliminada en PHP 7.0. Olvídala.
  • \n
  • addslashes() — no protege contra todas las inyecciones SQL, especialmente con codificaciones multibyte.
  • \n
  • strip_tags() — elimina etiquetas, pero no escapa la salida. El XSS sigue siendo posible a través de atributos.
  • \n
\n\n

Ejemplo de código peligroso que todavía se encuentra:

\n\n
<?php\n$id = $_GET['id'];\n$id = addslashes($id);\n$query = "SELECT * FROM users WHERE id = '$id'";\n// Si id = 1 OR 1=1 — te hackearon\n?>
\n\n

Cómo hacerlo bien: Usa consultas preparadas (prepared statements). Es la única forma confiable de protegerte contra inyecciones SQL.

\n\n
<?php\n$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");\n$stmt->execute(['id' => $_GET['id']]);\n?>
\n\n

¿Ves? Sin sanitización para SQL. Solo parámetros. La base de datos se encarga sola de distinguir entre datos y comandos.

\n\n

Error #3: Confundir validación con sanitización

\n\n

Muchos piensan: «Eliminaré todos los caracteres sospechosos y será seguro». Pero eso rompe la lógica de la aplicación. Imagina que un usuario ingresa la contraseña P@ssw0rd! y tú eliminas los caracteres @ y !. La contraseña se convierte en Pssw0rd y el usuario ya no puede iniciar sesión.

\n\n

Validación — verifica si la entrada cumple con el formato esperado (email, número, URL). Si no, se rechaza.

\n\n

Sanitización — elimina o modifica caracteres no deseados, pero solo cuando es realmente necesario (por ejemplo, para nombres de archivo).

\n\n

Ejemplo de validación correcta de email:

\n\n
<?php\n$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);\nif ($email === false) {\n    // El email no es válido — no se guarda ni se muestra\n    echo "Ingresa un email válido";\n    exit;\n}\n// Ahora $email es una cadena segura para cualquier propósito\n?>
\n\n

Regla de oro: Si esperas un número — verifica que sea un número. Si esperas un email — verifica el formato. Todo lo demás, recházalo.

\n\n

Error #4: Ignorar el contexto de salida (XSS)

\n\n

Guardaste los datos en la base de datos usando consultas preparadas. ¡Bien, no hay inyecciones SQL! Pero aho

Blogs

Book Recommendations