Cuando un atacante va a por un formulario, no lo rellena como una persona normal. Envía código pensado para entrar en tus sistemas o robar datos. Puede enviar JavaScript para que se ejecute en el navegador de tus visitantes, comandos SQL para romper tu base de datos o contenido malicioso para causar daños. La validación y el saneamiento de entradas son las defensas que frenan estos ataques.
Qué vas a aprender: qué son la validación y el saneamiento de entradas, en qué se diferencian, cómo funcionan los ataques de inyección, qué protecciones sirven para cada tipo de dato y cómo aplicarlas en tus formularios.
¿Qué es la validación de entradas?
La validación de entradas consiste en comprobar que los datos enviados a tu formulario tienen el formato que esperas y cumplen tus requisitos. Es la primera línea de defensa contra las entradas maliciosas.
La validación responde a preguntas como estas: si esto es un correo electrónico o texto al azar, si es un número o una palabra, si este campo está vacío cuando no debería, y si el visitante ha escrito algo con sentido para este campo o algo sospechoso.
Ejemplos de lo que comprueba la validación:
- Un campo de correo debe contener una arroba y un dominio
- Un campo de teléfono debe contener solo dígitos y guiones
- Un campo numérico no debe contener letras
- Un campo obligatorio no debe estar vacío
- Un campo de contraseña debe cumplir una longitud mínima
La validación ocurre en dos sitios. En el dispositivo del visitante se llama validación en el cliente. En tu servidor se llama validación en el servidor. La validación en el cliente avisa al visitante al momento si se equivoca. La validación en el servidor es la que realmente protege frente a ataques, porque un atacante puede saltarse las comprobaciones del cliente.
¿Qué es el saneamiento de entradas?
El saneamiento consiste en eliminar o neutralizar todo lo peligroso de lo que escribe el usuario antes de guardarlo o procesarlo. Aunque los datos pasen la validación, aún pueden contener código o caracteres pensados para hacer daño.
Ejemplos de lo que hace el saneamiento:
- Elimina etiquetas HTML como `<script>` y `<img>` de los campos de texto
- Elimina caracteres especiales de SQL que podrían usarse para entrar en las bases de datos
- Escapa los caracteres especiales para que se traten como texto y no como código
- Limita la longitud de la entrada para evitar ataques de desbordamiento de búfer
La validación y el saneamiento se complementan, pero cumplen funciones distintas. La validación comprueba que los datos tienen el formato correcto. El saneamiento elimina todo lo peligroso aunque el formato sea técnicamente correcto.
Cómo funcionan los ataques de inyección
Inyección SQL
Un ataque de inyección SQL ocurre cuando un atacante escribe código SQL en un campo del formulario. Si el código de tu formulario no sanea esa entrada, el código SQL se ejecuta en tu base de datos.
Ejemplo: un formulario de acceso pide un correo electrónico. En lugar de su correo, el atacante envía:
' OR '1'='1 Si tu formulario no lo sanea, tu código podría ejecutar una consulta SQL como esta:
SELECT * FROM users WHERE email = '' OR '1'='1' La parte `OR '1'='1'` hace que la condición sea siempre verdadera, así que la consulta devuelve a todos los usuarios y no solo al de ese correo. El atacante ya se ha saltado el sistema de acceso.
Cross-Site Scripting (XSS)
Un ataque XSS ocurre cuando un atacante envía código JavaScript en un campo del formulario. Si el formulario no sanea ese código y lo guarda, el JavaScript se ejecuta en el navegador de cualquiera que vea esos datos más adelante.
Ejemplo: un formulario de comentarios acepta los comentarios de los usuarios. Un atacante envía:
<script>alert('hacked')</script> Si no se sanea y se guarda en la base de datos, cuando alguien abra la sección de comentarios se ejecutará el JavaScript y mostrará una alerta. Una versión más peligrosa podría robar cookies, redirigir a los visitantes a una página de phishing o extraer datos del formulario.
Inyección de comandos
Si los datos de tu formulario se usan en comandos del sistema (algo que ocurre en algunos sistemas de backend), un atacante puede inyectar comandos del sistema operativo.
Ejemplo: un campo del formulario se usa en un comando como este:
ffmpeg -i $filename output.mp4 Si `$filename` no se sanea y un atacante envía `;rm -rf /`, el comando pasa a ser:
ffmpeg -i ;rm -rf / output.mp4 El comando `rm -rf /` se ejecuta y borra archivos del sistema. Por eso los comandos del sistema nunca deben recibir entradas de usuario sin sanear.
Validación y saneamiento según el tipo de dato
Direcciones de correo electrónico
Validación: comprueba que la entrada sigue un patrón de correo (algo como texto@dominio.extensión). Confirma que solo tiene caracteres permitidos.
Saneamiento: elimina las etiquetas HTML y los caracteres especiales. Conserva solo caracteres alfanuméricos, puntos, guiones y la arroba.
Números de teléfono
Validación: comprueba que solo contiene dígitos, guiones, paréntesis y espacios. Verifica que la longitud es la correcta para el país esperado.
Saneamiento: elimina todos los caracteres no numéricos salvo guiones y paréntesis. Quita los ceros o espacios iniciales si hace falta.
Campos de texto (comentarios, nombres, direcciones)
Validación: comprueba que el campo no está vacío y que la longitud es razonable (no millones de caracteres).
Saneamiento: elimina o escapa las etiquetas HTML, el JavaScript y los caracteres especiales de SQL. Conserva solo texto plano y signos de puntuación básicos.
Números e importes
Validación: comprueba que la entrada es un número. En precios o cantidades, comprueba que sea un número positivo.
Saneamiento: elimina los caracteres no numéricos. Si hace falta, redondea al número correcto de decimales.
Contraseñas
Validación: comprueba la longitud mínima (al menos 8 caracteres) y, si quieres, exige una mezcla de mayúsculas, minúsculas, números y símbolos.
Saneamiento: no recortes ni modifiques las contraseñas. Deben guardarse tal cual (con hash, nunca en texto plano). Si quitas caracteres de una contraseña, los usuarios no podrán iniciar sesión.
Subida de archivos
Validación: comprueba que el tipo de archivo es el esperado (por ejemplo, solo PDF o solo imágenes). Comprueba que el tamaño no es excesivo.
Saneamiento: renombra el archivo para que los atacantes no puedan usar nombres especiales. Analiza el archivo en busca de malware. Guárdalo fuera de la raíz web para que no pueda ejecutarse como código.
Cómo aplicar la validación y el saneamiento
En el cliente (en el navegador)
Usa los atributos de validación de HTML5 para dar respuesta inmediata a los visitantes:
<input type="email" name="email" required> <input type="tel" name="phone" pattern="[0-9]{10}"> <input type="number" name="age" min="0" max="120"> Esto detecta los errores evidentes y mejora la experiencia de usuario. Pero la validación en el cliente se puede saltar, así que por sí sola no es una medida de seguridad.
En el servidor (en tu servidor)
Aquí es donde se juega la seguridad. Tu código de backend debe validar y sanear cada dato:
// Pseudo-code example if (email does not match email pattern) { reject the submission } // Remove HTML tags sanitized_comment = remove_html_tags(comment_text) // Escape special characters for database safe_name = escape_sql_characters(user_name) // Only then store the data store_in_database(safe_name, sanitized_comment) Usa consultas parametrizadas en las bases de datos
La mejor defensa contra la inyección SQL son las consultas parametrizadas (también llamadas sentencias preparadas). En lugar de meter la entrada del usuario directamente en una consulta SQL, usas marcadores de posición y pasas los datos por separado:
// Bad (vulnerable): query = "SELECT * FROM users WHERE email = '" + email + "'" // Good (safe): query = "SELECT * FROM users WHERE email = ?" execute(query, [email]) Con las consultas parametrizadas, el analizador de SQL sabe que la entrada del usuario son datos y no código. Aunque un atacante envíe código SQL, se trata como texto plano.
Usa bibliotecas y frameworks
No escribas el código de saneamiento desde cero. Usa bibliotecas consolidadas creadas para ello. En PHP, usa htmlspecialchars() o una biblioteca como HTML Purifier. En Python, usa el módulo `html` o una biblioteca como bleach. En Node.js, usa `express-validator` o algo similar. Estas bibliotecas están probadas y se actualizan para cubrir nuevos tipos de ataque.
Errores habituales de validación y saneamiento
Validar solo en el cliente. La validación en el cliente sirve para la experiencia de usuario, no para la seguridad. Un atacante puede saltársela. También tienes que validar en el servidor.
Bloquear caracteres peligrosos en lugar de permitir solo los seguros. Si intentas frenar la inyección SQL quitando punto y coma y comillas, los atacantes encontrarán la forma de esquivarlo. Es mejor crear una lista de los caracteres que esperas (en teléfonos, solo dígitos y guiones) y rechazar todo lo demás.
Fiarse del tipo de dato del campo. Si tienes un campo numérico, el navegador envía texto que parece un número. Tu servidor tiene que comprobar que de verdad es un número antes de usarlo. Nunca des por hecho que el tipo de dato es correcto.
Olvidar sanear los datos que se muestran. Aunque los datos se guarden de forma segura, si los muestras en una página web sin escapar el HTML, los atacantes pueden inyectar código que se ejecute en el navegador de los visitantes al verlos.
Sanear en el orden equivocado. Primero valida (¿tiene el formato correcto?) y después sanea (¿es seguro?). Si saneas y luego validas, puedes rechazar datos que en realidad eran seguros.
Qué hace WEMASY en la validación de entradas
WEMASY valida los campos del formulario de forma automática según el tipo de campo que elijas. En los campos de correo se comprueba que el formato sea válido. En los campos numéricos se comprueba que la entrada sea numérica. En los campos obligatorios se comprueba que haya contenido antes de enviar. En el servidor, WEMASY sanea toda la entrada para eliminar HTML, JavaScript y otro código peligroso antes de guardar los envíos. Tú eliges qué campos recoger y WEMASY se encarga de la validación y el saneamiento por detrás.
Consulta qué funciones de formularios incluye tu plan en la página de precios.