FlawOpen

flawopen.com/AI Security/hermes-agent-native-signin-redirect-parser-confusion

● Mapeo de FlawOpen: CWE-601 · CVSS v4 8.6[1] · Alta
Investigación · FlawOpen

Fallo de redirección en el inicio de sesión nativo de Hermes Agent

Tenable divulgó un fallo grave de validación de redirecciones en el inicio de sesión nativo de Hermes Agent. Las versiones anteriores a 0.21.6 están afectadas. La corrección de 0.21.6 llegó a Docker/Hermes Cloud y a las instalaciones CLI/git; 0.21.7, publicada el 11 de octubre, también incluye la aplicación Desktop, Microsoft Store/MSIX, el instalador, Docker y Hermes Cloud. Las notas consultadas no mencionan Termux; compruebe ese canal por separado. Tenable la califica como High (CVSS 4.0 8.6); no tiene CVE asignado. CWE-601 es una clasificación editorial del resultado de redirección.[1], [2], [5]

💡 Explicación en Lenguaje Sencillo (ELI5)

Imagina que una recepción comprueba una dirección en un mapa, copia sin cambios el texto recibido y se lo entrega a un mensajero que usa otro mapa. El mensajero podría ir a un lugar que la recepción nunca aprobó. Hermes comprobaba el callback con el parser de Python, pero después entregaba el texto original al navegador, que puede interpretarlo de otra manera.[1]

Conceptos Clave y Términos

Native-app callback
Una dirección web local temporal que una aplicación de escritorio usa para recibir el resultado de un inicio de sesión en el navegador.[1], [4]
URL parser differential
Dos parsers de URL asignan significados distintos a la misma entrada; validar una interpretación y usar otra después rompe el límite de seguridad.[1], [3]
PKCE
Proof Key for Code Exchange vincula un código de autorización a un verificador secreto que conserva la aplicación que inició el acceso.[1], [4]
Loopback address
Una dirección IP que vuelve al mismo dispositivo, como 127.0.0.1 o ::1. La corrección acepta literales IP canónicos, no hosts remotos arbitrarios.[3], [4]

Mapeos de marcos

  • Mapeo conceptual de FlawOpen a MITRE CWE; ningún proveedor ni registro CVE asignó este identificador de debilidad a esta demostración de investigación. CWE-601

Flujo de Ataque Paso a Paso

Paso 1

Una ruta pública de inicio nativo recibe un callback

El endpoint de autorización recibe un URI de redirección y un desafío PKCE antes de autenticar al usuario.[1]

Paso 2

El servidor y el navegador interpretan el callback de forma distinta

El validador vulnerable inspeccionaba el hostname analizado por Python, pero conservaba la cadena original. Cierta sintaxis ambigua puede hacer que el navegador navegue a otra autoridad.[1], [3]

Paso 3

Un inicio completado puede exponer el código

Después de que la víctima completa el inicio de sesión normal, el navegador puede enviar el código a la autoridad que interpretó. Un atacante que eligió el desafío PKCE correspondiente podría intentar canjearlo. Hace falta que la víctima inicie sesión; no es una toma de cuenta sin interacción.[1]

Paso 4

Canonicalizar y actualizar la compilación distribuida

La corrección rechaza la sintaxis ambigua y las autoridades no canónicas, devuelve el URI canónico y guarda ese valor. Actualice a 0.21.7 o posterior mediante un canal compatible; compruebe Termux por separado, ya que las notas consultadas de 0.21.7 no lo mencionan.[2], [5], [3]

Código Fuente: Vulnerable vs. Seguro

Este es un modelo ilustrativo del límite, no el código completo de Hermes Agent ni un exploit. El ejemplo vulnerable resume el patrón validar-host-analizado/usar-entrada-original. El ejemplo endurecido muestra la propiedad de la corrección integrada: rechazar entradas ambiguas, aceptar solo autoridades loopback canónicas, devolver el URI canónico y guardar/utilizar ese valor. Consulte el PR enlazado para ver la implementación y las pruebas reales.[1], [3]

IMPLEMENTACIÓN VULNERABLE
from urllib.parse import urlparse

def validate_callback(raw):
    parsed = urlparse(raw)
    # El flujo original comprobaba el host analizado, pero después conservaba la URL sin procesar.
    if parsed.scheme == "http" and parsed.hostname in {"127.0.0.1", "::1"}:
        return raw
    raise ValueError("callback must be loopback")
PARCHE SEGURO Y ROBUSTO
from urllib.parse import urlparse, urlunparse

LOOPBACK_HOSTS = {"127.0.0.1": "127.0.0.1", "::1": "[::1]"}

def validate_callback(raw):
    if not raw.isascii() or "\\" in raw or any(ord(c) <= 0x20 or ord(c) == 0x7f for c in raw):
        raise ValueError("callback must use canonical loopback syntax")
    try:
        parsed = urlparse(raw)
        host, port = parsed.hostname, parsed.port
    except ValueError as exc:
        raise ValueError("invalid callback") from exc
    if parsed.scheme != "http" or "#" in raw or parsed.username is not None or parsed.password is not None:
        raise ValueError("callback must be a plain loopback URL")
    authority_host = LOOPBACK_HOSTS.get(host)
    if authority_host is None:
        raise ValueError("callback host must be a loopback IP literal")
    authority = authority_host + (f":{port}" if port is not None else "")
    if parsed.netloc != authority:
        raise ValueError("callback authority is not canonical")
    return urlunparse(parsed._replace(path=parsed.path or "/"))

Lista de Verificación de Seguridad para Ingeniería

Fuentes

← AI Security Directory →