Tema 10

10. Validación de entradas, sanitización y manejo seguro de parámetros

Toda API expuesta recibe datos de origen no confiable. Eso incluye parámetros, cabeceras, cuerpos JSON, identificadores, filtros y archivos. Si esos datos no se validan y normalizan correctamente, la API puede ejecutar lógica incoherente, filtrar información, aceptar estados imposibles o convertirse en vehículo para inyecciones y abuso funcional.

Objetivo Controlar de forma estricta todo dato que entra a la API
Enfoque Contrato, validación, normalización y rechazo seguro
Resultado Reducir ambigüedad, errores de lógica e inyecciones

10.1 Introducción

Una API segura parte de una idea simple: todo lo que llega desde el cliente debe considerarse no confiable hasta ser validado. Esa regla incluye no solo texto libre o formularios, sino también campos que parecen obvios como IDs, fechas, números, arrays, flags booleanos, métodos, cabeceras y relaciones entre objetos.

Muchos incidentes de seguridad no surgen porque el atacante “rompe” el sistema, sino porque consigue que el backend acepte una entrada inesperada, inconsistente o maliciosa. A veces eso termina en inyección; otras veces en abuso de lógica, bypass de controles, exposición de datos o degradación del servicio.

Por eso, validar no es solo comprobar tipos. Es definir con precisión qué entradas son permitidas, en qué formato, con qué límites y bajo qué reglas de negocio.

10.2 Qué significa validar entradas

Validar entradas significa comprobar que cada dato recibido cumple el contrato esperado antes de ser utilizado por la lógica de negocio, persistencia, búsqueda, serialización o integración con otros sistemas.

Una validación robusta normalmente incluye:

  • Tipo correcto.
  • Formato permitido.
  • Longitud o tamaño máximo y mínimo.
  • Rango numérico válido.
  • Enumeración de valores permitidos cuando aplique.
  • Relación coherente con otros campos.
  • Compatibilidad con reglas de negocio y estado actual.
Validar no es “limpiar un poco”. Es decidir explícitamente qué entradas forman parte del contrato y rechazar lo demás.

10.3 Validación sintáctica versus validación semántica

Conviene distinguir dos niveles de validación:

  • Sintáctica: comprueba forma, tipo y estructura.
  • Semántica: comprueba significado y coherencia con el dominio.

Por ejemplo, que un campo sea una fecha válida pertenece al plano sintáctico. Que esa fecha no pueda estar en el pasado para una reserva futura pertenece al plano semántico. Una API segura necesita ambos niveles.

10.4 Dónde puede entrar dato no confiable

Una API recibe datos por múltiples canales, no solo por el cuerpo JSON. Todos deben tratarse como superficies de entrada:

  • Parámetros de path.
  • Query strings.
  • Cabeceras HTTP.
  • Cuerpo de la solicitud.
  • Cookies.
  • Archivos o contenido multipart.
  • Datos devueltos por servicios externos o callbacks.

Un error común es validar el body con detalle, pero asumir que path, query o headers son confiables o “más seguros”. No lo son.

10.5 El principio de allowlist

Siempre que sea posible, conviene definir lo permitido en lugar de intentar enumerar lo prohibido. Este enfoque se conoce como allowlist o validación positiva.

Ejemplos:

  • Aceptar solo ciertos estados válidos en un campo `status`.
  • Permitir únicamente formatos de fecha esperados.
  • Restringir ordenamientos a un conjunto conocido de columnas.
  • Limitar filtros a atributos documentados y soportados.

Las blocklists pueden ser útiles como defensa adicional, pero no deberían ser la base de la validación.

10.6 Normalización antes de decidir

Muchas entradas pueden representarse de varias maneras: mayúsculas y minúsculas, espacios, formatos alternativos, valores vacíos, listas repetidas o Unicode similar. Si la API no normaliza antes de validar o comparar, puede tomar decisiones inconsistentes.

Ejemplos de problemas:

  • Comparar emails sin un criterio uniforme.
  • Permitir duplicados lógicos por diferencias triviales de formato.
  • Bypass de reglas por espacios, encoding o valores equivalentes.
  • Fallas de autorización o negocio por IDs no normalizados.

10.7 Sanitización: qué es y qué no es

Sanitizar implica transformar o limpiar ciertos datos para que puedan manipularse de forma segura en un contexto particular. Pero sanitizar no reemplaza validar. Primero se debe definir qué entrada es aceptable; luego, cuando corresponde, adaptar su representación para un uso específico.

Ejemplos típicos de sanitización:

  • Escapar datos antes de renderizarlos en HTML.
  • Eliminar caracteres no permitidos en un identificador acotado.
  • Normalizar espacios o formato de un campo textual.
La sanitización es contextual. Un dato “limpio” para búsqueda no necesariamente es seguro para SQL, HTML, logs o nombres de archivo.

10.8 Validar por esquema

Una práctica útil en APIs es definir esquemas explícitos para las entradas. Esto ayuda a documentar el contrato y a rechazar estructuras inesperadas desde el principio.

Validar por esquema permite controlar:

  • Campos requeridos y opcionales.
  • Tipos de datos.
  • Estructuras anidadas.
  • Longitudes, rangos y patrones.
  • Campos desconocidos o no documentados.

El error frecuente es aceptar payloads flexibles “por comodidad”, y luego dejar que la lógica interna decida qué hacer con campos inesperados. Eso complica seguridad y mantenimiento.

10.9 Campos desconocidos y mass assignment

Cuando la API acepta más campos de los que el cliente realmente debería poder enviar, aparece un riesgo clásico: mass assignment. El cliente envía propiedades adicionales y el backend, por mapeo automático o lógica débil, termina aplicándolas al modelo interno.

Ejemplos peligrosos:

  • Enviar `isAdmin=true` o `role=admin` en una actualización de perfil.
  • Modificar estados internos como `approved`, `verified` o `internalNotes`.
  • Inyectar referencias o relaciones que la API no pretendía exponer.

La defensa correcta es usar listas explícitas de campos aceptados y no confiar en deserialización automática sin control.

10.10 Query parameters, filtros y ordenamientos

Los parámetros de consulta son especialmente sensibles porque suelen afectar búsqueda, ordenamiento, paginación y consumo de recursos. Si se aceptan sin reglas estrictas, pueden habilitar abuso, errores de lógica o inyecciones.

Puntos a controlar:

  • Qué filtros están permitidos.
  • Qué operadores acepta cada filtro.
  • Qué campos pueden usarse para ordenar.
  • Cuántos resultados se pueden pedir por página.
  • Cómo se manejan combinaciones incompatibles o costosas.

10.11 Validación de identificadores

Los identificadores merecen atención especial porque suelen ser puerta de entrada a recursos sensibles. Validar un ID no es solo revisar tipo o longitud; también implica asegurar que tenga sentido en el contexto y que no desencadene accesos indebidos o consultas caras.

Conviene validar:

  • Formato esperado.
  • Tamaño razonable.
  • Compatibilidad con el tipo de recurso.
  • Relación con el tenant, usuario o contexto activo.

10.12 Tipos numéricos, booleanos y fechas

Los tipos que parecen simples suelen generar errores sutiles. Un número puede estar fuera de rango, una fecha puede ser técnicamente válida pero imposible para el negocio, y un booleano puede representarse de múltiples maneras ambiguas.

Problemas comunes:

  • Permitir números negativos donde no corresponden.
  • Aceptar fechas absurdas o inconsistentes entre sí.
  • Convertir automáticamente valores ambiguos a booleanos.
  • Usar precisión o redondeo sin criterio en montos y cantidades.

10.13 Relaciones entre campos

Una parte importante de la validación no está en cada campo aislado, sino en su relación con otros. Algunos ejemplos:

  • La fecha de fin no puede ser anterior a la fecha de inicio.
  • Un descuento no puede superar el monto base.
  • Si `tipo=empresa`, ciertos campos adicionales son obligatorios.
  • No se puede enviar simultáneamente una referencia externa y una creación interna del mismo recurso.

Ignorar estas reglas relacionales deja a la API expuesta a estados incoherentes y abuso funcional.

10.14 Manejo de archivos y contenido binario

Si la API acepta archivos, la superficie de riesgo aumenta. No basta con validar extensión declarada. También deben controlarse tamaño, tipo real, cantidad, nombre, destino y tratamiento posterior del archivo.

Riesgos típicos:

  • Subida de archivos demasiado grandes para agotar recursos.
  • Tipos inesperados o peligrosos.
  • Nombres de archivo maliciosos o ambiguos.
  • Procesamiento posterior inseguro por terceros o pipelines internos.

10.15 Validación y errores seguros

Cuando una entrada no es válida, la API debería rechazarla de forma clara pero controlada. El cliente necesita saber qué parte del contrato falló, pero no conviene exponer detalles internos excesivos.

Un manejo seguro de errores de validación suele incluir:

  • Estructura consistente de respuesta.
  • Indicación del campo o regla incumplida sin revelar lógica interna innecesaria.
  • Código HTTP apropiado, normalmente `400` o similar según el caso.
  • Separación entre detalle útil para cliente y detalle técnico reservado a logs internos.

10.16 Validación en cliente versus validación en servidor

La validación del lado cliente puede mejorar experiencia de uso, pero nunca sustituye la validación del servidor. Todo control importante debe repetirse en backend porque el atacante puede omitir, alterar o reemplazar completamente el cliente.

La regla práctica es simple:

  • Frontend valida para usabilidad.
  • Backend valida para seguridad y consistencia real.

10.17 Integraciones externas y datos de terceros

No solo el cliente directo entrega datos no confiables. También las integraciones externas pueden enviar payloads inconsistentes, incompletos o maliciosos. Una API madura valida igual de estrictamente lo que recibe de webhooks, callbacks, APIs de terceros y colas externas.

Confiar “porque viene de un partner” es una mala práctica. La confianza operativa no reemplaza validación técnica.

10.18 Errores comunes en validación

  • Validar tipo pero no rango, longitud ni coherencia semántica.
  • Aceptar campos desconocidos por conveniencia.
  • Confiar en sanitización genérica como sustituto de validación.
  • No controlar parámetros de orden, filtro o paginación.
  • Depender del frontend para bloquear combinaciones inválidas.
  • Permitir estructuras anidadas o arrays sin límites.
  • No revisar el impacto de inputs sobre costo computacional.

10.19 Qué debes recordar de este tema

  • Todo dato que entra a la API debe tratarse como no confiable hasta ser validado.
  • Validar incluye tipo, formato, rango, tamaño, coherencia y reglas de negocio.
  • Sanitizar no reemplaza validar; es una operación contextual posterior.
  • Mass assignment, filtros inseguros y parámetros ambiguos son fuentes frecuentes de riesgo.
  • La validación fuerte reduce inyecciones, abuso funcional y estados incoherentes.

10.20 Conclusión

La validación de entradas es una de las defensas más importantes en una API REST porque define el perímetro lógico del contrato entre cliente y servidor. Cuando ese perímetro es difuso, la API queda expuesta a ambigüedad, estados inválidos, sobrecarga e inyecciones. Diseñar validaciones explícitas, coherentes y consistentes reduce gran parte de la superficie de ataque antes de que los datos lleguen a capas más sensibles del sistema.

En el próximo tema profundizaremos en las inyecciones en APIs: SQL, NoSQL, comandos, plantillas y serialización insegura, para ver cómo entradas mal controladas terminan convirtiéndose en ejecución o consulta maliciosa.