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: · Go Komura · 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
flowchart TB
accTitle: Visión de conjunto del problema
accDescr: Leer 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.
A["Solicitud del usuario"] --> B["Comprobación del código de autenticación"]
B --> C["Emisión y verificación del JWT"]
C --> D["API de usuario"]
D --> E["Autorización del mid de destino"]
D --> F["Autorización del status de actualización"]
D -.-> G["Registrar la entrada externa en el registro"]
G --> H["Biblioteca vulnerable"]
H --> I["Ejecució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.
flowchart TB
accTitle: Diferencia entre autenticación y autorización
accDescr: Confirmar el sujeto no basta: hace falta otra comprobación que autorice a ese sujeto a operar sobre los datos o los campos de destino.
A["Autenticación y verificación del token"] --> B["Determinar de quién es la petición"]
B --> C["¿Se puede llegar a esos datos?"]
C --> D["¿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».
alges la política del tratamiento criptográficomides autorización a nivel de objetostatuses autorización a nivel de propiedadotpes 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.
flowchart TB
accTitle: Stateless y el estado que se conserva
accDescr: Aunque 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.
A["Solicitud con JWT"] --> B["Identificar al usuario solo con esa petición"]
B --> C["Ejecutar el tratamiento y responder"]
D["Información de usuario, facturación, número de fallos"] -.-> C
C -.-> E["No 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».
flowchart TB
accTitle: Escala temporal del código de autenticación de 4 dígitos
accDescr: En 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.
A["Hay 10000 candidatos"] --> B["La media es unas 5000 veces"]
B --> C["A 10 por segundo, unos 500 segundos"]
C --> D["Más corto que los 600 segundos de validez"]
D -.-> E["En 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.
- Cambiar el
algde la cabecera deRS256aNONE - 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.
flowchart TB
accTitle: Flujo del ataque JWT alg=none
accDescr: Si el atacante cambia el método de verificación y el ID de usuario, una biblioteca que permite none acepta el JWT alterado.
A["Obtener un JWT correcto"] --> B["Cambiar alg a none"]
B --> C["Cambiar user a otro usuario"]
C --> D["La biblioteca omite la verificación de firma"]
D --> E["Aceptarlo 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.
flowchart TB
accTitle: Verificación JWT segura y verificación JWT peligrosa
accDescr: No 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.
A["Recibir el JWT"] --> B{"¿Es un alg permitido por el servidor?"}
B -->|"No"| X["Rechazar"]
B -->|"Sí"| C["Verificar la firma y cada claim"]
C --> D["Tratarlo como sujeto verificado"]
Y["Tratamiento peligroso"] -.-> Z["Omitir 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.
flowchart TB
accTitle: La firma y el secreto del JWT son cosas distintas
accDescr: base64url 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.
A["JWT con firma"] --> B["Leer cabecera y payload"]
B --> C["Decodificar base64url"]
C --> D["El contenido no queda en secreto"]
A --> E["Verificar correctamente la firma"]
E --> F["Comprobar 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.
flowchart TB
accTitle: Ataque BOLA
accDescr: Aunque 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.
A["JWT con firma correcta (user01)"] --> C["API de usuario"]
B["mid cambiado (user02)"] --> C
C --> D["No se contrasta con el sujeto"]
D --> E["Obtener 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».
flowchart TB
accTitle: Cómo evitar BOLA
accDescr: Confirmar 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.
A["Sujeto del JWT verificado"] --> B{"Cómo se decide el ID de destino"}
B -->|"Se recibe mid"| C{"¿Coincide con el sujeto?"}
C -->|"Sí"| D["Operar sobre los datos propios"]
C -->|"No"| E["Rechazar"]
B -->|"API solo para uno mismo"| F["Derivar el ID de destino del sujeto"]
F --> D
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.
flowchart TB
accTitle: Mass Assignment
accDescr: Si 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.
A["La especificación es mid, name y age"] --> B["Añadir status=paid"]
B --> C["Pasar todos los parámetros a P"]
C --> D["Reflejarlos de golpe en los datos internos"]
D --> E["El 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.
- En el tipo de entrada de actualización, poner solo los campos que el usuario puede cambiar
- 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.
flowchart TB
accTitle: Autorización a nivel de campo
accDescr: Limitar 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.
A["Petición de actualización de perfil"] --> B{"¿Solo name y age?"}
B -->|"Sí"| C["Actualizar solo los campos permitidos"]
B -->|"No"| D["Rechazar los campos desconocidos"]
E["Notificación de pago verificada"] --> F["Contrastar paymentId y evitar duplicados"]
F --> G["Actualizar 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
mido unstatusarbitrarios, 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.
flowchart TB
accTitle: Estrechar el contrato del componente común
accDescr: Si 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.
A["API para el usuario general"] --> B["Sujeto verificado y DTO de actualización"]
B --> C["Unificar la autorización en el componente común"]
C --> D["Operar sobre los datos permitidos"]
E["Operación con ID arbitrario y Map arbitrario"] -.-> F["Separarla a una vía limitada, como la de administración"]
C -.-> G["Probar 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.
flowchart TB
accTitle: Con o sin límite de intentos
accDescr: Retener el número de fallos y bloquear al superar el umbral detiene la adivinación en línea ilimitada.
A["Fallo al contrastar el código"] --> B["Actualizar el número de fallos de la cuenta"]
B --> C{"¿Se ha superado el umbral?"}
C -->|"Sí"| D["Bloquear la cuenta"]
C -->|"No"| E["Permitir los intentos restantes"]
F["Sin límite, se puede seguir probando"] -.-> A
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.
flowchart TB
accTitle: Contramedidas del código de autenticación
accDescr: Ademá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.
A["Emitir o reemitir el código"] --> B["No reiniciar el número de fallos"]
B --> C["Contrastar limitando el número y la velocidad"]
C --> D{"¿Ha tenido éxito el contraste?"}
D -->|"Sí"| E["Invalidar el código de inmediato"]
D -->|"No"| F["Registro de fallos, retraso, bloqueo"]
F --> G["Notificación y procedimiento de recuperación seguro"]
A -.-> H["Limitar 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.
- El atacante envía una cadena que incluye un JNDI Lookup en una cabecera HTTP
- El servidor objetivo escribe ese valor en el registro
- La biblioteca vulnerable evalúa el JNDI Lookup y consulta un servidor LDAP de ataque
- La respuesta LDAP devuelve la URL de un servidor HTTP de ataque
- 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.
flowchart TB
accTitle: Flujo de confirmación de una vulnerabilidad de tipo Log4Shell
accDescr: Ademá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.
A["Entrada externa en una cabecera HTTP"] --> B["Tratamiento de registro del servidor objetivo"]
B --> C["Consulta LDAP mediante JNDI"]
C --> D["Recibir la URL de obtención de la clase"]
D --> E["El servidor objetivo obtiene la clase"]
E --> F["El servidor objetivo ejecuta la orden de verificación"]
F --> G["Obtener index.html del servidor de prueba"]
G --> H["Registrar 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.
flowchart TB
accTitle: Limitar la verificación al menor efecto secundario
accDescr: Obtener 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.
A["Aprobación explícita del propietario"] --> B["Decidir el impacto y las condiciones de observación"]
B --> C["Registrar el acceso en un servidor bajo control"]
C --> D["Contrastar con el instante y el origen esperados"]
D --> E["Retirar el entorno de verificación y las credenciales"]
B -.-> F["No 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.
flowchart TB
accTitle: Elegir el lugar de inspección del WAF
accDescr: El 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.
A["Leer el lugar de almacenamiento de la cadena de ataque"] --> B["Cabecera x-api-version"]
B --> C["El objeto de inspección es Header"]
C --> D["Pasar a un patrón que incluya mayúsculas y minúsculas"]
E["ANY son los parámetros de todos los métodos"] -.-> C
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.
- Aplicar el modo de detección al tráfico real
- Clasificar falsos positivos y detecciones correctas
- Ajustar la cabecera objetivo, la ruta, la API, el límite de caracteres, etc.
- Confirmar que el impacto sobre la comunicación normal es aceptable
- Pasar al modo de bloqueo
- 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.
flowchart TB
accTitle: Del modo de detección al modo de bloqueo del WAF
accDescr: Examinar las alertas durante la detección, ajustar los falsos positivos y tratar el ataque, y seguir supervisando también después del bloqueo.
A["Observar el tráfico en modo de detección"] --> B{"¿Cuál es el contenido de la alerta?"}
B -->|"Falso positivo"| C["Ajustar la regla o la condición de excepción"]
C --> A
B -->|"Ataque"| D["Aislar, preservar registros, investigar el impacto"]
D --> E["Pasar al bloqueo"]
A --> F["Confirmar el impacto sobre la comunicación normal"]
F --> E
E --> G["Supervisar 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.
- Detener de forma provisional, con el WAF, el patrón de ataque ya conocido
- Investigar si la biblioteca afectada está realmente incluida
- Restringir LDAP, RMI y la comunicación HTTP saliente innecesaria
- Actualizar a la versión corregida
- 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.
flowchart TB
accTitle: Lugar que ocupa el WAF
accDescr: La 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.
A["Publicación de una vulnerabilidad grave"] --> B["Confirmación del impacto y respuesta provisional"]
B --> C["Obtener registros y alertas con la detección"]
B --> D["Bloqueo y restricción de la comunicación saliente"]
C --> E["Ajustar y tratar a partir de la observación"]
D --> F["Actualizar a la versión corregida de la biblioteca"]
E --> F
F --> G["Confirmar 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?».
flowchart TB
accTitle: Vincular las dependencias con el sistema en ejecución
accDescr: Correspondencia, 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.
A["Lista de dependencias directas y transitivas"] --> B["Versión real del artefacto distribuido"]
B --> C["Servicios en ejecución y destino de despliegue"]
C --> D["Juzgar el objetivo afectado en poco tiempo"]
D --> E["Aprobación, reconstrucción y redistribución"]
C -.-> F["Conocer 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.
flowchart TB
accTitle: Separar la actualización y la investigación de infracción
accDescr: Impedir 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.
A["Actualizar a la versión corregida"] --> B["Detener la explotación futura"]
C["Investigar los registros de antes y después de la actualización"] --> D["Contrastar comunicación, procesos y archivos"]
D --> E["Confirmar credenciales y envíos al exterior"]
B -.-> F["Una infracción pasada no desaparece"]
F -.-> C
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
algde la cabecera JWT - El ID de usuario del payload JWT
- El
middel parámetro de la API - Un
statusfuera de especificación - El
otpde 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.
flowchart TB
accTitle: Volver del enunciado a la respuesta
accDescr: Seguir 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.
A["Alinear especificación e implementación"] --> B["Identificar el valor cambiado"]
B --> C["Seguir dónde se confió"]
C --> D["Decidir el tratamiento que hay que añadir"]
D --> E["Devolverlo 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
noney los algoritmos no previstos - Se verifican, según el uso, la firma,
iss,aud,expynbf - 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
flowchart TB
accTitle: La revisión prueba lo que viene después del caso normal
accDescr: Ademá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.
A["Confirmar el éxito de una petición normal"] --> B["Confirmar cambiando solo el ID de destino"]
B --> C["Confirmar añadiendo un campo de actualización desconocido"]
C --> D["Repetir el fallo de autenticación y la reemisión"]
D --> E["Confirmar el rechazo, el registro y la recuperación"]
E -.-> F["Tratar 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.
flowchart TB
accTitle: Tabla de correspondencia entre vulnerabilidades y contramedidas
accDescr: Preparar 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.
A["Separar los límites en los que se confía"] --> B["Token e intentos de autenticación"]
A --> C["Datos de destino y campos de actualización"]
A --> D["Ejecución a partir de una entrada externa"]
B --> E["Fijar el alg permitido y limitar los intentos"]
C --> F["Contrastar el sujeto y limitar el DTO de actualización"]
D --> G["Mitigació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.
flowchart TB
accTitle: Resumen final
accDescr: El éxito de la comprobación anterior no es motivo para omitir la comprobación siguiente ni las contramedidas de operación.
A["Éxito de la verificación anterior"] --> B{"¿Se cumple también la comprobación siguiente?"}
B -->|"Confirmarla aparte"| C["Apilar una decisión por cada límite"]
B -->|"Omitirla porque esta ha tenido éxito"| D["Queda un límite sin confirmar"]
C --> E["Llevarlo 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
-
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
-
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
-
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
-
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
-
RFC Editor, RFC 7519: JSON Web Token (JWT). La especificación del JWT, incluido el Unsecured JWT y
alg=none. ↩ -
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. ↩
-
OWASP, API1:2023 Broken Object Level Authorization. Explica la necesidad de confirmar la autorización para cada ID de objeto indicado por el usuario. ↩
-
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. ↩
-
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 relacionados
Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.
Análisis del examen de Especialista en Seguridad de la Información Registrado, otoño de Reiwa 5, tarde, pregunta 1 — el XSS almacenado donde 16 reseñas se muestran como solo 2
A partir de la pregunta 1 de la tarde del examen de Especialista en Seguridad de la Información Registrado, otoño de Reiwa 5, se explica ...
Examen de Especialista en Seguridad de la Información, otoño de 2023 (Reiwa 5), pregunta 2 de la tarde — los archivos que salen por el Wi-Fi de invitados
La pregunta 2 de la tarde del examen RISS de otoño de 2023 muestra cómo una empresa que prohibió el USB pierde archivos por el Wi-Fi de i...
Las 10 principales amenazas de seguridad de la información 2026 — cómo leer el ranking y qué deben abordar realmente las pymes
En el «Top 10 de amenazas de seguridad de la información 2026» de IPA, el ransomware repite en el 1.º puesto por 11.º año consecutivo, la...
Lo que también debe saber quien encarga un sitio web — cómo usar la guía «Cómo crear un sitio web seguro» de la IPA como checklist
¿Con qué criterio revisar la seguridad de su sitio web? Explicamos las 11 vulnerabilidades de la guía IPA «Cómo crear un sitio web seguro...
Medidas de seguridad para pymes, por dónde empezar — Cómo recorrer la versión 4.0 de la «Guía de medidas de seguridad de la información para pymes» del IPA
¿Por dónde empezar la seguridad en una pyme? La guía v4.0 del IPA explica los seis principios básicos, la autoevaluación de 5 minutos y S...
Temas relacionados
Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.
Temas técnicos de Windows
Portal sobre desarrollo de Windows, investigación de fallos y aprovechamiento de activos existentes.
Servicios relacionados con este tema
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.
Consultoría técnica y revisión de diseño
Detectar, mediante una revisión de diseño, las lagunas de autorización en las API existentes, el alcance del impacto de las bibliotecas dependientes y las reglas provisionales de WAF es precisamente el tipo de trabajo que cubre nuestra consultoría técnica.
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.