Cómo sanitizar la entrada del usuario en PHP: 7 errores fatales y sus soluciones

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

Introducción: ¿por qué su sitio en PHP podría ser hackeado ahora mismo?

\n

Imagine la situación: ha creado un sitio genial en PHP, un formulario de contacto, comentarios, un área personal. Todo funciona. Pero un día entra al panel de administración y está vacío. O peor aún: en el sitio aparece publicidad de un casino y Google ha bloqueado su recurso. ¿Le suena familiar? La raíz del mal es el procesamiento incorrecto de la entrada del usuario.

\n

La pregunta "How can I sanitize user input with PHP?" es una de las más populares en Stack Overflow. Miles de desarrolladores tropiezan una y otra vez con los mismos errores. En este artículo analizaremos los principales errores que cometen incluso los programadores experimentados y mostraremos cómo evitarlos. Aprenderá a protegerse contra XSS, inyecciones SQL y otros ataques. ¡Allá vamos!

\n\n

Error n.º 1: Usar mysql_real_escape_string() para todo

\n

La vieja escuela: muchos desarrolladores todavía piensan que si envuelven todos los datos en mysql_real_escape_string(), el problema está resuelto. Esto es un grave error. Esta función está diseñada solo para escapar cadenas en consultas SQL, y además para la extensión obsoleta mysql_*, que se eliminó ya en PHP 7.

\n

Ejemplo de código incorrecto:

\n
<?php\n$name = mysql_real_escape_string($_POST['name']);\n$query = "INSERT INTO users (name) VALUES ('$name')";\n$result = mysql_query($query);\n?>
\n

Por qué es malo:

\n
    \n
  • La función no protege contra ataques XSS (por ejemplo, inserción de JavaScript).
  • \n
  • La extensión mysql_* está obsoleta y no es segura.
  • \n
  • Se mezcla la lógica de escape con la lógica de negocio.
  • \n
\n

Cómo solucionarlo: use consultas preparadas (prepared statements) con PDO o MySQLi. Y para mostrar datos en pantalla, use una sanitización independiente.

\n\n

Error n.º 2: Ignorar los ataques XSS al mostrar datos

\n

El error más común. Recibe datos, los guarda en la base de datos y simplemente los muestra con echo o print. Voilà: un atacante puede insertar un script que robe cookies, redirija al usuario o dañe el diseño.

\n

Ejemplo de código vulnerable:

\n
<?php\necho "<p>Hola, " . $_GET['name'] . "!</p>";\n?>
\n

Si en la URL se pasa ?name=<script>alert('XSS')</script>, el script se ejecutará.

\n

Solución: use la función htmlspecialchars() con el parámetro ENT_QUOTES:

\n
<?php\n$name = htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');\necho "<p>Hola, " . $name . "!</p>";\n?>
\n

Importante: la sanitización debe hacerse justo en el momento de la salida, no al guardar. Si reemplaza caracteres en la base de datos, perderá los datos originales.

\n\n

Error n.º 3: Filtrado ciego con strip_tags()

\n

Muchos piensan: "Oh, simplemente eliminaré todas las etiquetas HTML y listo". Pero strip_tags() no es una panacea. Primero, solo elimina etiquetas, pero deja los atributos (por ejemplo, onclick). Segundo, si necesita permitir algunas etiquetas (como <b> o <i>), strip_tags() se vuelve incómodo.

\n

Ejemplo:

\n
<?php\n$comment = strip_tags($_POST['comment']);\necho $comment; // Eliminará <script>, pero dejará <a onclick="...">\n?>
\n

Solución: use htmlspecialchars() para texto normal o bibliotecas como HTML Purifier si necesita permitir ciertas etiquetas. HTML Purifier verifica no solo etiquetas, sino también atributos, estilos e incluso CSS.

\n\n

Error n.º 4: Falta de validación de email, URL y números

\n

La sanitización no es solo sobre XSS. Si espera un email y recibe la cadena "123", puede causar errores. O si guarda una URL sin verificar, un atacante puede insertar javascript:alert(1).

\n

Blogs

Book Recommendations