Tema 10
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.
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.
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:
Conviene distinguir dos niveles de validación:
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.
Una API recibe datos por múltiples canales, no solo por el cuerpo JSON. Todos deben tratarse como superficies de entrada:
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.
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:
Las blocklists pueden ser útiles como defensa adicional, pero no deberían ser la base de la validación.
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:
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:
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:
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.
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:
La defensa correcta es usar listas explícitas de campos aceptados y no confiar en deserialización automática sin control.
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:
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:
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:
Una parte importante de la validación no está en cada campo aislado, sino en su relación con otros. Algunos ejemplos:
Ignorar estas reglas relacionales deja a la API expuesta a estados incoherentes y abuso funcional.
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:
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:
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:
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.
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.