Examen de Especialista en Seguridad de la Información Registrado, primavera de Reiwa 6, tarde, pregunta 1 — alg=none de JWT, autorización de API y medidas provisionales de WAF

· Actualizado el: · · Especialista en Seguridad de la Información Registrado, Examen SC, API, Seguridad de API, JWT, Autenticación, Autorización, WAF, Log4Shell, Seguridad de la información, Vulnerabilidad, IPA

Historial de revisiones (primera versión, publicada el 6 Aug 2026)
Primera publicación
Citar este artículo(DOI (archivo registrado): 10.5281/zenodo.22175994)

Los DOI siguientes remiten a versiones ya archivadas y pueden diferir del texto actual. Para citar el texto actual, utilice la URL de esta página.

Go Komura (2026). Examen de Especialista en Seguridad de la Información Registrado, primavera de Reiwa 6, tarde, pregunta 1 — alg=none de JWT, autorización de API y medidas provisionales de WAF. KomuraSoft LLC. https://comcomponent.com/es/blog/sc-exam-r6s-pm-q1-api-security/

DOI (archivo registrado)
10.5281/zenodo.22175994
DOI (última versión registrada)
10.5281/zenodo.22175995

«Se verifica el JWT y, aun así, se puede suplantar a otra persona.» «El JWT es correcto y, aun así, se puede leer la información de otra persona.» Las dos afirmaciones se parecen, pero se corrigen en sitios distintos. La primera es un problema de verificación del token; la segunda, de autorización sobre los datos de destino.

La pregunta 1 de la tarde del examen de Especialista en Seguridad de la Información Registrado, primavera del año Reiwa 6 (2024), toma como tema una API invocada desde un smartphone y pide distinguir esas comprobaciones.1 En la primera mitad se tratan el JWT, el ID de usuario, los campos de actualización y el código de autenticación; en la segunda, una vulnerabilidad de biblioteca y un WAF.

Este artículo se apoya en el ejemplo oficial de respuestas y en el comentario de calificación, y explica cada punto en el orden «esencia de la respuesta → fundamento en el enunciado → diseño que se añade en la práctica». Léalo sin mezclar lo que hay que responder dentro del límite de caracteres del examen con las medidas que necesita un sistema real.23

1. Primero, la conclusión — el éxito de una verificación no permite omitir la siguiente

El principio que recorre este artículo es este: no convertir el éxito de la verificación anterior en motivo para omitir el siguiente límite de confianza. Un límite de confianza es la raya que decide en qué condiciones se puede confiar en un valor que llega de fuera.

Tener un JWT correcto no significa que se pueda leer la información de otra persona. Poder actualizar la información propia no significa que se pueda cambiar también el estado de facturación. La caducidad del código de autenticación y el WAF exigen, cada uno, su propia comprobación y su propia operación.

Mapa de las respuestas

La tabla siguiente recoge la esencia de las respuestas oficiales. Para las respuestas en prosa, confirme el límite de caracteres y el fundamento de cada pregunta en el capítulo correspondiente.2

Pregunta y espacio en blanco Esencia de la respuesta Explicación detallada
Pregunta 1, a Stateless Capítulo 3
Pregunta 2(1), b 500 segundos Capítulo 4
Pregunta 2(2) Verificar que el alg de la cabecera JWT no sea NONE Capítulo 5
Pregunta 2(3) Verificar que el ID de usuario del JWT coincida con mid Capítulo 6
Pregunta 2(4), c Módulo común P Capítulo 7
Pregunta 2(5), d Bloquear la cuenta cuando los fallos consecutivos superen el umbral Capítulo 8
Pregunta 3(1) Registrar y comprobar los accesos a index.html en el servidor de prueba Capítulo 9
Pregunta 3(2), e y f Ambos son Header Apartado 10.1
Pregunta 3(3) Una expresión regular que admita mayúsculas y minúsculas Apartado 10.2
Pregunta 3(4) Evitar el bloqueo por falsos positivos y examinar las alertas Apartado 10.3

Empiece por el capítulo 2 para fijar la estructura del problema y lea los capítulos 3 a 10 en el orden de las preguntas. La forma de redactar las respuestas está en el capítulo 12, y la lista de verificación para el diseño y la revisión de código en la práctica, en el capítulo 13.

En el diagrama, una línea continua marca una relación que siempre se cumple y una línea discontinua una relación condicional (las condiciones están en la explicación de cada relación en la página de detalle). La lista completa de relaciones (18 en total, con evidencia y grado de certeza) y las definiciones de los conceptos principales están reunidas en la página de detalle del mapa de conocimiento (en japonés). Datos: JSON-LD / Turtle

2. Estructura del problema — leer por separado las cinco comprobaciones

El escenario es la empresa G, que está a punto de ofrecer un nuevo servicio de salud. Los usuarios introducen comidas, peso y datos similares desde una aplicación para smartphone y reciben una evaluación de riesgos para la salud y consejos de menú. El sistema se construye en la nube y combina una pasarela de API, procesamiento dirigido por eventos y una base de datos administrada.

Los nombres de productos y servicios del enunciado están abstraídos. Este artículo no reproduce tal cual las figuras y tablas del cuadernillo; reformula la estructura necesaria para entender cada pregunta. Se distinguen los pasajes que recogen la esencia de las respuestas oficiales de las notas prácticas añadidas aquí.1

Visión de conjunto del problemaLeer el código de autenticación, el JWT, el ID de destino, los campos de actualización y la ejecución a partir de una entrada externa como comprobaciones distintas.Solicitud del usuarioComprobación del código de autenticaciónEmisión y verificación del JWTAPI de usuarioAutorización del mid de destinoAutorización del status de actualizaciónRegistrar la entrada externa en el registroBiblioteca vulnerableEjecución de código externo mediante JNDI

Figura 1: Desde la autenticación hasta las operaciones de la API y el tratamiento de registros, no hay un solo lugar en el que se confíe en un valor.

2.1. Separar autenticación, verificación del token y dos tipos de autorización

Tras confirmar la identidad con el código de autenticación y emitir y verificar el JWT, sigue quedando la autorización sobre los datos y sobre los campos. En la ruta que envía una entrada externa al registro también hace falta un límite que impida tratar esa entrada como una orden.

[ID de usuario y contraseña]
          |
          v
[Comprobación del código de 4 dígitos] ---- sin límite de intentos ----> fuerza bruta
          |
          v
[Emisión del JWT]
          |
          v
[Biblioteca JWT] ------- permite alg=none ------> alteración del ID de usuario
          |
          v
[API de usuario]
    |             |
    |             +-- pasar status tal cual ----> falla de autorización a nivel de propiedad
    |
    +-- confiar en mid -----------------------> falla de autorización a nivel de objeto

[Registrar la entrada externa en el registro]
          |
          v
[Biblioteca vulnerable] ---- JNDI/LDAP/HTTP ------> ejecución de código externo

Lo más importante aquí es la distinción siguiente.

Comprobación Qué pregunta Ejemplo que se rompe en este problema
Autenticación ¿Quién es usted? Fuerza bruta del código de 4 dígitos
Verificación del token ¿Esa identidad no ha sido alterada? alg=none
Autorización a nivel de objeto ¿Se puede acceder a los datos de ese usuario? Sustitución de mid
Autorización a nivel de propiedad ¿Se puede cambiar ese campo? status=paid
Límite entre entrada y ejecución ¿La entrada externa se interpreta como una orden? JNDI Lookup

El éxito de la comprobación anterior no es motivo para omitir la siguiente. Un usuario con un JWT correcto no tiene por qué poder leer los datos de otra persona. Un usuario que puede actualizar sus propios datos no tiene por qué poder cambiar también el estado de facturación.

Cuando se puede hacer esta separación por etapas, las respuestas de cada pregunta dejan de ser memorización.

Diferencia entre autenticación y autorizaciónConfirmar el sujeto no basta: hace falta otra comprobación que autorice a ese sujeto a operar sobre los datos o los campos de destino.Autenticación y verificación del tokenDeterminar de quién es la petición¿Se puede llegar a esos datos?¿Se puede cambiar ese campo?

Figura 2: Diferencia entre autenticación y autorización. La autenticación va primero, y la autorización es otra comprobación.

2.2. En la pregunta 2, distinguir por el valor que cambió el atacante

Los puntos de la pregunta 2 que se confunden con facilidad se ordenan por el valor que controló el atacante.

Ataque Valor que cambió el atacante Lugar en el que no se debía confiar Contramedida de raíz
Alteración del JWT El alg de la cabecera JWT y el ID de usuario del payload El algoritmo de verificación que declara el propio token Fijar los algoritmos permitidos en el servidor
Obtención de información de otra persona El mid de la solicitud El ID de destino indicado por el cliente Contrastar con el sujeto del JWT, o decidir el ID de destino a partir del JWT
Cambio a usuario de pago Un status fuera de especificación Todas las propiedades vinculadas automáticamente Convertir las propiedades actualizables en una lista de permitidos
Superación del código de 4 dígitos Candidatos de otp Intentos de autenticación ilimitados Introducir límite de fallos, retraso y evaluación de riesgo

Lo importante es no resumirlo todo como «validar los valores de entrada».

  • alg es la política del tratamiento criptográfico
  • mid es autorización a nivel de objeto
  • status es autorización a nivel de propiedad
  • otp es la resistencia a la adivinación en línea

Aunque estén en la misma solicitud HTTP, la razón por la que se protegen es distinta.

3. Pregunta 1 — stateless no impide conservar datos de negocio ni el número de fallos

La pregunta 1 pide una de las propiedades de diseño de una API RESTful: no gestionar sesión.

Respuesta: el espacio en blanco a es «stateless».2

3.1. Fundamento — cada solicitud reúne por sí sola la información necesaria para el tratamiento

Stateless significa que, aunque el servidor no recuerde el estado de conversación de la solicitud anterior, cada solicitud reúne por sí sola la información necesaria para el tratamiento. En este problema, la aplicación para smartphone adjunta un JWT en la cabecera Authorization de cada solicitud. El servidor verifica ese JWT e identifica al usuario de esa solicitud.

3.2. Punto fácil de malinterpretar — no se tiran los datos ni el número de fallos

Lo fácil de malinterpretar es leer stateless como «el servidor no retiene ningún estado». En la práctica se retienen, con normalidad, estados como los siguientes.

  • La base de datos que guarda información de usuario y datos de salud
  • El estado de facturación
  • El valor del código de autenticación, su caducidad y el número de fallos
  • La clave de firma del JWT
  • Si el diseño usa una lista de revocación, esa información de revocación
  • Registros y pistas de auditoría

Lo que no se retiene es el estado de sesión del servidor que solo sirve para continuar una conversación, como premisa de cada llamada a la API.

Además, ser stateless no eleva automáticamente la seguridad. Enviar el JWT en cada petición facilita el escalado horizontal, pero si la verificación del JWT es incorrecta, el error se extiende de forma uniforme a todos los nodos. La propiedad de la arquitectura y la corrección de la seguridad son cosas distintas.

Stateless y el estado que se conservaAunque cada solicitud se trate sin depender del historial de la conversación, se conservan estados como los datos de negocio o el número de fallos.Solicitud con JWTIdentificar al usuario solo con esa peticiónEjecutar el tratamiento y responderInformación de usuario, facturación, número de fallosNo hace falta depender de la conversación anterior

Figura 3: Eliminar la dependencia de la conversación y conservar el estado de negocio y de seguridad son compatibles.

4. Pregunta 2(1) — calcular el tiempo medio para superar el código de 4 dígitos

Respuesta: el espacio en blanco b es «500». La unidad es segundos.2

4.1. Fundamento — alinear número de candidatos, velocidad de intento y periodo de validez

La API de autenticación, si coinciden el ID de usuario y la contraseña, envía un número de 4 dígitos por correo. Después, si coinciden el ID de usuario y el código de 4 dígitos, emite un JWT. El código es válido durante 10 minutos desde su generación.

En el diagnóstico era posible probar 10 veces por segundo. Se pide en cuántos segundos se supera, de media.

El cálculo usa «la mitad del número de candidatos»

Los números de 4 dígitos, incluido el 0 inicial, son las 10.000 combinaciones siguientes.

0000, 0001, 0002, ... , 9999

Si la respuesta correcta se elige de forma uniforme y se prueba en orden sin repetición, el examen calcula el número medio de intentos como la mitad de los candidatos.

Intentos medios = 10.000 ÷ 2 = 5.000 veces
Tiempo medio    = 5.000 ÷ 10 veces/s = 500 segundos

Con esta aproximación se llega a los 500 segundos de la respuesta oficial. Si se promedia estrictamente desde el intento 1 hasta el 10.000, son 5.000,5 veces, pero aquí se sigue la respuesta del examen.

En el peor caso se tardan 1.000 segundos, pero lo que pregunta el problema es la media. Y el periodo de validez del código es de 600 segundos, más largo que los 500 segundos de tiempo medio de superación. Esa es la razón por la que se juzgó que «la probabilidad de superarlo es alta».

Escala temporal del código de autenticación de 4 dígitosEn la aproximación del examen la media es 500 segundos, y con intentos sin repetición se pueden examinar el 60 por ciento de los candidatos en los 600 segundos de validez.Hay 10000 candidatosLa media es unas 5000 vecesA 10 por segundo, unos 500 segundosMás corto que los 600 segundos de validezEn 600 segundos se confirman 6000 candidatos

Figura 4: Escala temporal del código de autenticación de 4 dígitos. Si se prueba de media la mitad de los candidatos, se acierta dentro del periodo de validez.

4.2. Nota práctica — no mirar solo el tiempo de caducidad, sino cuántas veces se puede intentar

La fuerza de un código de autenticación no se decide solo por el número de dígitos ni solo por el periodo de validez.

Número de intentos posibles durante el periodo de validez
= intentos por segundo × periodo de validez
= 10 × 600
= 6.000 veces

Si se prueban valores distintos en orden, se puede confirmar el 60 % de las 10.000 combinaciones dentro del periodo de validez. Aunque haya tiempo de caducidad, no basta si no se limita el número de intentos.

El NIST SP 800-63B vigente exige al menos 6 dígitos para un secreto de corta duración usado en autenticación fuera de banda, y hace obligatorio un límite de intentos si tiene menos de 64 bits. También pide no usar el correo electrónico para autenticación fuera de banda4. En el examen se responde dentro de la especificación dada de 4 dígitos y envío por correo, pero en un diseño nuevo en la práctica conviene revisar también esa premisa.

5. Pregunta 2(2) — no dejar que el atacante elija el método de verificación del JWT

Esencia de la respuesta

La pregunta pide, en 20 caracteres o menos cada una, «sobre qué datos y qué verificación realiza» la biblioteca Q una vez corregida.

El ejemplo de respuesta es el siguiente.

Elemento Esencia de la respuesta
Datos objeto de la verificación El valor indicado en el alg de la cabecera JWT
Contenido de la verificación Verificar que no sea NONE

Esa es la corrección directa de la vulnerabilidad del enunciado.2 «Verificar la firma» se quedaría en repetir un tratamiento que ya está implementado. El comentario de calificación también señala ese tipo de respuesta errónea.3

5.1. Fundamento — lo que falla es la «forma de elegir» una verificación de firma que ya existe

El JWT del problema consta de cabecera, payload y firma.

base64url(header).base64url(payload).base64url(signature)

En la cabecera se registraba RS256 como algoritmo de firma. En el payload entran el ID de usuario, el instante de emisión y la caducidad.

El diagnosticador cambió las dos cosas siguientes.

  1. Cambiar el alg de la cabecera de RS256 a NONE
  2. Cambiar el ID de usuario del payload al de otro usuario

Al enviar ese JWT, la verificación tenía éxito y se podía suplantar a otra persona.

Flujo del ataque JWT alg=noneSi el atacante cambia el método de verificación y el ID de usuario, una biblioteca que permite none acepta el JWT alterado.Obtener un JWT correctoCambiar alg a noneCambiar user a otro usuarioLa biblioteca omite la verificación de firmaAceptarlo como otro usuario

Figura 5: Flujo del ataque JWT alg=none. El atacante está eligiendo el algoritmo de verificación.

none no es un valor ajeno a la especificación

RFC 7519 define el «Unsecured JWT», un JWT sin firma ni cifrado, con alg igual a none5. Por tanto, el valor none no es algo que no exista en absoluto en la especificación.

El problema es que una API que solo debía aceptar JWT con firma aceptó el none indicado por el atacante.

El tratamiento vulnerable, escrito de forma conceptual, es el siguiente.

1. Leer la cabecera JWT
2. Mirar el alg escrito en la cabecera y elegir el método de verificación
3. Si alg es none, no verificar la firma
4. Confiar en el ID de usuario del payload

Se está dejando que una entrada controlada por el atacante elija la propia fuerza de la seguridad.

5.2. Nota práctica — fijar los algoritmos permitidos en el servidor

Aquí hay que separar la respuesta del examen de la recomendación práctica.

RFC 8725 establece que la biblioteca JWT debe hacer que el llamador indique el conjunto de algoritmos permitidos, y que no debe usar ninguno fuera de ese conjunto6. Es decir, una idea como la siguiente.

Mala idea:
  aceptar si token.header.alg != "none"

Buena idea:
  aceptar solo si está en serverConfig.allowedAlgorithms
  ejemplo: allowedAlgorithms = ["RS256"]

Aunque se rechace solo none, pueden quedar otros algoritmos débiles o una confusión de algoritmos que mezcle clave pública y clave simétrica. El principio es no ir añadiendo condiciones en forma negativa, sino fijar de forma estrecha las condiciones que se permiten.

En la verificación de un JWT, además del algoritmo, según el uso se confirman al menos los siguientes.

Elemento Qué confirmar
Firma Si se puede verificar con la clave y el algoritmo previstos
iss Si es un emisor de confianza
aud Si el token se emitió para esta API
exp Si está dentro del periodo de validez
nbf Si no es anterior al instante de inicio de uso
sub o ID de usuario Si es un sujeto válido en la aplicación
Tipo de token Si no se están confundiendo ID token, access token, etc.

En este problema la clave del payload es user, pero en la práctica se usa el sub estándar o se define con claridad el significado de un claim propio.

Verificación JWT segura y verificación JWT peligrosaNo decidir el método de verificación por lo que declara el token; verificar la firma y cada claim después de cumplir las condiciones permitidas en el servidor.NoSíRecibir el JWT¿Es un alg permitido por el servidor?RechazarVerificar la firma y cada claimTratarlo como sujeto verificadoTratamiento peligrosoOmitir la verificación con el none declarado

Figura 6: Verificación segura y verificación peligrosa. En la práctica se fijan de forma estrecha los algoritmos permitidos.

5.3. Separar firma y secreto — base64url no es cifrado

Hay otro malentendido habitual con JWT. La cabecera y el payload se expresan en base64url, pero eso no es cifrado. Cualquiera puede decodificarlos y leerlos.

Lo que garantiza la firma, y solo si la verificación tiene éxito, es que el contenido no se ha alterado después de la emisión. No significa que se pueda meter en el payload de un JWT firmado información personal que se quiera mantener en secreto.

La firma y el secreto del JWT son cosas distintasbase64url es una representación que también puede leer un tercero; la detección de alteración de la firma y la confidencialidad se piensan por separado.JWT con firmaLeer cabecera y payloadDecodificar base64urlEl contenido no queda en secretoVerificar correctamente la firmaComprobar que no se ha alterado

Figura 7: La firma se usa para detectar alteración, no para ocultar el contenido en una forma ilegible.

6. Pregunta 2(3) — un JWT correcto y un destino de operación correcto son cosas distintas

Esencia de la respuesta

La subrayado ② de la tabla 5 pregunta, en 40 caracteres o menos, el tratamiento que hay que añadir al procesamiento de llamada del módulo común P.

El ejemplo de respuesta es el siguiente.2

Un tratamiento que verifique si el ID de usuario incluido en el JWT coincide con el valor de mid

El lugar de añadido que indica la pregunta no es el propio módulo común P, sino el «procesamiento de llamada a P» que invoca P. Ahí se añade la comprobación de coincidencia entre JWT y mid.1

En la práctica, el objetivo es aplicar la autorización de forma coherente en la capa común por la que se llega a los datos, incluido el lado de P. Así es más fácil que la misma autorización cubra tanto GET como PUT, y también otras API que usen P en el futuro. Si solo se copia el tratamiento de comparación a cada pantalla o endpoint, aparecen omisiones de implementación.

6.1. Fundamento — el sujeto del JWT y el mid de destino se pasan por separado

Este es un ataque que no altera el JWT en sí.

La API de usuario recibe, en GET o PUT, un ID de usuario llamado mid. El módulo común P obtiene y actualiza en la base de datos la información de usuario asociada a ese mid.

La estructura del ataque es simple.

ID de usuario del JWT: user01    ← JWT firmado correctamente
mid de la solicitud: user02  ← lo cambia el atacante

La firma del JWT es correcta, así que la autenticación tiene éxito. Sin embargo, la API confía tal cual en mid=user02 y devuelve la información de user02.

Es un caso típico de lo que OWASP API Security Top 10 2023 llama Broken Object Level Authorization (BOLA). Cuando se accede a datos usando el ID de objeto indicado por el usuario, hay que confirmar cada vez la autorización sobre ese objeto7.

Ataque BOLAAunque el sujeto del JWT correcto y el mid de la solicitud sean distintos, se usa solo el mid y se devuelve la información de otra persona.JWT con firma correcta (user01)API de usuariomid cambiado (user02)No se contrasta con el sujetoObtener o actualizar los datos de user02

Figura 8: Ataque BOLA. La autenticación pasa, pero no se confirma la autorización.

6.2. Nota práctica — en una API solo para uno mismo, no recibir mid

Si la API solo obtiene y actualiza la información del propio usuario, no hace falta recibir el ID de usuario desde el cliente.

GET /users/me
Authorization: Bearer <JWT>

En el servidor se extrae el sujeto del JWT ya verificado.

principal = validateJwt(request.authorization)
userId = principal.subject
return repository.getUser(userId)

La actualización es igual.

principal = validateJwt(request.authorization)
input = validateProfileUpdate(request.body)
repository.updateProfile(
    userId = principal.subject,
    name = input.name,
    age = input.age
)

El tratamiento de comparación, si se escribe, protege. Pero si el diseño no recibe el ID de destino desde fuera, se reduce el propio tipo de error que consiste en olvidarse de escribir la comparación.

Si un administrador necesita operar sobre la información de otro usuario, se separa así.

PUT /users/me                  para el usuario general
PUT /admin/users/{userId}      para el administrador

En la vía de administrador se exigen otro permiso, un registro de auditoría y, si hace falta, una nueva autenticación. Se ve mejor el límite de la política de autorización que «añadir una excepción solo cuando el usuario es administrador en la API general».

Cómo evitar BOLAConfirmar que el sujeto verificado coincide con mid, o, en una API solo para uno mismo, derivar el destino del sujeto para reducir las omisiones de comparación.Se recibe midSíNoAPI solo para uno mismoSujeto del JWT verificadoCómo se decide el ID de destino¿Coincide con el sujeto?Operar sobre los datos propiosRechazarDerivar el ID de destino del sujeto

Figura 9: Cómo evitar BOLA. O no se recibe mid, o se contrasta con el sujeto del JWT.

6.3. Comprobación — «quién» y «qué se puede hacer» son cosas distintas

Tanto en el examen como en la práctica, la formulación siguiente resulta útil.

  • Autenticación: quién es
  • Autorización: qué puede hacer esa persona

Que la verificación de firma del JWT haya tenido éxito llega hasta «se puede confiar en el sujeto que representa este token». «Ese sujeto puede leer user02» hay que confirmarlo aparte.

7. Pregunta 2(4) — recibir solo los campos que se pueden actualizar

Respuesta: el espacio en blanco c es «módulo común P».2

7.1. Fundamento — a dónde se pasó un status fuera de especificación

En la especificación de la API de usuario se definen, como parámetros de actualización, los siguientes.

mid   ID de usuario
name  nombre
age   edad

Sin embargo, el diagnosticador añadió el valor siguiente, que no está en la especificación.

status=paid

Entonces, el estado de un usuario gratuito pasó a ser el de un usuario de pago.

Según el enunciado, el servicio L no verificaba los parámetros recibidos y los pasaba todos al módulo común P. P estaba hecho de forma que podía actualizar la base de datos tal cual.

Por tanto, el destino que recibe un valor fuera de especificación y puede actualizar incluso el estado del usuario es el módulo común P.

Mass AssignmentSi se pasa hasta un status fuera de especificación al módulo común y se actualiza, el usuario puede cambiar el estado de facturación.La especificación es mid, name y ageAñadir status=paidPasar todos los parámetros a PReflejarlos de golpe en los datos internosEl estado de facturación pasa a paid

Figura 10: Mass Assignment. Una propiedad fuera de especificación se refleja de golpe en el objeto interno.

7.2. Diferencia con BOLA — no se protege el destino, sino el campo de su interior

La sustitución de mid del capítulo anterior y la adición de status de ahora se parecen, pero el grano que se protege es distinto.

Vulnerabilidad Lo que cambia el atacante Lo que habría que confirmar
Sustitución de mid El objeto de destino Si este usuario puede acceder a este registro de usuario
Adición de status Una propiedad del interior del objeto Si este usuario puede cambiar este campo

OWASP API Security Top 10 2023 trata lo segundo como Broken Object Property Level Authorization, e incluye en esa clasificación el Mass Assignment anterior8.

7.3. Nota práctica — convertir el tipo de entrada de actualización en una lista de permitidos

Una implementación vulnerable es, en concepto, como la siguiente.

entity = repository.find(body.mid)
bindAllProperties(entity, body)
repository.save(entity)

Aunque en la pantalla solo haya campos de name y age, el atacante puede construir la solicitud HTTP directamente. Un campo que no está en la IU no es un límite de seguridad.

Una implementación segura deja explícitos los campos actualizables.

input = parseExactSchema(body, fields = ["name", "age"])

entity = repository.find(authenticatedUserId)
entity.name = input.name
entity.age  = input.age
repository.save(entity)

Aquí importan dos cosas.

  1. En el tipo de entrada de actualización, poner solo los campos que el usuario puede cambiar
  2. No ignorar los campos desconocidos fuera de especificación, sino, a ser posible, rechazarlos como error

Si se ignoran en silencio los campos desconocidos, se oculta que el ataque ha fallado, pero se pasan por alto errores de implementación del cliente y señales de ataque. Si no hay un motivo de compatibilidad, rechazar con un esquema estricto facilita la investigación.

Autorización a nivel de campoLimitar el tipo de entrada de actualización a name y age, y actualizar el estado de facturación por una vía exclusiva a partir de una notificación de pago verificada.SíNoPetición de actualización de perfil¿Solo name y age?Actualizar solo los campos permitidosRechazar los campos desconocidosNotificación de pago verificadaContrastar paymentId y evitar duplicadosActualizar status por una vía exclusiva

Figura 11: Autorización a nivel de campo. Se limitan los campos actualizables con una lista de permitidos y el estado de facturación se cambia por otra vía.

7.4. El estado de facturación solo se cambia a partir de un resultado de pago verificado

status=paid no es una parte del perfil del usuario. Es un estado que se deriva de un hecho del lado del servidor: que el pago ha tenido éxito.

Actualización del perfil del usuario
  -> solo se pueden cambiar name / age

Notificación verificada del servicio de pago
  -> contrastar paymentId
  -> evitar el tratamiento duplicado
  -> cambiar status a paid

Aunque se guarde en la misma columna de la base de datos, el permiso y la vía para cambiarlo son distintos. Si se usa la entidad interna tal cual como tipo de entrada de la API externa, ese límite desaparece.

7.5. En un componente común, incluir también autorización y restricción de entrada

En este problema aparecen dos componentes comunes: la biblioteca de gestión de JWT Q y el módulo común P.

Un componente común tiene ventajas grandes.

  • Si se corrige un solo lugar, la corrección se refleja en todas las API que lo usan
  • No hace falta duplicar la implementación de autorización o verificación en cada función
  • Se puede concentrar el objeto de las pruebas
  • Se puede unificar el formato de registros y auditoría

Por otro lado, el error también se extiende a todo.

  • Si la biblioteca Q acepta alg=none, todas las API que usan JWT quedan en peligro
  • Si el módulo común P acepta un mid o un status arbitrarios, quedan en peligro tanto GET como PUT
  • Si la biblioteca vulnerable H se usa en la base, varias rutas que escriben cabeceras HTTP en el registro se convierten en superficie de ataque

Por tanto, lo que hay que comúnizar no es el simple acceso a datos. Hay que comúnizar las invariantes de seguridad y verificar con rigor ese componente común por sí solo.

Por ejemplo, el contrato de P queda así.

P.getOwnUser(authenticatedSubject)
P.updateOwnProfile(authenticatedSubject, ProfileUpdate{name, age})

Es más seguro no exponer tal cual, al llamador general, una API de bajo nivel como la siguiente.

P.getUser(arbitraryMid)
P.updateUser(arbitraryMap)

La segunda solo hace falta en vías limitadas, como el tratamiento de administración. Si se reparte a todas las API la libertad de bajo nivel, el diseño espera que cada llamador la use bien cada vez.

Estrechar el contrato del componente comúnSi se incluyen la autorización y el tipo de entrada en el contrato del componente común, se reduce la dependencia de que el llamador lo use bien cada vez.API para el usuario generalSujeto verificado y DTO de actualizaciónUnificar la autorización en el componente comúnOperar sobre los datos permitidosOperación con ID arbitrario y Map arbitrarioSepararla a una vía limitada, como la de administraciónProbar el componente común con rigor

Figura 12: Lo que se comúniza no es solo el acceso a datos, sino las condiciones de autorización y de entrada que hay que proteger.

8. Pregunta 2(5) — contar los fallos y detener la fuerza bruta

Frente a la fuerza bruta del código de 4 dígitos, se responde, en 30 caracteres o menos, el tratamiento que entra en el espacio en blanco d de la tabla 5. El umbral es 10.

El ejemplo de respuesta es el siguiente.2

Un tratamiento que bloquee la cuenta cuando el número de fallos consecutivos supere el umbral

8.1. Fundamento — el número de fallos es un estado necesario para una decisión de seguridad

Esto no contradice el stateless de la pregunta 1. No retener el estado de conversación de las llamadas a la API como sesión de servidor, y persistir el número de fallos necesario para una decisión de seguridad, son cosas distintas.

Con o sin límite de intentosRetener el número de fallos y bloquear al superar el umbral detiene la adivinación en línea ilimitada.SíNoFallo al contrastar el códigoActualizar el número de fallos de la cuenta¿Se ha superado el umbral?Bloquear la cuentaPermitir los intentos restantesSin límite, se puede seguir probando

Figura 13: Con o sin límite de intentos. El límite de fallos detiene de forma práctica la fuerza bruta.

8.2. Nota práctica — prepararse también para el cierre por bloqueo

El límite de intentos por cuenta es necesario, pero si el atacante conoce el ID de otro usuario, puede fallar a propósito hasta superar el umbral y cerrar al usuario legítimo. Por eso, en la práctica se combinan los siguientes.

Control Papel
Número de fallos por cuenta Detener la fuerza bruta contra una sola cuenta
Tiempo de espera escalonado Permitir un error de escritura del usuario legítimo y, a la vez, bajar la velocidad del ataque
Control por IP de origen, dispositivo, ASN, etc. Contener un ataque que prueba pocas veces en muchas cuentas
Evaluación basada en riesgo Restringir con más fuerza una región, un dispositivo o una velocidad distintos de lo habitual
Notificación al usuario Permitir darse cuenta de un ataque o de un error de operación
Procedimiento de recuperación seguro Que el canal para desbloquear no se convierta en vía de ataque

Además, no se debe volver a 0 el número de fallos al reenviar el código. Si no, el atacante puede revivir el cupo de intentos cada vez que llama a la API de reenvío. El NIST SP 800-63B vigente también pide no reiniciar el número de fallos aunque se genere un nuevo secreto de autenticación4.

8.3. Proteger como un conjunto también la reemisión, la reutilización y la API de envío

En el enunciado el eje es la caducidad, pero en la práctica también hace falta lo siguiente.

  • Invalidar de inmediato un código que ha tenido éxito
  • Rechazar la reutilización del mismo código
  • No dejar el propio código en el registro
  • Hacer que la respuesta no permita inferir si el usuario existe a partir del éxito o el fallo al contrastar el código
  • Poner también un límite de intentos en la API de envío del código

Si se usa un secreto corto, no se puede dejar la seguridad solo en la generación aleatoria.

Contramedidas del código de autenticaciónAdemás del número de candidatos y de la caducidad, se combinan la retención del número de intentos, la invalidación tras el éxito, la notificación y el procedimiento de recuperación.SíNoEmitir o reemitir el códigoNo reiniciar el número de fallosContrastar limitando el número y la velocidad¿Ha tenido éxito el contraste?Invalidar el código de inmediatoRegistro de fallos, retraso, bloqueoNotificación y procedimiento de recuperación seguroLimitar también la API de envío y no registrar el código

Figura 14: Contramedidas del código de autenticación. Además del número de dígitos y del tiempo de caducidad, se combinan el control de intentos y la operación.

9. Pregunta 3(1) — confirmar la ejecución de la orden de verificación en el registro de acceso

Esencia de la respuesta

La pregunta 3(1) pide qué hay que implementar en el servidor de prueba para poder confirmar que se ha ejecutado el comando.

El ejemplo de respuesta es el siguiente.

Un mecanismo que registre y compruebe los accesos a index.html del servidor de prueba2

9.1. Fundamento — observar que se ha llegado hasta la última orden de verificación

Tras el inicio del servicio, se publica una vulnerabilidad grave V en la biblioteca de código abierto H, de uso extendido. El flujo del enunciado es el siguiente.

  1. El atacante envía una cadena que incluye un JNDI Lookup en una cabecera HTTP
  2. El servidor objetivo escribe ese valor en el registro
  3. La biblioteca vulnerable evalúa el JNDI Lookup y consulta un servidor LDAP de ataque
  4. La respuesta LDAP devuelve la URL de un servidor HTTP de ataque
  5. El servidor objetivo obtiene el archivo de clase y ejecuta el comando

Se puede leer como un ataque de tipo Log4Shell (CVE-2021-44228) con el nombre propio oculto. La explicación de Apache también lo describe como una vulnerabilidad que, si el atacante puede controlar un mensaje de registro o un parámetro, permite ejecutar código arbitrario cargado desde un servidor LDAP9.

Flujo de confirmación de una vulnerabilidad de tipo Log4ShellAdemás de la referencia JNDI y de la obtención de la clase, se confirma en el registro la obtención de index.html provocada por el comando de verificación.Entrada externa en una cabecera HTTPTratamiento de registro del servidor objetivoConsulta LDAP mediante JNDIRecibir la URL de obtención de la claseEl servidor objetivo obtiene la claseEl servidor objetivo ejecuta la orden de verificaciónObtener index.html del servidor de pruebaRegistrar y comprobar ese acceso

Figura 15: Flujo de confirmación de una vulnerabilidad de tipo Log4Shell. No se usa una orden destructiva: se confirma el alcance con el registro de un acceso HTTP.

La orden de verificación solo provoca un acceso HTTP inofensivo

La empresa G ejecuta un código de verificación que no afecta al sistema y comprueba si se puede explotar la vulnerabilidad V desde fuera. La orden que realiza el código de verificación es solo obtener el index.html del servidor de prueba.

Si en el registro de acceso del servidor web queda un GET desde el servidor objetivo, se puede confirmar que, al menos, ha pasado la cadena siguiente.

Solicitud HTTP externa
  -> tratamiento de registro
  -> JNDI Lookup
  -> respuesta LDAP
  -> obtención de la clase
  -> ejecución del comando de verificación
  -> acceso HTTP al servidor de prueba

9.2. Por qué no basta con una visualización en pantalla, sino con el registro del servidor de prueba

El objetivo del ataque es un servidor. No tiene por qué aparecer un cambio en la pantalla del navegador del usuario. Además, aunque exista la vulnerabilidad, la comunicación saliente intermedia puede detenerse en un cortafuegos.

Si se registra el acceso en el lado del servidor de prueba, queda una evidencia observable de que se ha llegado al exterior desde el servidor objetivo.

9.3. Nota práctica — obtener aprobación y confirmar con el menor efecto secundario

Cuando se hace una verificación del mismo tipo en la práctica, hay que cumplir siempre lo siguiente.

  • Obtener una aprobación explícita del propietario del sistema objetivo
  • Usar un método de verificación sin impacto en producción, o con un impacto aceptable
  • No usar órdenes destructivas de escritura, borrado o cambio de configuración
  • Gestionar el dominio o el servidor de verificación en la propia organización
  • Registrar el instante de verificación, el origen, el objetivo y la devolución de llamada esperada
  • Tras la verificación, retirar los servidores LDAP o HTTP temporales y las credenciales

«Confirmar la ejecución de código arbitrario» y «ejecutar un código arbitrario peligroso» no son lo mismo. Se deja en el menor efecto secundario que cumpla el objetivo.

Limitar la verificación al menor efecto secundarioObtener aprobación, decidir un método de confirmación inofensivo y las condiciones de observación, y retirar el entorno de verificación y las credenciales tras la ejecución.Aprobación explícita del propietarioDecidir el impacto y las condiciones de observaciónRegistrar el acceso en un servidor bajo controlContrastar con el instante y el origen esperadosRetirar el entorno de verificación y las credencialesNo escribir, borrar ni cambiar la configuración

Figura 16: Decidir primero el hecho que se quiere observar, e incluir en el procedimiento de verificación la confirmación inofensiva y la limpieza posterior.

10. Preguntas 3(2) a 3(4) — decidir el lugar de inspección, el patrón y el comportamiento del WAF

10.1. Pregunta 3(2) — el objeto de inspección es Header en los dos casos

El WAF del servicio N permite elegir como objeto de inspección GET, POST, PUT, ANY, Header, COOKIE y Multipart.

El código de ataque entra en el valor de una cabecera HTTP llamada x-api-version. Por tanto, los espacios en blanco e y f de la tabla 6 son, ambos, Header.2

El fundamento es el lugar en el que está la cadena de ataque

Aquí el problema no es tanto el conocimiento general como leer el flujo de datos del enunciado.

Lugar de la cadena de ataque:
  cabecera x-api-version
          |
          v
Objeto de inspección del WAF:
  Header

El ANY de este problema es una indicación que inspecciona los valores de parámetro de todos los métodos, distinta del Header que inspecciona cabeceras.1

No es un parámetro GET ni el cuerpo POST. No se elige «ANY porque parece un ataque» al ver la lista de funciones del WAF: se responde el lugar del enunciado en el que el atacante metió el valor.

Elegir el lugar de inspección del WAFEl objeto de inspección del WAF se decide no por el nombre del ataque, sino por el lugar del enunciado en el que se almacenó la cadena de ataque.Leer el lugar de almacenamiento de la cadena de ataqueCabecera x-api-versionEl objeto de inspección es HeaderPasar a un patrón que incluya mayúsculas y minúsculasANY son los parámetros de todos los métodos

Figura 17: No se conjetura a partir del nombre del ataque: se hace corresponder el lugar de almacenamiento, la cabecera, con el objeto de inspección.

10.2. Pregunta 3(3) — permitir mayúsculas y minúsculas en cada carácter

La primera propuesta era, en concepto, la regla siguiente.

Header  \Wjndi\W  bloquear
Header  \Wldap\W  bloquear

Sin embargo, si se intercambian mayúsculas y minúsculas como en jNdI, se puede eludir un patrón que solo usa minúsculas.

El ejemplo de respuesta de la pregunta 3(3) es uno de los siguientes.2

\W[jJ][nN][dD][iI]\W
\W(j|J)(n|N)(d|D)(i|I)\W

En el cuadernillo, la barra invertida puede verse como el signo del yen en un entorno japonés, pero en la expresión regular es \W. \W coincide con un carácter que no sea letra, dígito ni subrayado. En la sintaxis de JNDI Lookup aparecen, antes y después de jndi, caracteres que no son de palabra, como ${ o :, y se incluyen para verlos.

Con la misma idea se puede hacer que el lado de ldap ignore mayúsculas y minúsculas.

\W[lL][dD][aA][pP]\W

10.3. Pregunta 3(4) — usar la detección para evitar un bloqueo erróneo

Sobre las reglas de WAF modificadas, el especialista registrado Z aconseja que, durante un periodo determinado tras el inicio de la operación en producción, el comportamiento sea «detección» y no «bloqueo».

La pregunta pide, en 25 caracteres o menos cada una, la ventaja de ponerlo en detección y el contenido que hay que llevar a cabo para minimizar el daño.

El ejemplo de respuesta es el siguiente.2

Elemento Esencia de la respuesta
Ventaja Se puede evitar el bloqueo por un falso positivo
Contenido que hay que llevar a cabo Al recibir una alerta, examinar si se trata de un ataque

Fundamento — la detección va en un mismo conjunto con una operación que examina las alertas

En el modo de detección, el tráfico que coincide con la regla se deja pasar, se registra y se emite una alerta. Aunque en una llamada normal a la API entre por casualidad la cadena jndi o ldap, no se detiene de golpe el negocio.

A cambio, en el lado de operación hace falta lo siguiente.

Recepción de la alerta
   |
   v
Confirmar la solicitud objetivo
   |
   +-- comunicación normal -> estrechar la regla, considerar una condición de excepción
   |
   +-- ataque     -> aislar el objetivo, preservar registros, investigar el impacto, pasar al bloqueo

Si nadie mira las alertas, el modo de detección no tiene efecto de defensa. La detección va en un mismo conjunto con una operación que observa y decide.

10.4. Nota práctica — observar, ajustar y pasar al bloqueo

El procedimiento habitual de introducción es el siguiente.

  1. Aplicar el modo de detección al tráfico real
  2. Clasificar falsos positivos y detecciones correctas
  3. Ajustar la cabecera objetivo, la ruta, la API, el límite de caracteres, etc.
  4. Confirmar que el impacto sobre la comunicación normal es aceptable
  5. Pasar al modo de bloqueo
  6. Supervisar el número de bloqueos y el impacto en el negocio

Sin embargo, este es el principio en tiempo de paz. Si la vulnerabilidad es grave, ya se está explotando y no hay un medio alternativo, a veces se juzga que el daño de una infracción es mayor que la parada por un falso positivo, y se bloquea desde el principio. En la situación del examen, para confirmar que el servicio se puede seguir usando como hasta ahora, se elige primero la detección.

Del modo de detección al modo de bloqueo del WAFExaminar las alertas durante la detección, ajustar los falsos positivos y tratar el ataque, y seguir supervisando también después del bloqueo.Falso positivoAtaqueObservar el tráfico en modo de detección¿Cuál es el contenido de la alerta?Ajustar la regla o la condición de excepciónAislar, preservar registros, investigar el impactoPasar al bloqueoConfirmar el impacto sobre la comunicación normalSupervisar el número de bloqueos y el impacto en el negocio

Figura 18: De la detección al bloqueo. Primero se observa y se ajusta, se confirma que el impacto es aceptable y se pasa al bloqueo.

11. Respuesta práctica a una vulnerabilidad — ganar tiempo con el WAF y avanzar la actualización y la investigación

En el enunciado, en el sitio oficial de la biblioteca H todavía no había versión corregida ni medida provisional, y las reglas de WAF exhaustivas del proveedor de la nube tardaban hasta 72 horas. Por eso la empresa G confirma el impacto por sí misma y, al menos con los patrones ya conocidos, se defiende de forma temporal.

Lo que preguntó el examen son las reglas provisionales de WAF y su operación, pero el WAF no corrige la vulnerabilidad en sí. La confirmación del impacto, la mitigación provisional y la corrección de raíz se pueden avanzar en paralelo en lo que no hace falta esperar. El conjunto de la respuesta, incluida la nota práctica, es el siguiente.

Etapa Objetivo Respuesta en este problema y en la práctica
Confirmación del impacto Juzgar si la propia organización está realmente en peligro Confirmar con una devolución de llamada inofensiva si se puede explotar desde fuera
Mitigación provisional Ganar tiempo hasta la corrección Reglas de WAF, detección y bloqueo, restricción de la comunicación saliente
Corrección de raíz Eliminar la causa vulnerable Actualizar a la versión corregida de la biblioteca
Confirmación posterior Investigar si ya se había explotado Investigación de registros de WAF, de la aplicación, de DNS, del proxy, etc.
Prevención de repetición Acelerar la decisión la próxima vez Inventario de dependencias, SBOM, procedimiento de actualización, vía de contacto

11.1. No tomar la regla provisional como una defensa completa contra Log4Shell

El examen pide la expresión regular que corresponde al método de elusión mostrado en el enunciado. En un ataque real puede haber deformaciones difíciles de cubrir solo con una firma: división de la cadena, otro Lookup, codificación, otro protocolo, etc.

Por tanto, el lugar que ocupa en la práctica es el siguiente.

  1. Detener de forma provisional, con el WAF, el patrón de ataque ya conocido
  2. Investigar si la biblioteca afectada está realmente incluida
  3. Restringir LDAP, RMI y la comunicación HTTP saliente innecesaria
  4. Actualizar a la versión corregida
  5. Tras la actualización, revisar los registros e investigar si ha habido una infracción

El WAF es la capa que gana tiempo hasta que sale la versión corregida.

Lugar que ocupa el WAFLa detección deja pasar el tráfico y observa; el bloqueo y la restricción de la comunicación saliente mitigan, y la causa de raíz se elimina con la actualización.Publicación de una vulnerabilidad graveConfirmación del impacto y respuesta provisionalObtener registros y alertas con la detecciónBloqueo y restricción de la comunicación salienteAjustar y tratar a partir de la observaciónActualizar a la versión corregida de la bibliotecaConfirmar a posteriori si ha habido una infracción

Figura 19: Lugar que ocupa el WAF. El WAF gana tiempo hasta que sale la versión corregida; la contramedida de raíz es la actualización.

11.2. Preparación en tiempo de paz — conocer las bibliotecas que se usan y dónde están desplegadas

En el enunciado, aunque la empresa G pregunta a la empresa F si se usa la biblioteca H, hace falta un análisis detallado de la configuración y la respuesta tarda.

En la práctica, si se empieza a buscar archivos JAR solo después de publicarse una vulnerabilidad grave, la respuesta se retrasa. Al menos habría que tener, desde tiempo de paz, lo siguiente.

  • Lista de dependencias directas y transitivas
  • Componentes y versiones que realmente incluye el artefacto distribuido
  • A qué servicio, contenedor o equipo está desplegado
  • El procedimiento para actualizar una biblioteca dependiente, volver a construir y volver a distribuir
  • La vía de contacto que aprueba un cambio de emergencia
  • Los destinos de comunicación saliente permitidos y el impacto de detenerlos
  • El lugar de conservación de los registros y el método de búsqueda

El SBOM no es un fin. Es un índice para responder en poco tiempo a «esta vulnerabilidad, ¿a qué sistema en ejecución afecta?».

Vincular las dependencias con el sistema en ejecuciónCorrespondencia, desde tiempo de paz, entre los componentes dependientes y el destino de distribución, para acelerar la investigación y la decisión de actualización tras publicarse una vulnerabilidad.Lista de dependencias directas y transitivasVersión real del artefacto distribuidoServicios en ejecución y destino de despliegueJuzgar el objetivo afectado en poco tiempoAprobación, reconstrucción y redistribuciónConocer también destinos de comunicación y lugar de los registros

Figura 20: El SBOM no tiene como fin recogerse: es un índice para decidir con rapidez el destino afectado y el método de actualización.

11.3. Confirmación posterior — no dar por terminada la investigación de infracción solo con actualizar

Es posible que el ataque ya se hubiera recibido alrededor de la publicación de la vulnerabilidad. Actualizar a la versión corregida detiene la explotación futura, pero no borra unas credenciales ya comprometidas ni una puerta trasera ya instalada.

En un tipo Log4Shell se investigan, al menos, los puntos de vista siguientes.

  • Solicitudes HTTP que contienen cadenas sospechosas que indican JNDI o LDAP
  • Comunicación desde el servidor de aplicaciones hacia LDAP, RMI o HTTP externos
  • Arranque de un proceso hijo distinto de lo habitual
  • Creación de JAR, class, scripts o ejecutables sospechosos
  • Acceso a credenciales de la nube o a variables de entorno
  • Cambios de autenticación o de permiso y envíos al exterior, antes y después de la actualización

Es importante no afirmar «no ha habido ataque» solo con los registros del WAF. Hay vías internas que no pasan por el WAF, y registros que no se conservaron en el pasado.

Separar la actualización y la investigación de infracciónImpedir la explotación futura con la actualización a la versión corregida, e investigar la posibilidad de una infracción ya ocurrida, son necesidades distintas.Actualizar a la versión corregidaDetener la explotación futuraInvestigar los registros de antes y después de la actualizaciónContrastar comunicación, procesos y archivosConfirmar credenciales y envíos al exteriorUna infracción pasada no desaparece

Figura 21: Avanzar por separado la corrección de la causa y la investigación de una infracción ya ocurrida.

12. Cómo redactar la respuesta — responder la diferencia con la especificación, con los términos del enunciado

Este problema es, más que un problema de conocimiento, un problema de leer la diferencia entre especificación e implementación.

12.1 Separar la «especificación» y la «implementación» de la tabla

En el problema de status, un valor que no está en la especificación de la API pasa en la implementación.

Especificación:
  mid / name / age

Implementación:
  enviar todos los parámetros recibidos a P

Si se ve esta diferencia, se entiende que el espacio en blanco c es el módulo común P.

12.2 Trazar una línea en el valor que cambió el atacante

Los valores cambiados en cada ataque son los siguientes.

  • El alg de la cabecera JWT
  • El ID de usuario del payload JWT
  • El mid del parámetro de la API
  • Un status fuera de especificación
  • El otp de la API de autenticación
  • La cabecera HTTP x-api-version

Casi todas las preguntas preguntan «dónde debería verificarse ese valor».

12.3 Devolver la respuesta a los términos del enunciado

En la práctica se puede hablar de «BOLA», «Mass Assignment» o «rate limiting». Sin embargo, lo que pide la pregunta es un tratamiento concreto ajustado a la estructura del enunciado.

Mal ejemplo:

Realizar la autorización de forma adecuada.

Buen ejemplo:

Verificar si el ID de usuario incluido en el JWT coincide con el valor de mid.

Mal ejemplo:

Aplicar una contramedida de fuerza bruta.

Buen ejemplo:

Bloquear la cuenta cuando el número de fallos consecutivos supere el umbral.

Conocer el nombre abstracto no basta para una respuesta puntuable dentro del límite de caracteres.

12.4 En el WAF, seguir «dónde entró»

El objeto de inspección del WAF no se conjetura a partir del tipo de ataque: se decide a partir del lugar de almacenamiento de la cadena de ataque.

Se metió en la cabecera x-api-version
        ↓
El objeto de inspección es Header

El comentario de calificación indica que la tasa de aciertos del conjunto es media, y que las de la pregunta 2(2) y la pregunta 3(1) son algo bajas.3 Que la tasa de aciertos de la pregunta 3(1) fuera algo baja se debe también a que hubo muchas respuestas que no encajaban con el flujo de ataque de la figura 6. Solo con reescribir el procedimiento de ataque en flechas se ve qué hay que observar.

Volver del enunciado a la respuestaSeguir la diferencia entre especificación e implementación, el valor cambiado y el tratamiento en el que se confió, y escribir un tratamiento concreto con los términos del enunciado.Alinear especificación e implementaciónIdentificar el valor cambiadoSeguir dónde se confióDecidir el tratamiento que hay que añadirDevolverlo a los términos y al número de caracteres del enunciado

Figura 22: No se memorizan términos: se sigue el flujo del valor y se responde como un tratamiento concreto.

13. Lista de verificación para una revisión de API en la práctica

Esta es una lista de verificación para llevar este problema a una revisión real de diseño y de código.

Verificación de JWT

  • Los algoritmos de firma permitidos están fijados en la configuración del servidor
  • Se rechazan none y los algoritmos no previstos
  • Se verifican, según el uso, la firma, iss, aud, exp y nbf
  • No se confunden ID token, access token y refresh token
  • Hay un procedimiento para la rotación de claves y para la revocación
  • En el payload del JWT no se mete información que debería permanecer en secreto

Autorización a nivel de objeto

  • Si se cambia el ID de la solicitud, no se llega a los datos de otra persona
  • Hay autorización en listado, detalle, actualización, borrado y descarga
  • La autorización se aplica no en la pantalla, sino en la capa común por la que se llega a los datos
  • En una API solo para uno mismo, se ha considerado derivar el ID de destino del token
  • Las operaciones de administrador tienen una política distinta de la API del usuario general

Autorización a nivel de propiedad

  • El tipo de entrada externa y la entidad de la base de datos están separados
  • Los campos actualizables se enumeran en una lista de permitidos
  • Las propiedades fuera de especificación se rechazan o se auditan
  • Estados como permiso, facturación, aprobación u propietario no se pueden cambiar desde la entrada del usuario
  • La respuesta tampoco incluye propiedades confidenciales innecesarias

Intentos de autenticación

  • Hay un límite de fallos por cuenta
  • Hay un retraso escalonado o un control por origen
  • El número de fallos no se reinicia al reemitir el código
  • El código de autenticación se puede usar solo una vez
  • El código de autenticación y la contraseña no se dejan en el registro
  • El procedimiento de desbloqueo y recuperación no se ha convertido en otra vía de autenticación débil

Vulnerabilidad grave de una biblioteca dependiente

  • Se puede hacer corresponder el servicio en ejecución con la versión de la dependencia
  • Hay un procedimiento para verificar el impacto de forma inofensiva
  • Se pueden aplicar medidas provisionales como WAF o restricción de la comunicación saliente
  • Hay una operación en la que un responsable confirma las alertas de detección
  • Hay una vía de publicación de emergencia para actualizar a la versión corregida
  • Se investiga en los registros la posibilidad de explotación anterior a la actualización
La revisión prueba lo que viene después del caso normalAdemás del éxito de una petición normal, se confirman por separado el cambio de ID o de campo y los intentos repetidos, y se verifica la contramedida de la capa común.Confirmar el éxito de una petición normalConfirmar cambiando solo el ID de destinoConfirmar añadiendo un campo de actualización desconocidoRepetir el fallo de autenticación y la reemisiónConfirmar el rechazo, el registro y la recuperaciónTratar cada una como una comprobación distinta

Figura 23: Partir del éxito del caso normal y confirmar si cada límite distinto puede rechazar de verdad.

14. Resumen — no omitir el siguiente límite de confianza

La pregunta 1 de la tarde de la primavera del año Reiwa 6 es un problema que pide leer, uno a uno, los puntos de seguridad de una API.

Usar JWT no significa una autenticación segura. Si se deja que el atacante elija el algoritmo de firma, se puede reescribir el ID de usuario.

Que la firma del JWT sea correcta no significa una autorización correcta. Si se confía en el mid de la solicitud, un usuario legítimo puede acceder a la información de otra persona.

Poder actualizar el propio objeto no significa que se puedan cambiar todas las propiedades. Si se vincula automáticamente un estado interno como status, se pueden reescribir el permiso o el estado de facturación.

Que el código de autenticación tenga caducidad no significa que sea fuerte frente a la fuerza bruta. Hay que calcular el número de candidatos y la velocidad de intento, y limitar el número de fallos.

Meter reglas en el WAF no significa haber corregido la vulnerabilidad. Se gana tiempo con la detección y el bloqueo, se confirma el impacto y, al final, se actualiza la biblioteca.

Tabla de correspondencia entre vulnerabilidades y contramedidasPreparar una contramedida por cada límite: token e intentos de autenticación, destino y campos de actualización, y ejecución a partir de una entrada externa.Separar los límites en los que se confíaToken e intentos de autenticaciónDatos de destino y campos de actualizaciónEjecución a partir de una entrada externaFijar el alg permitido y limitar los intentosContrastar el sujeto y limitar el DTO de actualizaciónMitigación provisional y actualización de la biblioteca

Figura 24: Tabla de correspondencia entre vulnerabilidades y contramedidas. La contramedida se separa según el límite que se rompió.

El principio que recorre este problema es uno solo.

No convertir el éxito de la verificación anterior en motivo para omitir el siguiente límite de confianza.

En artículos anteriores de esta serie se explican el XSS almacenado de la pregunta 1 de la tarde de otoño de Reiwa 5 y la sustracción de información desde el Wi-Fi para visitantes de la pregunta 2 de la tarde de otoño de Reiwa 5. Para una visión de conjunto de los puntos a verificar en un sitio web completo, consulte también Usar «Cómo crear un sitio web seguro» de IPA como lista de verificación.

Resumen finalEl éxito de la comprobación anterior no es motivo para omitir la comprobación siguiente ni las contramedidas de operación.Confirmarla aparteOmitirla porque esta ha tenido éxitoÉxito de la verificación anterior¿Se cumple también la comprobación siguiente?Apilar una decisión por cada límiteQueda un límite sin confirmarLlevarlo al diseño y a la verificación cotidianos

Figura 25: Resumen final. Los límites de confianza se comprueban por etapas, y ninguno debe omitirse.

Referencias

  1. IPA, Cuadernillo de preguntas de la tarde del examen de Especialista en Seguridad de la Información Registrado, primavera del año Reiwa 6. El enunciado que trata este artículo. ↩ ↩2 ↩3 ↩4

  2. IPA, Ejemplo de respuestas de la tarde del examen de Especialista en Seguridad de la Información Registrado, primavera del año Reiwa 6. El ejemplo oficial de respuesta de cada pregunta. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12

  3. IPA, Comentario de calificación de la tarde del examen de Especialista en Seguridad de la Información Registrado, primavera del año Reiwa 6. Explica la tasa de aciertos y las tendencias de las respuestas erróneas. ↩ ↩2 ↩3

  4. NIST, SP 800-63B: Authentication and Authenticator Management. Indica el número de dígitos de los secretos de corta duración, el límite de intentos, el número de fallos al reemitir y no usar el correo electrónico para autenticación fuera de banda. ↩ ↩2

  5. RFC Editor, RFC 7519: JSON Web Token (JWT). La especificación del JWT, incluido el Unsecured JWT y alg=none. ↩

  6. RFC Editor, RFC 8725: JSON Web Token Best Current Practices. El BCP que establece fijar los algoritmos permitidos y verificar el emisor, el sujeto y la audience. ↩

  7. OWASP, API1:2023 Broken Object Level Authorization. Explica la necesidad de confirmar la autorización para cada ID de objeto indicado por el usuario. ↩

  8. OWASP, API3:2023 Broken Object Property Level Authorization. Explica la falla de autorización a nivel de propiedad, incluido el Mass Assignment, y sus contramedidas. ↩

  9. Apache Logging Services, Security. Explica el impacto de CVE-2021-44228, la ejecución de código a través de JNDI y LDAP, y la versión corregida. ↩

Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.

Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.

El artículo está directamente relacionado con los siguientes servicios.

Desarrollo de sitios web

En las API para socios registrados y en la integración con aplicaciones móviles, la verificación de JWT, la autorización a nivel de objeto y la limitación de las propiedades actualizables inciden directamente en la seguridad del sistema web.

Preguntas frecuentes

Preguntas habituales en las consultas sobre el tema del artículo.

¿Por qué se puede suplantar a otra persona aunque la verificación de la firma del JWT haya tenido éxito?
En este problema, la biblioteca de gestión de JWT aceptaba el alg de la cabecera del JWT tal como lo indicaba el atacante, y trataba un JWT con alg=none como válido sin firma. Por lo tanto, incluso reescribiendo el ID de usuario del payload, la verificación se completaba con éxito. La respuesta del examen es que el objeto a verificar debe ser el alg de la cabecera del JWT, comprobando que su valor no sea NONE. Sin embargo, en la práctica no basta con rechazar solo NONE. Hay que fijar en la configuración del servidor los algoritmos permitidos, por ejemplo RS256, sin usar directamente el algoritmo declarado por el propio token para la selección. Además, según el uso, conviene verificar también el issuer, la audience, la fecha de expiración y el subject.
¿Basta con comparar el ID de usuario contenido en el JWT con el mid de la solicitud como medida de autorización?
Como respuesta a este problema, es suficiente. Si el módulo común P verifica que el ID de usuario incluido en el JWT coincide con el mid, se puede detener el ataque que especifica el mid de otra persona. Sin embargo, para una API que solo maneja la información del propio usuario, en la práctica es más seguro no recibir el mid del cliente y determinar el ID de usuario a partir del subject del JWT ya verificado. Por ejemplo, usando GET /users/me o PUT /users/me se reduce la posibilidad de que falte implementar la propia comparación. Las API mediante las que un administrador opera sobre otros usuarios deben separarse en otro endpoint y otra política de autorización.
¿Por qué el ataque que añade status no se puede evitar solo con la validación habitual de valores de entrada?
Aunque se valide la longitud de name o el rango de age, si de entrada se vincula automáticamente un status que ni siquiera debería recibirse y se pasa al objeto interno, no se puede evitar. El problema no es el formato del valor, sino la autorización a nivel de propiedad: si el usuario tiene permiso para modificar esa propiedad. En el tipo de entrada para la actualización solo deben definirse name y age, y las propiedades desconocidas deben rechazarse. El estado de facturación debe cambiarse únicamente a partir de eventos en los que el servidor pueda confiar, como el resultado exitoso del servicio de pago.
El código de autenticación de 4 dígitos caduca a los 10 minutos: ¿por qué sigue siendo peligroso?
Porque los candidatos, de 0000 a 9999, solo suman 10.000 combinaciones, y si se pueden probar 10 por segundo, el promedio es de 5.000 intentos, es decir, se acierta en 500 segundos. Como el periodo de validez de 10 minutos son 600 segundos, probando candidatos distintos en secuencia se pueden verificar 6.000 combinaciones dentro de ese periodo. Solo con el tiempo de caducidad no se puede detener la fuerza bruta. Es necesario diseñar juntos el número de candidatos, la velocidad de los intentos y el límite de intentos.
La contramedida de la pregunta es el bloqueo de la cuenta: ¿basta también en la práctica con un bloqueo inmediato?
No. En el espacio en blanco del problema se coloca el proceso de bloquear la cuenta cuando el número de fallos consecutivos supera un umbral, pero un bloqueo permanente y fijo por sí solo permite que un atacante provoque una denegación de servicio bloqueando deliberadamente la cuenta de otra persona. En la práctica se combinan el número de fallos por cuenta, un retraso escalonado, la evaluación de riesgo del origen o del dispositivo, notificaciones y procedimientos de recuperación. También es importante no reiniciar a cero el número de fallos al emitir un nuevo código.
¿Qué sentido tiene poner el WAF en modo de detección en lugar de bloqueo?
Que, incluso cuando una cadena normal se clasifica erróneamente como ataque, no se detenga la comunicación de negocio. En la respuesta del problema, el beneficio es que se puede evitar el bloqueo por falsos positivos, y lo que hay que hacer es examinar, al recibir una alerta, si se trata realmente de un ataque. El modo de detección no es una configuración para dejarlo sin más. Se usa como periodo de observación para revisar los registros, eliminar los falsos positivos, ajustar las reglas y pasar después al bloqueo. En una emergencia en la que una vulnerabilidad grave y conocida ya está siendo explotada activamente, también puede ser razonable decidir bloquear primero, comparando ese riesgo con el riesgo de disponibilidad.
¿Es Log4j la biblioteca H de este problema?
El enunciado oculta el nombre del producto, pero la secuencia del ataque —JNDI Lookup, un servidor LDAP, la obtención de una clase desde un servidor HTTP, una cadena incrustada en una cabecera HTTP y un valor base de CVSS v3.1 elevado— es natural leerla como una abstracción de CVE-2021-44228, conocida como Log4Shell. En este artículo se explica esa correspondencia, pero en el examen no hace falta responder con el nombre propio: se puede resolver a partir del procedimiento de ataque dado y de las especificaciones del WAF.
¿Qué debería llevarse a la práctica profesional a partir de este problema?
Que el éxito de la autenticación, que el JWT no haya sido alterado, que se tenga permiso para acceder al objeto de destino y que se tenga permiso para modificar la propiedad de destino son, todas ellas, comprobaciones distintas entre sí. Además, los códigos de autenticación cortos necesitan un límite de intentos, y ante una vulnerabilidad grave de una biblioteca conviene avanzar en paralelo la verificación del impacto, la defensa provisional y la corrección definitiva. Los ejes centrales en la práctica son concentrar la autorización en componentes comunes, convertir el esquema de entrada en una lista de permitidos, fijar en el servidor las condiciones de verificación del JWT, y mantener un conocimiento actualizado de las bibliotecas dependientes que permita actualizarlas.

Perfil del autor

Página de presentación del autor del artículo.

Go Komura

Representante de KomuraSoft LLC

Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.

Volver al blog