flawopen.com/AI Security/hermes-agent-native-signin-redirect-parser-confusion
Défaut de redirection de la connexion native de Hermes Agent
Tenable a publié une faille grave de validation des redirections dans la connexion native de Hermes Agent. Les versions antérieures à 0.21.6 sont concernées. Le correctif de la version 0.21.6 a été livré pour Docker/Hermes Cloud et les installations CLI/git ; la version 0.21.7, publiée le 11 octobre, indique aussi la disponibilité pour l’application Desktop, Microsoft Store/MSIX, l’installateur, Docker et Hermes Cloud. Les notes consultées ne mentionnent pas Termux ; vérifiez ce canal séparément. Tenable lui attribue le niveau High (CVSS 4.0 8.6) ; aucun CVE n’est assigné. CWE-601 est une classification éditoriale de l’effet de redirection.[1], [2], [5]
Imaginez un accueil qui vérifie une adresse sur une carte, recopie l’adresse reçue sans la modifier et la remet à un coursier qui utilise une autre carte. Le coursier peut aller ailleurs que l’endroit autorisé. Hermes vérifiait le callback avec le parseur Python, puis transmettait la chaîne brute au navigateur, qui peut l’interpréter différemment.[1]
Concepts Clés et Termes
Native-app callback- Une adresse web locale temporaire utilisée par une application de bureau pour recevoir le résultat d’une connexion lancée dans le navigateur.[1], [4]
URL parser differential- Deux parseurs d’URL donnent un sens différent à la même entrée ; valider une interprétation puis en utiliser une autre rompt la frontière de sécurité.[1], [3]
Correspondances de référentiels
- Correspondance conceptuelle de FlawOpen avec MITRE CWE ; aucun fournisseur ni enregistrement CVE n’a attribué cet identifiant de faiblesse à cette démonstration de recherche. CWE-601
Déroulement de l'Attaque Étape par Étape
Une route publique de connexion native reçoit un callback
Le point de terminaison d’autorisation reçoit un URI de redirection et un défi PKCE avant l’authentification de l’utilisateur.[1]
Une connexion terminée peut exposer le code
Après la connexion normale de la victime, le navigateur peut envoyer le code à l’autorité qu’il a interprétée. Un attaquant ayant choisi le défi PKCE correspondant peut tenter de l’échanger. La connexion de la victime est nécessaire : ce n’est pas une prise de compte sans interaction.[1]
Canonicaliser et mettre à jour la version distribuée
Le correctif rejette les syntaxes ambiguës et les autorités non canoniques, renvoie l’URI canonique et stocke cette valeur. Passez à la version 0.21.7 ou ultérieure par un canal pris en charge ; vérifiez Termux séparément, car les notes consultées de la version 0.21.7 ne le mentionnent pas.[2], [5], [3]
Code Source : Vulnérable vs Sécurisé
Il s’agit d’un modèle illustratif de la frontière, pas du code complet de Hermes Agent ni d’un exploit. L’exemple vulnérable résume le schéma vérifier l’hôte analysé/utiliser l’entrée brute. L’exemple corrigé montre la propriété du correctif fusionné : rejeter les entrées ambiguës, n’autoriser que des autorités loopback canoniques, renvoyer l’URI canonique puis persister/utiliser cette valeur. Le PR lié contient l’implémentation et les tests réels.[1], [3]
from urllib.parse import urlparse
def validate_callback(raw):
parsed = urlparse(raw)
# Le flux d’origine vérifiait l’hôte analysé, puis conservait l’URL brute.
if parsed.scheme == "http" and parsed.hostname in {"127.0.0.1", "::1"}:
return raw
raise ValueError("callback must be loopback")
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 "/"))
Liste de Contrôle de Sécurité pour l'Ingénierie
- ✓Inventoriez les versions et les canaux d’installation de Hermes Agent, puis vérifiez la version réellement exécutée. La version 0.21.7 indique une disponibilité pour Desktop, Microsoft Store/MSIX, l’installateur, Docker et Hermes Cloud.[5]
- ✓Passez à la version 0.21.7 ou ultérieure par le canal pris en charge ; vérifiez Termux séparément, car les notes consultées ne le listent pas.[2], [5]
- ✓Vérifiez que la validation renvoie une valeur canonique et que le flux stocke et utilise exactement cette valeur ; ne validez pas une représentation puis ne réutilisez pas la saisie brute.[3]
- ✓Ajoutez des tests sur les divergences de parseurs, les informations utilisateur, les barres obliques inverses, les fragments, les formes IP et ports non canoniques ; confirmez le rejet avant émission du code.[3]