Neutron, nuestro motor de IA, obtuvo un 97.1% en el benchmark CyberGym de UC Berkeley. Más información

Análisis a fondo

Análisis a fondo

Robo de tokens de sesión y omisión de SAML en OpenAM (CVE-2026-123551)

OpenAM anterior a 16.1.4 filtra tokens de sesión y acepta aserciones SAML sin firmar, permitiendo secuestrar sesiones sin autenticarse; corregido en 16.1.4.

Resumen

  • OpenAM anterior a 16.1.4 difunde tokens de sesión en claro a los temas de los agentes de políticas y acepta aserciones SAML sin firmar en los enlaces ECP y HTTP-Artifact. Un atacante no autenticado puede usar cualquiera de los dos fallos para secuestrar sesiones de usuarios y administradores.
  • La misma versión corrige un fallo de autorregistro que permite a un usuario anónimo unirse a un grupo administrativo. OpenIdentityPlatform publicó los avisos y OpenAM 16.1.4 el 2026-10-22.
  • Los registros CVE puntúan la divulgación de tokens con CVSS v4.0 10.0 y los otros dos fallos con 9.3. Los avisos del proveedor puntúan el fallo de tokens con CVSS v3.1 10.0 y los otros dos con 9.8.
  • No se reporta prueba de concepto pública ni explotación en entornos reales. Los fallos no están en el catálogo KEV de CISA al 2026-11-08. Actualice a OpenAM 16.1.4.

¿Estoy afectado?

Todas estas condiciones deben cumplirse:

  • Ejecuta OpenIdentityPlatform OpenAM en una versión anterior a 16.1.4.
  • Para el fallo de tokens de sesión, ejecuta una versión 14.0.0 a 16.1.3 y el WebSocket de notificaciones es accesible. Las notificaciones de agentes están activadas por defecto, y eso es lo que coloca los identificadores de sesión en los temas de los agentes.
  • Para el fallo SAML, OpenAM actúa como proveedor de servicio SAML v2.0 alojado. Sus metadatos anuncian el servicio de consumo de aserciones ECP (PAOS), que los metadatos generados incluyen por defecto. El proveedor de servicio tiene WantAssertionsSigned en false, que los metadatos generados también ponen por defecto, y una clave de cifrado configurada para que los proveedores de identidad puedan cifrarle aserciones.
  • Para el fallo de autorregistro, el autorregistro está activado en el realm. Está desactivado por defecto.
Rama Versiones afectadas Versión corregida
OpenAM 14.0.0 a 16.1.3 Los tres fallos 16.1.4 (2026-10-22)
OpenAM anterior a 14.0.0 Omisión de aserción SAML y escalada por autorregistro; el WebSocket de notificaciones no existe 16.1.4 (2026-10-22)

El endpoint de versión responde sin sesión. Pregunte al servidor directamente:

curl -s https://openam.example.com:8443/openam/json/serverinfo/version

La respuesta contiene version, revision y date. En la imagen de contenedor, la misma petición se ejecuta contra el puerto local:

docker exec openam curl -s http://localhost:8080/openam/json/serverinfo/version

¿Cómo lo corrijo?

Actualice a OpenAM 16.1.4 o posterior. El proveedor lo publicó el 2026-10-22, el mismo día que los avisos.

Cronología desde los commits de corrección hasta los registros CVE: correcciones el 2026-10-21, OpenAM 16.1.4 y los avisos el 2026-10-22, registros CVE el 2026-11-08
Figura 1: OpenAM corrigió los tres fallos antes de que aparecieran los registros CVE. Fuente: commits de OpenAM, publicación 16.1.4 y registros CVE, consultados el 8 de noviembre de 2026.

  1. Para la imagen de contenedor, configure el servicio en openidentityplatform/openam:16.1.4 en su archivo Compose. Descargue la imagen configurada y recree el contenedor:
docker compose pull openam
docker compose up -d openam
  1. Para un despliegue WAR, descargue openam-server-only 16.1.4 desde Maven Central y despliegue el nuevo openam.war sobre la aplicación web existente. Reinicie el contenedor después del despliegue.

  2. Para una compilación Maven que depende de artefactos de OpenAM, fije org.openidentityplatform.openam:openam-server-only y los demás módulos de OpenAM en 16.1.4.

Si no puede actualizar de inmediato, estas medidas reducen la exposición pero no corrigen el código:

  • Ponga WantAssertionsSigned en true en cada proveedor de servicio SAML v2.0 alojado y active la firma de respuestas. Esto cubre el fallo de aserción. No cubre el WebSocket de notificaciones ni el autorregistro.
  • Restrinja el WebSocket /openam/notifications y los endpoints heredados de Liberty ID-FF a los hosts de los agentes de políticas, en el proxy inverso o en la red. Esto reduce la ruta de divulgación de tokens. No detiene a un atacante que puede alcanzar esos endpoints por otra ruta.
  • Desactive el autorregistro en cada realm. Esto cierra únicamente la ruta de registro anónimo.
  • Trate cada instancia de OpenAM expuesta a Internet antes de la actualización como expuesta, y revise sus sesiones y administradores después de actualizar.

¿Cuál es la causa raíz?

OpenAM aplicaba la herencia de firma SAML solo en el enlace HTTP-POST. Todos los demás enlaces dependían de una marca de metadatos que los metadatos generados del proveedor de servicio ponen en false. La comprobación está en SAML2Utils.verifyResponse, en la biblioteca de federación, en OpenAM 16.1.3:

if (wantAssertionsSigned && !(responseIsSigned || allAssertionsSigned)) {
    throw new SAML2Exception(bundle.getString("assertionNotSigned"));
}

if (profileBinding.equals(SAML2Constants.HTTP_POST)) {
    boolean wantPostResponseSigned = SAML2Utils
            .wantPOSTResponseSigned(orgName, hostEntityId, SAML2Constants.SP_ROLE);
    if (wantPostResponseSigned && !responseIsSigned) {
        throw new SAML2Exception(bundle.getString("responseNotSigned"));
    }
    if (!responseIsSigned && !allAssertionsSigned) {
        throw new SAML2Exception(bundle.getString("assertionNotSigned"));
    }
}

El primer bloque solo rechaza una respuesta sin firmar cuando los metadatos WantAssertionsSigned del proveedor de servicio están en true. El segundo bloque rechaza una respuesta sin firmar o aserciones sin firmar independientemente de esa marca, pero solo se ejecuta para HTTP_POST. En los enlaces ECP (PAOS) y HTTP-Artifact, ninguno de los dos bloques exige una firma si la marca de metadatos está desactivada.

El WebSocket de notificaciones confiaba en que el contenedor ejecutara su filtro, y el filtro solo estaba mapeado a los despachos de petición. El manejador del WebSocket suscribía al cliente a cualquier tema que este nombrara:

String topic = json.get("topic").asString();
subscription.bindTo(Topic.of(topic));

El filtro de seguridad lee la cookie de agente y comprueba que el token pertenece a un agente de políticas J2EE o web. En OpenAM 16.1.3 su mapeo en web.xml no nombraba ningún despachador, así que el contenedor solo lo ejecutaba en despachos REQUEST.

Un reenvío interno a /notifications llega como un despacho FORWARD. El filtro se omitía, y la actualización del WebSocket continuaba sin la comprobación de agente. Los endpoints heredados de Liberty ID-FF de OpenAM realizan esos reenvíos. El aviso cita un reenvío interno no validado como la forma de alcanzar el socket sin credenciales.

La acción de autorregistro anónimo creaba la cuenta con el token del administrador del sistema. Nunca aplicaba la lista de atributos permitidos. En IdentityResourceV2.anonymousCreate en 16.1.3, el cuerpo de la petición iba directamente al servicio de identidad:

SSOToken admin = RestUtils.getToken();
return createInstance(admin, jVal, realm, context, null)

La lista permitida vivía en IdentityRestUtils y solo se aplicaba a peticiones que llevaban un SelfServiceContext. La acción heredada no lleva ninguno, así que un llamante podía definir cualquier atributo. Un valor memberof no permanece como atributo: la capa de identidad lo convierte en pertenencia a un grupo. Un usuario que se autorregistraba podía, por tanto, unirse a un grupo administrativo.

¿Cómo se explota?

La ruta SAML no requiere credenciales ni interacción del usuario:

  1. El atacante encuentra un proveedor de servicio SAML v2.0 alojado en una instancia OpenAM afectada. Anuncia ECP (PAOS), tiene WantAssertionsSigned desactivado y tiene una clave de cifrado configurada.
  2. El atacante construye una respuesta SAML con una aserción que nombra una cuenta objetivo, incluida una cuenta de administrador, y la envía al endpoint ECP o HTTP-Artifact sin firma.
  3. OpenAM comprueba el emisor contra el círculo de confianza, pero no la firma en ese enlace. Asocia la aserción con la cuenta local y emite una sesión.
  4. El atacante usa esa sesión contra OpenAM y contra cada aplicación que confía en él para el inicio de sesión único.

La ruta de notificaciones requiere una ruta hacia el WebSocket:

  1. El atacante envía una petición a un endpoint heredado de Liberty ID-FF que reenvía internamente a /notifications. El reenvío omite el filtro que comprueba el token de agente de políticas.
  2. El atacante se suscribe a un tema interno. Antes de la corrección, el manejador aceptaba cualquier nombre de tema.
  3. OpenAM publica el valor completo de iPlanetDirectoryPro al crear, cerrar, expirar o cambiar una propiedad de una sesión, porque las notificaciones de agentes están activadas por defecto.
  4. El atacante reutiliza un valor capturado como credencial de portador contra los endpoints REST de OpenAM y contra las aplicaciones que confían en la misma sesión.

La ruta de autorregistro requiere que el autorregistro esté activado:

  1. El atacante completa la verificación por correo electrónico de una dirección que controla.
  2. El atacante envía la acción anonymousCreate con un valor memberof que nombra un grupo administrativo.
  3. OpenAM crea la cuenta con su token de administrador del sistema y escribe la pertenencia al grupo. La nueva cuenta puede administrar el realm.

No existe prueba de concepto pública para ninguno de los tres fallos. Los avisos indican que los detalles técnicos y el código de prueba de concepto se retienen para dar tiempo a los operadores a actualizar.

¿Cómo se desarrolla el ataque?

Una aserción SAML sin firmar alcanza un proveedor de servicio que solo comprueba firmas en otro enlace, se asocia con una cuenta local y se convierte en una sesión para cada aplicación detrás de OpenAM.

flowchart LR A["El atacante construye una aserción
SAML sin firmar"] --> B["La envía al endpoint
ECP o HTTP-Artifact"] B --> C["El SP comprueba la firma
solo en HTTP-POST"] C --> D["ninguna comprobación de firma
en este enlace"] D --> E["La aserción se asocia a un usuario local,
incluido un administrador"] E --> F["OpenAM emite una sesión"] F --> G["El atacante alcanza cada
aplicación que confía en OpenAM"]

¿Qué puede hacer un atacante?

El fallo SAML permite a un atacante no autenticado obtener una sesión como cualquier cuenta que el proveedor de servicio pueda mapear, incluida una cuenta de administrador. Las cuentas alcanzables dependen del mapeo.

La autofederación o un NameID usado como identificador de usuario alcanza cualquier cuenta. Un identificador de federación que es una dirección de correo o un nombre de usuario alcanza cualquier cuenta cuyo identificador el atacante conozca o pueda adivinar. El atacante hereda cada aplicación que confía en la sesión secuestrada.

El fallo de notificaciones permite a un atacante no autenticado leer el token de sesión activo de cada usuario cuya sesión se crea, cambia o termina mientras la conexión WebSocket está abierta. Eso incluye a los administradores. Un token es una credencial de portador contra la API REST de OpenAM y contra cada aplicación detrás de la misma sesión. El atacante también puede suscribirse a temas internos.

El fallo de autorregistro permite a un atacante anónimo crear una cuenta que es miembro de cualquier grupo existente, incluido un grupo administrativo. Donde existe ese grupo, el resultado es el control administrativo completo del realm. El atacante necesita que el autorregistro esté activado, que no es la configuración por defecto.

Los tres registros CVE puntúan cada fallo como crítico: CVSS v4.0 10.0 para la divulgación de tokens y 9.3 para los otros dos.

Gráfico de las tres puntuaciones CVSS v4.0: 10.0 para la divulgación de tokens de sesión, 9.3 para la omisión de aserción SAML y 9.3 para la escalada por autorregistro
Figura 2: los tres registros CVE puntúan cada fallo como crítico. Fuente: los tres registros CVE, consultados el 8 de noviembre de 2026.

Ninguno de los tres fallos requiere una posición local. Los fallos SAML y de notificaciones son alcanzables por red. El fallo de autorregistro es alcanzable por red cuando la función está activada.

¿Por qué funciona la corrección?

La corrección SAML coloca la decisión de firma antes de cualquier otra comprobación y la aplica a cada enlace. El commit añade isMissingRequiredSignature. Rechaza una respuesta cuando ni la respuesta ni todas sus aserciones están firmadas, salvo que el enlace sea el enlace HTTP-Artifact de canal posterior y su configuración lo permita. El extracto se reduce a esa comprobación y a su excepción:

+boolean allAssertionsSigned = true;
+List<String> unsignedAssertionIDs = new ArrayList<>();
+for (Assertion assertion : assertions) {
+    if (!assertion.isSigned()) {
+        allAssertionsSigned = false;
+        unsignedAssertionIDs.add(assertion.getID());
+    }
+}
+if (isMissingRequiredSignature(responseIsSigned, allAssertionsSigned,
+        () -> isAssertionSignatureRequired(wantAssertionsSigned, profileBinding, spConfig, orgName,
+                hostEntityId))) {
+    throw new SAML2Exception(bundle.getString("assertionNotSigned"));
+}

El mismo commit vincula una respuesta HTTP-Artifact al proveedor de identidad que resolvió el artefacto, de modo que un socio de confianza no pueda responder con una respuesta emitida en nombre de otro socio. La corrección es completa para la ruta de respuesta del proveedor de servicio que describen los avisos.

La corrección del WebSocket añade una lista de temas permitidos y hace que el filtro se ejecute en todos los tipos de despacho:

+private static final String ALLOWED_TOPIC_PREFIX = "/agent/";
+if (!topic.startsWith(ALLOWED_TOPIC_PREFIX)) {
+    sendError(session, id, "topic not permitted");
+    return;
+}
 <filter-mapping>
     <filter-name>NotificationsWebSocketFilter</filter-name>
     <url-pattern>/notifications</url-pattern>
+    <dispatcher>REQUEST</dispatcher>
+    <dispatcher>FORWARD</dispatcher>
+    <dispatcher>INCLUDE</dispatcher>
+    <dispatcher>ASYNC</dispatcher>
+    <dispatcher>ERROR</dispatcher>
 </filter-mapping>

El código de federación también rechaza un reenvío a una raíz que lleva un filtro limitado a peticiones. La corrección cubre las dos formas que describe el aviso para alcanzar el socket.

La corrección del autorregistro aplica la lista permitida de forma explícita, fuera de cualquier SelfServiceContext:

+if (!USER_TYPE.equals(objectType)) {
+    throw new BadRequestException("Self-registration is only supported for users");
+}
+removeIgnoringCase(jVal, EMAIL);
+removeIgnoringCase(jVal, FIELD_MAIL);
+jVal.put(FIELD_MAIL, email);
+enforceSelfRegistrationWhiteList(configHandler, realm, jVal, objectType);

La comprobación de la lista permitida también rechaza la pertenencia a un grupo no permitida, compara los nombres de atributo sin distinguir mayúsculas y minúsculas y rechaza un cuerpo que no puede convertir. La identidad se sigue creando con el token de administrador, pero solo con los atributos que la lista permite.

¿Cómo compruebo si estuve comprometido?

No se publican indicadores de compromiso, y los avisos indican que no se ha reportado explotación. Trate estos datos como pistas, no como pruebas, y tenga en cuenta que un intento fallido puede no dejar rastro.

Compruebe primero la versión, porque todas las demás comprobaciones dependen de ella. Después busque sesiones creadas a través de los endpoints de federación sin un inicio de sesión correspondiente en el proveedor de identidad. Busque también cuentas creadas por autorregistro que sean miembros de grupos administrativos, y conexiones WebSocket a /openam/notifications desde hosts que no sean agentes de políticas.

Los registros de acceso del proxy inverso registran la ruta del WebSocket:

grep -iE "GET /openam/notifications|anonymousCreate" /var/log/nginx/access.log

El registro de auditoría de OpenAM registra eventos de identidad y de sesión en JSON. Busque creaciones de identidad y eventos de sesión alrededor del periodo que investiga:

grep -hE '"eventName": ?"AM-(IDENTITY|SESSION)"' /path/to/openam/audit/*.json | tail -n 200

Si el registro de auditoría no está activado, actívelo antes de la actualización y conserve los registros existentes. Un token de sesión capturado antes de un cierre de sesión sigue siendo válido hasta que caduca. Revise las sesiones activas después de actualizar si tiene algún motivo para sospechar una exposición.

Cronología

  • 2026-10-21: OpenAM integra las correcciones de los fallos SAML, del WebSocket de notificaciones y de autorregistro.
  • 2026-10-22: se publica OpenAM 16.1.4 y se publican los tres avisos.
  • 2026-11-08: VulnCheck publica los registros CVE, y la base de datos de avisos de GitHub los lista.

Preguntas frecuentes

¿Esto afecta a ForgeRock AM u otro fork de OpenAM?

Los avisos cubren OpenIdentityPlatform OpenAM. No nombran ForgeRock AM ni ningún otro fork. Si ejecuta otro fork, pregunte a su proveedor si tiene las mismas correcciones antes de confiar en este aviso.

¿Basta con 16.1.4?

Sí. OpenAM 16.1.4 contiene las correcciones de los tres fallos, y el proveedor lo publicó el mismo día que los avisos. Use 16.1.4 o posterior.

¿Estoy afectado si no uso SAML?

Puede ser que sí. El fallo del WebSocket de notificaciones afecta a OpenAM 14.0.0 a 16.1.3 con independencia de SAML, y el fallo de autorregistro se aplica donde el autorregistro esté activado. Compruebe la versión y la configuración de las funciones.

¿Hay exploits públicos?

No se publica ninguna prueba de concepto pública para ninguno de los tres fallos. Los avisos retienen los detalles técnicos y el código de explotación para dar tiempo a los operadores a actualizar. Los fallos no están en el catálogo KEV de CISA al 2026-11-08.

¿Puedo mitigar sin actualizar?

Solo en parte. Poner WantAssertionsSigned en true, desactivar el autorregistro y restringir /openam/notifications cierra una ruta cada medida, pero ninguna corrige el código. Actualice a 16.1.4 en cuanto pueda.

¿Por qué aparecieron los registros CVE después de la versión corregida?

El proveedor publicó los avisos con la versión 16.1.4 el 2026-10-22. VulnCheck asignó y publicó los registros CVE el 2026-11-08, que es cuando los escáneres que solo leen fuentes CVE pudieron señalar las versiones por primera vez.

Encuentre servidores OpenAM expuestos con Ostorlab

El descubrimiento de superficie de ataque de Ostorlab inventaría sus hosts expuestos a Internet para que vea qué despliegues de OpenAM están expuestos y cuáles actualizar primero. Muestra los servicios expuestos, no si una instancia concreta es vulnerable.

Referencias

  • Aviso de OpenIdentityPlatform GHSA-5c3q-hp86-xjr8, «OpenAM: unauthenticated disclosure of live session tokens via the notification WebSocket», CVSS v3.1 10.0, afecta 14.0.0 a 16.1.3, corregido en 16.1.4: https://github.com/OpenIdentityPlatform/OpenAM/security/advisories/GHSA-5c3q-hp86-xjr8 (consultado el 8 de noviembre de 2026)
  • Aviso de OpenIdentityPlatform GHSA-3j2f-qhrc-rjfj, «OpenAM: SAML v2.0 service provider accepts unsigned assertions on some bindings», CVSS v3.1 9.8, corregido en 16.1.4: https://github.com/OpenIdentityPlatform/OpenAM/security/advisories/GHSA-3j2f-qhrc-rjfj (consultado el 8 de noviembre de 2026)
  • Aviso de OpenIdentityPlatform GHSA-jv8f-m88g-h6mm, «OpenAM: self-registration does not enforce the allowed attribute list», CVSS v3.1 9.8, corregido en 16.1.4: https://github.com/OpenIdentityPlatform/OpenAM/security/advisories/GHSA-jv8f-m88g-h6mm (consultado el 8 de noviembre de 2026)
  • Registro CVE-2026-123551, divulgación de tokens de sesión, CVSS v4.0 10.0 y v3.1 10.0: https://www.cve.org/CVERecord?id=CVE-2026-123551 (consultado el 8 de noviembre de 2026)
  • Registro CVE-2026-123550, omisión de aserción SAML, CVSS v4.0 9.3 y v3.1 9.8: https://www.cve.org/CVERecord?id=CVE-2026-123550 (consultado el 8 de noviembre de 2026)
  • Registro CVE-2026-123549, escalada por autorregistro, CVSS v4.0 9.3 y v3.1 9.8: https://www.cve.org/CVERecord?id=CVE-2026-123549 (consultado el 8 de noviembre de 2026)
  • Commit de corrección del fallo SAML, 3bf8e61a7e, 2026-10-21: https://github.com/OpenIdentityPlatform/OpenAM/commit/3bf8e61a7e (consultado el 8 de noviembre de 2026)
  • Commit de corrección del WebSocket de notificaciones, 7d6a031c8e, 2026-10-21: https://github.com/OpenIdentityPlatform/OpenAM/commit/7d6a031c8e (consultado el 8 de noviembre de 2026)
  • Commit de corrección del autorregistro, 4c8a33822a, 2026-10-21: https://github.com/OpenIdentityPlatform/OpenAM/commit/4c8a33822a (consultado el 8 de noviembre de 2026)
  • Publicación de OpenAM 16.1.4, 2026-10-22: https://github.com/OpenIdentityPlatform/OpenAM/releases/tag/16.1.4 (consultado el 8 de noviembre de 2026)
  • SAML2Utils.java de OpenAM 16.1.3, la lógica de firma vulnerable: https://github.com/OpenIdentityPlatform/OpenAM/blob/16.1.3/openam-federation/openam-federation-library/src/main/java/com/sun/identity/saml2/common/SAML2Utils.java (consultado el 8 de noviembre de 2026)
  • web.xml de OpenAM 16.1.3, el mapeo de filtro sin despachadores: https://github.com/OpenIdentityPlatform/OpenAM/blob/16.1.3/openam-server-only/src/main/webapp/WEB-INF/web.xml (consultado el 8 de noviembre de 2026)
  • ServerVersionResource de OpenAM, el endpoint de versión no autenticado: https://github.com/OpenIdentityPlatform/OpenAM/blob/16.1.4/openam-core-rest/src/main/java/org/forgerock/openam/core/rest/server/ServerVersionResource.java (consultado el 8 de noviembre de 2026)
  • Catálogo de vulnerabilidades explotadas de CISA, versión 2026.11.06, sin entrada de OpenAM: https://www.cisa.gov/known-exploited-vulnerabilities-catalog (consultado el 8 de noviembre de 2026)
  • Cifras de alcance del repositorio OpenAM, 902 estrellas y 474,791 descargas de Docker Hub: https://github.com/OpenIdentityPlatform/OpenAM y https://hub.docker.com/r/openidentityplatform/openam (consultado el 8 de noviembre de 2026)
  • Fuente de la figura 1, los tres commits de corrección y la publicación 16.1.4: https://github.com/OpenIdentityPlatform/OpenAM/compare/16.1.3...16.1.4 (consultado el 8 de noviembre de 2026)