Cómo Auditar y Asegurar APIs Usando el OWASP API Security Top 10
Antes de comenzar
- Un inventario de APIs o al menos acceso a repositorios de código fuente, configuraciones de API gateway y documentación de servicios
- Documentación del modelo de autenticación y autorización para las APIs que deseas revisar
- Un entorno de prueba o staging donde puedas reproducir solicitudes de forma segura
- Logs de acceso, métricas o telemetría del gateway para las APIs bajo revisión
- Acceso básico al código fuente o especificaciones OpenAPI
Lo que aprenderás
- Construir o verificar un inventario real de APIs que incluya APIs públicas, internas, de socios y shadow
- Auditar la autorización a nivel de objeto, función y tenant de manera más efectiva
- Revisar validación de entrada, aplicación de esquemas y riesgos estilo mass-assignment
- Verificar rate limits, controles de abuso y rutas de amplificación de costos
- Encontrar exposición de datos sensibles en respuestas, logs, rutas de debug y llamadas a terceros
- Convertir hallazgos de auditoría en un plan de remediación priorizado que tu equipo pueda ejecutar
En esta página
La seguridad de APIs sigue siendo una de las formas más rápidas de sufrir una brecha porque las APIs exponen funciones de negocio, identificadores de objetos, acciones privilegiadas y datos sensibles de una manera que es fácil de automatizar a escala. Una pequeña falla de autorización en un endpoint a menudo puede reproducirse en miles de IDs, tenants u objetos. Por eso una revisión de API no debería detenerse en “usamos OAuth” o “el gateway tiene auth habilitado.”
Las integraciones modernas de IA y SaaS empeoran el problema. Muchos equipos ahora consumen APIs de terceros como si fueran sistemas internos de confianza, hacen proxy de prompts y resultados de IA a través de capas API, y añaden endpoints específicos de socios o beta más rápido de lo que el inventario puede seguir. Esa combinación crea exactamente los tipos de problemas que OWASP destaca en gestión impropia de inventario, consumo de recursos sin restricciones y consumo inseguro de APIs.
Este tutorial te da un flujo de trabajo de auditoría práctico basado en el OWASP API Security Top 10. Construirás un inventario de API utilizable, revisarás autorización y límites de tenant, inspeccionarás esquema y controles de abuso, verificarás exposición de datos, revisarás seguridad operacional y luego convertirás los hallazgos en un plan de remediación que corrija los mayores riesgos primero.
Paso 1: Construye o verifica tu inventario de APIs
No empieces con escaneo de vulnerabilidades. Empieza con visibilidad. Si no sabes qué APIs existen, quién las posee, qué versión está activa y quién puede alcanzarlas, ya estás en territorio API9.
Inventaría APIs públicas, internas, de socios y shadow
Construye un archivo de inventario único que responda estas preguntas para cada superficie API:
- ¿Cuál es el hostname o base path?
- ¿Es pública, interna, solo para socios o desconocida?
- ¿Quién la posee?
- ¿Qué modelo de auth usa?
- ¿En qué entorno está?
- ¿Hay un plan de deprecación documentado?
Archivo: api-inventory.csv
service,base_url,audience,owner,environment,auth,openapi_spec,current_version,status
payments-api,https://api.example.com/payments,public,payments-team,production,oauth2,openapi/payments.yaml,v2,active
admin-api,https://admin-api.internal.example.com,internal,platform-team,production,jwt-rbac,openapi/admin.yaml,v1,active
partner-orders,https://partners.example.com/orders,partner,bizops-team,production,api-key-plus-hmac,openapi/partner-orders.yaml,v1,active
legacy-beta,https://beta-api.example.com,unknown,unknown,production,unknown,missing,v0,investigate
Extrae inventario del código y tráfico, no solo de documentación
La documentación es un punto de partida, no la verdad. Para encontrar endpoints no documentados o obsoletos, combina búsqueda de código fuente y logs de acceso.
Búsqueda de ejemplo en código fuente:
grep -R "router\.\|app\.\|@RequestMapping\|@GetMapping\|@PostMapping" ./services
grep -R "openapi\|swagger" ./services
Inventario de ejemplo derivado de logs JSON de acceso:
jq -r '.host + "," + .method + "," + .path' access.log \
| sort -u \
| tee observed-routes.csv
Si tu gateway registra IDs de ruta o nombres de servicio upstream, extrae esos también.
Marca APIs shadow y obsoletas explícitamente
Una auditoría real necesita un apartado para endpoints que aún no comprendes completamente. No los fuerces en “interno” o “seguro” solo para que la hoja de cálculo se vea más limpia.
Crea una hoja de trabajo de revisión:
Archivo: shadow-api-review.md
# Shadow API Review
## beta-api.example.com
- Owner: unknown
- Environment: production
- OpenAPI spec: missing
- Auth model: unknown
- Last seen in traffic: 2026-03-08
- Public DNS: yes
- Action: classify or remove within 7 days
Inventaría versiones y flujos de datos
No inventaríes solo hostnames. Rastrea versiones y rutas de compartición de datos también.
Archivo: api-data-flows.yaml
payments-api:
inbound_clients:
- web-app
- mobile-app
outbound_dependencies:
- tax-provider
- fraud-provider
sensitive_data:
- customer-name
- partial-card-metadata
- billing-address
partner-orders:
inbound_clients:
- reseller-a
- reseller-b
outbound_dependencies:
- warehouse-api
sensitive_data:
- customer-email
- shipping-address
Ahora deberías tener un inventario de API funcional con rutas reales, audiencias, versiones, propietarios y flujos de datos.
Paso 2: Revisa autenticación y autorización
Esta es la parte de mayor rendimiento de la auditoría. Las mayores brechas de API normalmente provienen de verificaciones de autorización faltantes o inconsistentes, no de payloads exóticos.
Verifica la autorización a nivel de objeto
La autorización a nivel de objeto pregunta: ¿puede este llamador acceder a este objeto específico?
Si tu API carga un registro desde un ID, UUID, slug o clave foránea proporcionada por el usuario, necesitas una verificación de propiedad o política después de la búsqueda y antes de devolver o mutar el objeto.
Archivo: src/middleware/ownership.ts
import { Request, Response, NextFunction } from "express";
export function requireAccountOwnership(
fetchAccount: (accountId: string) => Promise<{ id: string; tenantId: string } | null>
) {
return async (req: Request, res: Response, next: NextFunction) => {
const accountId = req.params.accountId;
const account = await fetchAccount(accountId);
if (!account) {
return res.status(404).json({ error: "Not found" });
}
if (account.tenantId !== req.auth?.tenantId) {
return res.status(403).json({ error: "Forbidden" });
}
res.locals.account = account;
next();
};
}
Si tu ruta de código parece “leer ID del path, buscar objeto, devolver objeto,” pero nunca verifica tenant o propiedad, eso es una señal de alerta.
Verifica la autorización a nivel de función
La autorización a nivel de función pregunta: ¿puede este llamador acceder a esta función o acción?
Eso incluye rutas de admin, exportaciones, acciones masivas, flujos de aprobación y operaciones de negocio sensibles.
Archivo: src/middleware/requireScope.ts
import { Request, Response, NextFunction } from "express";
export function requireScope(requiredScope: string) {
return (req: Request, res: Response, next: NextFunction) => {
const scopes = req.auth?.scopes ?? [];
if (!scopes.includes(requiredScope)) {
return res.status(403).json({ error: "Missing required scope" });
}
next();
};
}
Y luego úsalo consistentemente:
app.post(
"/admin/users/:userId/suspend",
requireScope("admin:user:suspend"),
suspendUserHandler
);
Verifica la separación de tenants
Las APIs multi-tenant no deberían depender solo de un ID de tenant proporcionado por el cliente. El contexto de tenant debería venir de claims de auth verificados o búsqueda del lado del servidor, no de un header arbitrario que el cliente puede cambiar.
Mal patrón:
const tenantId = req.headers["x-tenant-id"];
Mejor patrón:
const tenantId = req.auth?.tenantId;
Luego verifica que cada ruta de acceso a datos se restrinja por ese tenant.
Verifica alcance de token, audiencia y expiración
Para cada mecanismo de auth, responde:
- ¿El token tiene verificación de audiencia?
- ¿Los scopes o roles son lo suficientemente estrechos?
- ¿La expiración es razonable?
- ¿Los refresh tokens se manejan por separado?
- ¿Un token puede acceder a APIs públicas y de admin?
Crea una matriz de auth simple:
Archivo: auth-matrix.yaml
payments-api:
auth_type: oauth2-jwt
audience: payments-api
scopes:
- payments:read
- payments:write
admin_scopes:
- payments:refund
max_access_token_lifetime_minutes: 15
admin-api:
auth_type: internal-jwt
audience: admin-api
scopes:
- admin:users:read
- admin:users:suspend
max_access_token_lifetime_minutes: 10
Ahora deberías saber si tus APIs aplican propiedad, permisos a nivel de acción, límites de tenant y reglas sensatas de alcance de tokens.
Paso 3: Revisa manejo de entrada y controles de esquema
Este paso es donde encuentras bugs estilo mass-assignment, validación débil de queries, parsing inseguro y divergencia de esquemas entre documentación y comportamiento real.
Valida bodies de solicitud contra un esquema
No dependas de sentencias if escritas a mano dispersas en controladores. Usa esquemas de solicitud explícitos para body, parámetros de ruta y parámetros de query.
Archivo: src/validation/updateProfile.ts
import { z } from "zod";
export const updateProfileSchema = z.object({
displayName: z.string().min(1).max(80),
marketingOptIn: z.boolean().optional(),
});
Archivo: src/middleware/validateBody.ts
import { AnyZodObject } from "zod";
import { Request, Response, NextFunction } from "express";
export function validateBody(schema: AnyZodObject) {
return (req: Request, res: Response, next: NextFunction) => {
const result = schema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
error: "Invalid request body",
details: result.error.flatten(),
});
}
req.body = result.data;
next();
};
}
Previene exceso de propiedades de objeto
Solo permite propiedades conocidas. No vincules JSON arbitrario a modelos ORM u objetos de actualización directamente.
Mal patrón:
await userRepository.update(req.params.userId, req.body);
Mejor patrón:
const allowed = {
displayName: req.body.displayName,
marketingOptIn: req.body.marketingOptIn,
};
await userRepository.update(req.params.userId, allowed);
Valida parámetros de query y paginación
Los parámetros de query son parte de la superficie de ataque también. Aplica rangos y defaults.
Archivo: src/validation/listOrdersQuery.ts
import { z } from "zod";
export const listOrdersQuerySchema = z.object({
limit: z.coerce.number().int().min(1).max(100).default(25),
offset: z.coerce.number().int().min(0).default(0),
status: z.enum(["pending", "paid", "failed"]).optional(),
});
Revisa deserialización y comportamiento del parser
Marca cualquier endpoint que:
- acepte objetos serializados crudos sin validación de esquema
- interprete dinámicamente operadores o nombres de campo desde JSON
- acepte queries GraphQL con controles débiles de complejidad
- acepte formatos de archivo inseguros o transformaciones de documentos
Alinea OpenAPI con el comportamiento real
Si tu especificación OpenAPI dice que solo displayName es escribible, pero el endpoint realmente acepta isAdmin, tenantId o accountBalance, tienes una brecha entre especificación y runtime.
Un extracto seguro de esquema de solicitud se ve así:
Archivo: openapi/profile.yaml
paths:
/v1/me/profile:
patch:
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
displayName:
type: string
maxLength: 80
marketingOptIn:
type: boolean
additionalProperties: false es una de las formas más fáciles de reducir la exposición accidental a nivel de propiedad cuando tu tooling y runtime lo soportan. Ahora deberías saber si tu API aplica esquemas de solicitud, limita propiedades escribibles, restringe parámetros de query y mantiene el comportamiento de runtime alineado con el contrato documentado.
Paso 4: Revisa rate limiting y controles de abuso
Aquí es donde revisas tanto el abuso clásico de API como las rutas modernas de amplificación de costos. No todos los casos de abuso son fuerza bruta. Algunos son abuso de paginación, abuso de exportación masiva, inundaciones de OTP, abuso de gasto de tokens de IA o automatización de flujos de trabajo de socios.
Crea perfiles de rate por ruta
No apliques un solo límite global a todo. Diferentes endpoints necesitan diferentes controles.
Archivo: rate-limit-profile.yaml
routes:
/v1/auth/login:
limit_per_minute: 5
burst: 2
key: ip_plus_username
/v1/password/reset:
limit_per_hour: 3
key: account_identifier
/v1/orders/search:
limit_per_minute: 30
burst: 10
key: token_subject
/v1/ai/generate:
limit_per_minute: 10
burst: 2
key: tenant_id
Añade límites a nivel de implementación
Archivo: src/middleware/rateLimit.ts
import rateLimit from "express-rate-limit";
export const loginRateLimit = rateLimit({
windowMs: 60 * 1000,
max: 5,
standardHeaders: true,
legacyHeaders: false,
keyGenerator: (req) => `${req.ip}:${req.body.username ?? "unknown"}`,
});
Revisa protección contra enumeración
Verifica si los atacantes pueden enumerar baratamente:
- IDs de usuario
- IDs de cuenta
- IDs de factura
- existencia de email
- flujos de restablecimiento de contraseña
- tokens de invitación
- registros de socios
Busca respuestas inconsistentes 404 vs 403, diferencias de timing y bodies de error diferentes para “existe” versus “no existe.”
Revisa abuso de bots y flujos de negocio
Identifica flujos con alto valor de negocio:
- creación de cupones
- creación de trials
- redención de tarjetas de regalo
- descargas masivas
- asignación de puestos
- endpoints de generación de IA
- endpoints de envío de OTP o email
Añade controles como:
- cuotas específicas por ruta
- claves de idempotencia
- CAPTCHA o desafío en flujos públicos
- alertas de anomalías en flujos de trabajo
- encolamiento para trabajos async de alto costo
Revisa rutas de amplificación de costos
Las APIs modernas a menudo proxean costos externos:
- SMS
- renderizado de documentos
- inferencia de IA
- geocodificación
- verificaciones de fraude
Si una ruta puede quemar dinero por solicitud, necesita controles más estrictos que un endpoint normal de solo lectura.
Ahora deberías saber qué endpoints necesitan controles de ráfaga más fuertes, resistencia a enumeración y cuotas conscientes de costos.
Paso 5: Revisa exposición de datos sensibles
Este paso captura APIs que técnicamente requieren auth pero aún exponen demasiados datos al llamador incorrecto, al sink de log incorrecto o al servicio downstream incorrecto.
Audita exposición de campos en respuestas
Para cada recurso sensible, define una allowlist de respuesta por rol o audiencia.
Archivo: src/serializers/customerSerializer.ts
type Customer = {
id: string;
email: string;
fullName: string;
internalRiskScore: number;
billingAddress: string;
};
export function serializeCustomerForSelf(customer: Customer) {
return {
id: customer.id,
email: customer.email,
fullName: customer.fullName,
billingAddress: customer.billingAddress,
};
}
export function serializeCustomerForSupport(customer: Customer) {
return {
id: customer.id,
email: customer.email,
fullName: customer.fullName,
};
}
No devuelvas entidades ORM completas directamente.
Redacta logs
Los logs de acceso y de aplicación a menudo filtran tokens, emails, números de cuenta o bodies de solicitud completos. Redacta antes de escribir.
Archivo: src/logging/redact.ts
export function redact(value: string): string {
return value
.replace(/Bearer\s+[A-Za-z0-9._-]+/g, "Bearer [REDACTED]")
.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, "[REDACTED_EMAIL]");
}
Y nunca registres bodies sensibles por defecto en rutas de auth, pagos o prompts de IA.
Elimina o asegura endpoints de debug
Revisa todas las rutas como:
/debug/internal/health/details/graphql-playground/swagger/metrics/__admin
Estas a menudo se dejan expuestas porque son “para ops,” pero la exposición en producción debe ser intencional y protegida.
Revisa reenvío a terceros
Si tu API reenvía prompts, payloads, datos de clientes o identificadores a proveedores SaaS externos, documenta y valida ese flujo explícitamente.
Archivo: third-party-forwarding-review.yaml
dependency: external-ai-provider
forwarded_fields:
- prompt
- account_tier
- locale
disallowed_fields:
- raw_access_token
- full_payment_card
- national_id
response_validation: required
timeout_seconds: 15
Ahora deberías saber si tus APIs devuelven datos en exceso, filtran información a logs, exponen superficies de debug o reenvían más datos de lo necesario a terceros.
Paso 6: Revisa seguridad operacional
Buenos controles a nivel de código aún fallan si el borde API está mal configurado o si no puedes detectar abuso a tiempo.
Revisa controles de gateway y reverse-proxy
Para cada borde API, verifica:
- TLS en todos los lugares donde debería estar
- solo métodos HTTP requeridos expuestos
- límites de tamaño de body
- política de timeout de solicitud y upstream
- propagación de request ID
- validación de esquema donde sea soportado
- allowlists de IP para APIs de socios o admin
Revisa monitoreo y alertas
Como mínimo, rastrea:
- picos de 401 y 403
- picos de 429
- latencia a nivel de ruta
- 5xx a nivel de ruta
- fallos de auth por endpoint
- barridos de IDs de objetos de alto volumen
- tráfico a versiones deprecadas
- uso inusual de socios
Crea un pequeño checklist de métricas:
Archivo: api-monitoring-checklist.md
# API Monitoring Checklist
- 401/403 dashboard per route
- 429 dashboard per route
- Token subject or tenant-based rate anomaly alerts
- Object enumeration detection on high-value routes
- Deprecated version traffic alerts
- Third-party dependency timeout alerts
Revisa versionamiento y deprecación
Cada versión debería tener:
- un propietario
- una audiencia
- una fecha de fin de vida
- un plan de comunicación de deprecación
- una verificación de retiro de tráfico
También puedes exponer headers de deprecación y sunset.
Archivo: src/middleware/deprecation.ts
import { Request, Response, NextFunction } from "express";
export function markDeprecated(res: Response) {
res.setHeader("Deprecation", "true");
res.setHeader("Sunset", "Wed, 30 Sep 2026 23:59:59 GMT");
res.setHeader("Link", '</docs/migrate-v2>; rel="deprecation"');
}
Revisa APIs de socios e internas también
Muchas organizaciones hacen un trabajo decente en APIs públicas y un trabajo débil en APIs “solo internas.” Las rutas internas, de socios y de admin deberían estar inventariadas, versionadas, monitoreadas y revisadas igualmente.
Ahora deberías saber si el borde API está endurecido, si puedes detectar abuso y si las versiones antiguas y rutas ocultas están siendo gestionadas deliberadamente.
Paso 7: Convierte hallazgos en un plan de remediación
Una auditoría de API solo importa si produce cambios. Los mejores planes de remediación separan la reducción rápida de riesgo del trabajo de diseño que necesita más tiempo.
Captura hallazgos en un formato estructurado
Archivo: api-audit-findings.yaml
findings:
- id: API-001
category: API1-BOLA
service: payments-api
endpoint: GET /v1/accounts/{accountId}
severity: critical
issue: Account lookup does not verify tenant ownership
quick_fix: Add tenant-scoped query and authorization middleware
owner: payments-team
due_in_days: 7
- id: API-002
category: API3-BOPLA
service: partner-orders
endpoint: PATCH /v1/orders/{id}
severity: high
issue: Writable object accepts undocumented internal fields
quick_fix: Add request schema with explicit allowlist
owner: bizops-team
due_in_days: 14
- id: API-003
category: API9-Inventory
service: legacy-beta
endpoint: unknown
severity: high
issue: Public beta host has no owner, no spec, and no retirement plan
quick_fix: Remove public exposure or assign owner immediately
owner: platform-team
due_in_days: 3
Separa correcciones rápidas de correcciones arquitectónicas
Buenas correcciones rápidas:
- añadir verificaciones de propiedad
- añadir verificaciones de scope faltantes
- restringir campos de respuesta
- añadir validación de esquema
- reducir límites de ruta
- deshabilitar endpoints de debug
- eliminar DNS público o enrutamiento obsoleto
Correcciones arquitectónicas a medio plazo:
- mover authz a una capa de políticas centralizada
- separar APIs de admin y públicas
- rediseñar aislamiento de tenant
- crear descubrimiento automatizado de inventario
- añadir controles de política de admisión o gateway
- estandarizar serializadores de respuesta y generación de esquemas
Asigna propietarios y fechas límite
Cada hallazgo necesita:
- un equipo propietario
- una severidad
- un enfoque de remediación
- una fecha objetivo
- un método de validación
Re-prueba la corrección
Una corrección no está completa hasta que puedas probar que la ruta de abuso ya no existe. Para cada hallazgo, guarda una prueba positiva y una negativa.
Archivo: tests/account-ownership.http
### Allowed: own tenant account
GET https://api.example.com/v1/accounts/acc_123
Authorization: Bearer {{tenant_a_token}}
### Blocked: another tenant account
GET https://api.example.com/v1/accounts/acc_999
Authorization: Bearer {{tenant_a_token}}
Problemas Comunes de Configuración
Auditar solo APIs públicas
Los equipos a menudo revisan el gateway público e ignoran superficies internas, de admin, de socios, beta y deprecadas. Eso deja algunas de las rutas de mayor riesgo fuera de la auditoría.
Asumir que autenticación equivale a autorización
Un token válido no es prueba de que el llamador debería acceder a un objeto, campo o función específica. Revisa authz por separado a niveles de objeto, campo, función y tenant.
Encontrar APIs shadow pero no eliminarlas
El trabajo de inventario solo reduce riesgo si las APIs obsoletas o desconocidas obtienen propiedad, protección o eliminación. Una hoja de cálculo sola no cierra la exposición.
Generar especificaciones OpenAPI pero no aplicarlas
Una especificación que no está atada a validación, pruebas o revisión puede divergir hasta convertirse en decoración. Prefiere validación de esquema y pruebas de contrato sobre especificaciones solo de documentación.
Corregir un endpoint en lugar del patrón
Si encuentras un problema de autorización a nivel de objeto, busca el mismo patrón de acceso en todo el código base. Las fallas de API a menudo se repiten por framework, serializador o patrón de repositorio.
Conclusión
Una auditoría de API fuerte comienza con inventario y termina con remediación priorizada. La ruta de revisión de mayor valor es normalmente: verificar todas las superficies API, verificar autorización de objeto y función, restringir esquemas y propiedades escribibles, asegurar controles de abuso, reducir exposición de datos sensibles y luego limpiar brechas operacionales como versiones ocultas y monitoreo débil.
Repite esta auditoría en un calendario, no solo después de incidentes. Una cadencia práctica es trimestral para APIs de alto riesgo, después de cambios importantes de auth o gateway, y siempre que añadas nuevas integraciones de socios, SaaS o dependientes de IA. Para mantener el inventario actualizado, vincula el descubrimiento de rutas a revisión de código, cambios de configuración de gateway y telemetría de tráfico en lugar de depender solo de actualizaciones de documentación.
El objetivo principal no es “pasar OWASP.” Es asegurarse de que tus APIs sean difíciles de enumerar, difíciles de abusar, difíciles de sobre-consumir y fáciles de entender y retirar cuando ya no deberían existir.
Artículos Relacionados
Asegurar Pipelines de Agentes de Codificación IA: Configuración de Sandbox, Límites de Permisos y Gates de Revisión Automatizados
Aprende a asegurar pipelines de agentes de codificación IA con detección, policy-as-code, escaneo de seguridad, ejecución de tests en sandbox, gates de revisión por niveles de riesgo y registro de auditoría.
Cómo Asegurar una App de IA Agéntica: Guardrails, Permisos de Herramientas y Logs de Auditoría
Aprende a asegurar una app de IA agéntica con guardrails, permisos por herramienta, aprobaciones de usuario y logs de auditoría usando una línea base práctica lista para producción.