Tema 4
Toda aplicación web procesa datos que provienen de usuarios, navegadores, APIs, archivos o servicios externos. La seguridad depende en gran parte de cómo esos datos se validan, transforman, almacenan y devuelven. Tratar toda entrada como no confiable es una de las reglas más importantes del desarrollo seguro.
Una aplicación web recibe datos de muchas fuentes: formularios, URLs, cookies, cabeceras, parámetros JSON, archivos subidos por usuarios, webhooks, integraciones con terceros y valores guardados previamente en bases de datos. Desde la seguridad, todos esos datos deben considerarse potencialmente peligrosos hasta que la aplicación demuestre lo contrario.
Este principio es central porque muchas vulnerabilidades dependen justamente de procesar datos no confiables como si fueran válidos. Inyecciones, XSS, errores de lógica, deserialización peligrosa, abuso de funciones y exposición de información suelen comenzar con una entrada mal tratada.
Por eso la validación de entradas no es un detalle de programación. Es una frontera crítica entre el exterior y la lógica interna del sistema.
Decir que una entrada no es confiable no significa que siempre sea maliciosa. Significa que la aplicación no debe asumir automáticamente que tiene el formato correcto, que pertenece al usuario adecuado, que respeta el flujo de negocio o que puede usarse sin controles adicionales.
Una entrada puede ser peligrosa por varias razones:
Para validar bien, primero hay que saber de dónde llegan los datos.
| Fuente | Ejemplos | Riesgos típicos |
|---|---|---|
| URL y query string | IDs, filtros, búsquedas, paginación | Manipulación de parámetros, acceso indebido, inyecciones |
| Formularios | Registro, login, comentarios, contacto | Datos inesperados, scripts, valores fuera de rango |
| Cabeceras y cookies | Sesión, idioma, agente, origen | Suplantación, sesión insegura, confianza indebida |
| Cuerpo JSON o XML | APIs, móviles, SPAs | Estructuras alteradas, tipos inválidos, objetos inesperados |
| Archivos | Imágenes, PDFs, planillas, adjuntos | Contenido malicioso, tamaño excesivo, tipo falso |
| Servicios externos | Pagos, webhooks, autenticación federada | Datos inconsistentes o firmas mal verificadas |
Uno de los errores más comunes es pensar que validar consiste únicamente en revisar si un campo existe o si tiene una longitud mínima. En realidad, validar bien implica definir con precisión qué forma correcta debe tener un dato para un contexto particular.
Una validación robusta puede incluir:
Por ejemplo, validar un email no es lo mismo que validar un precio, un identificador interno, una fecha de nacimiento o un monto de transferencia.
En seguridad, suele ser más seguro definir qué entradas están permitidas que intentar adivinar todo lo que podría ser peligroso. Esta idea suele llamarse enfoque de lista permitida o allowlist.
Por ejemplo:
Este enfoque es más robusto que filtrar caracteres "sospechosos", porque los ataques reales suelen encontrar formas de saltar bloqueos incompletos.
La validación del lado cliente, por ejemplo con JavaScript o controles HTML, es útil para mejorar experiencia del usuario. Reduce errores simples y permite dar feedback inmediato. Pero no es una barrera de seguridad suficiente.
La razón es directa: el atacante controla el cliente. Puede desactivar JavaScript, modificar el formulario, construir peticiones manuales o usar herramientas para enviar datos arbitrarios. Por eso la validación que realmente protege debe ejecutarse en el servidor.
La regla práctica es esta:
Para razonar mejor sobre entradas conviene separar dos niveles de validación.
Ejemplo:
Muchas aplicaciones validan solo la forma del dato y olvidan validar si ese dato corresponde al estado real del sistema.
Sanitizar consiste en transformar una entrada para eliminar, neutralizar o normalizar contenido peligroso antes de usarla en un contexto determinado. Esto puede ser útil, pero debe entenderse bien: sanitizar no reemplaza validar.
Por ejemplo, si un campo admite texto libre para comentarios, puede ser razonable limpiarlo o normalizarlo antes de mostrarlo en HTML. Pero si un campo debería contener un número de documento, lo correcto no es "sanitizarlo hasta que pase", sino rechazar lo que no cumpla la regla esperada.
Otro error frecuente es mezclar sanitización con escape de salida. Escapar salida significa codificar datos al momento de incluirlos en un contexto específico, por ejemplo HTML, atributos, JavaScript, CSS o URLs, para evitar que sean interpretados como instrucciones.
Esto es clave para prevenir XSS. Incluso si un dato ya fue validado al ingresar, cuando se muestra debe tratarse según el contexto de salida.
La idea importante es que la seguridad completa suele requerir varias capas:
Antes de validar o comparar valores, muchas aplicaciones necesitan normalizar entradas. Esto implica transformar datos a una forma consistente para evitar errores lógicos o bypass de controles.
Ejemplos comunes:
La normalización importa porque un atacante puede intentar aprovechar diferencias de representación para saltar filtros o comparaciones.
Cuando la aplicación recibe JSON, XML o formularios complejos, conviene validar contra un esquema o contrato claro. Eso ayuda a limitar campos inesperados, tipos incorrectos y estructuras no previstas.
En APIs modernas, por ejemplo, no alcanza con verificar que el cuerpo tenga "algo". Debe definirse:
Este enfoque reduce ambigüedad y evita que la lógica de negocio procese objetos arbitrarios.
Muchos flujos web dependen de identificadores: IDs de usuarios, pedidos, facturas, cursos, mensajes o archivos. Desde la seguridad, estos valores deben tratarse con cuidado porque suelen ser manipulables.
Un error frecuente es validar que el identificador tenga "formato correcto", pero olvidar comprobar si el usuario autenticado realmente tiene permiso para acceder a ese recurso. Eso deriva en problemas como IDOR o control de acceso roto.
Por lo tanto, para un identificador no basta con validar tipo o formato. También debe verificarse contexto y autorización.
Los campos de texto libre, como comentarios, descripciones, mensajes o publicaciones, son especialmente delicados porque por definición admiten mucha variabilidad. En estos casos la aplicación debe decidir con claridad qué quiere permitir.
La pregunta correcta no es "¿cómo limpio todo HTML peligroso?" sino "¿realmente necesito aceptar HTML aquí?".
La subida de archivos merece atención especial porque un archivo no es solo un nombre y una extensión. Puede contener contenido activo, formatos maliciosos, tamaños problemáticos o tipos engañosos.
Un manejo seguro suele requerir:
El manejo seguro de datos no solo implica validar. También implica preguntarse si realmente hace falta recibir, guardar o mostrar cierta información. Cuantos más datos sensibles procesa una aplicación, mayor es su superficie de riesgo.
La minimización es un principio muy útil:
En muchos casos, la mejor defensa no es proteger mejor un dato innecesario, sino dejar de procesarlo.
| Escenario | Mala práctica | Mejor enfoque |
|---|---|---|
| Campo edad | Aceptar cualquier texto y luego intentar convertir | Exigir entero dentro de un rango razonable |
| ID de factura | Verificar que sea número y devolver la factura | Validar formato y además propiedad o permiso sobre ese recurso |
| Comentario público | Guardar HTML sin control y renderizarlo directamente | Tratar como texto o sanitizar con política definida y escapar salida |
| API de actualización | Aceptar cualquier campo que el cliente envíe | Definir esquema estricto y rechazar estructuras no previstas |
La validación de entradas y el manejo seguro de datos están conectados con muchas otras categorías de seguridad:
Por eso este tema es transversal a gran parte del curso.
Cuando una validación falla, la aplicación debe reaccionar de forma clara para el usuario pero sin revelar información sensible ni detalles internos innecesarios. Un buen mensaje orienta la corrección del dato; un mal mensaje expone lógica interna, nombres de tablas, trazas o reglas de negocio excesivamente detalladas.
En seguridad, el manejo de errores también forma parte del procesamiento seguro de entradas.
La validación de entradas, la sanitización y el manejo seguro de datos forman una de las bases más importantes de la seguridad en aplicaciones web. No son controles aislados, sino una disciplina continua que atraviesa formularios, APIs, archivos, integraciones y respuestas al usuario.
En el próximo tema estudiaremos una consecuencia directa de procesar datos de forma insegura: las fallas de inyección, incluyendo SQL Injection, NoSQL Injection y comandos del sistema.