
Détecteur non destructif pour RCE non authentifié dans BeyondTrust Remote Support et PRA, enchaînant l'injection d'arguments et le contournement d'échappement PostgreSQL pour vérifier l'exploitabilité via une différentielle basée sur le temps.
Avertissement éthique : À des fins de recherche, d'éducation et de tests autorisés uniquement. Veuillez ne pas l'utiliser contre des systèmes sans autorisation.
BeyondTrust Remote Support (RS) et Privileged Remote Access (PRA) sont des appliances qui servent d'intermédiaires pour les sessions à distance privilégiées vers les systèmes internes d'une organisation. Elles sont donc fréquemment exposées à Internet et occupent une position de confiance sur le réseau.
Un attaquant non authentifié capable d'atteindre le point de terminaison WebSocket de l'appliance peut exécuter des commandes du système d'exploitation en tant qu'utilisateur du site en enchaînant deux failles : une injection d'arguments dans le script thin-scc-wrapper de l'appliance (CVE-2024-12356) et un contournement d'échappement de chaîne PostgreSQL qui transforme un octet UTF-8 invalide en une rupture anticipée de littéral SQL (CVE-2025-1094). Le chemin vulnérable est atteint avant toute authentification.
bt_rs_rce_check.py dans ce dépôt est un détecteur non destructif pour cette chaîne. Il emprunte exactement le chemin de code non authentifié utilisé par le véritable exploit mais s'arrête à la preuve d'accessibilité : la seule chose qu'il demande à la cible d'exécuter est un sleep bénin (une différentielle temporelle) ou une recherche bénigne de nom d'hôte/HTTP vers un collecteur hors bande que vous contrôlez. Il n'ouvre jamais de shell, n'écrit pas de fichiers, ne lit pas de données, ne persiste pas et ne se déplace pas latéralement.
psql PostgreSQL à UTF-8 invalide, enchaînée pour compléter l'exécution de code à distanceBT24-10-ONPREM1 / BT24-10-ONPREM2 pour les appliances auto-hébergées ; les instances cloud ont été corrigées par BeyondTrust).CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HLa chaîne permet une exécution de code à distance non authentifiée en tant qu'utilisateur du site sur une appliance dont l'objectif même est de servir d'intermédiaire pour l'accès privilégié aux systèmes internes. Une seule requête anonyme transforme donc un hôte RS ou PRA exposé en point d'ancrage et en pivot vers chaque système en aval que l'appliance gère.
Elle ne nécessite aucun identifiant, aucune interaction utilisateur et aucun accès préalable : l'attaquant est externe et anonyme, et la seule condition préalable est l'accessibilité réseau au point de terminaison WebSocket de l'appliance.
La vulnérabilité a été divulguée après avoir été découverte exploitée dans la nature, a été ajoutée au catalogue des vulnérabilités exploitées connues de la CISA le 19 décembre 2024, et a été publiquement liée à la violation de décembre 2024 du département du Trésor des États-Unis attribuée à un acteur parrainé par un État.
La logique vulnérable se trouve dans le script shell thin-scc-wrapper de l'appliance, qui lit une clé de session contrôlée par l'attaquant (gskey) à partir d'une trame WebSocket non authentifiée et la transmet vers la base de données. L'exécution de code à distance complète est une chaîne de trois problèmes distincts.
1. Injection d'arguments dans thin-scc-wrapper (CVE-2024-12356). Le wrapper transmet la gskey non fiable à un assistant sans guillemets, de sorte que le shell divise le mot en arguments avant que echo ne s'exécute :
quoted=$(export PHPRC="$BG_app_root/config/php-cli.ini"; echo $gskey | $ingrediRoot/app/dbquote)
Une clé commençant par -e transforme echo en echo -e, qui interprète les séquences d'échappement par antislash et permet à l'attaquant d'émettre des octets bruts arbitraires — surtout \xC0 — dans les données transmises à l'étape suivante. L'attaquant contrôle un drapeau d'une commande existante plutôt que d'injecter une nouvelle commande, c'est pourquoi il s'agit d'une injection d'arguments (CWE-88) plutôt que d'une injection de commande classique.
2. Contournement d'échappement PostgreSQL via UTF-8 invalide (CVE-2025-1094). dbquote échappe la valeur avec pg_escape_string() de PHP, qui appelle PQescapeStringInternal() de libpq. Pour un caractère multi-octets, il fait confiance à la longueur rapportée par pg_encoding_mblen() et copie les octets du caractère textuellement, sans les valider :
len = pg_encoding_mblen(encoding, source);
for (i = 0; i < len; i++) /* copier le caractère */
*target++ = *source++;
Un octet comme 0xC0 annonce un caractère de 2 octets, de sorte que l'échappeur avale l'octet suivant comme son « octet de continuation » — même lorsque cet octet est une apostrophe (0x27). La séquence 0xC0 0x27 passe donc avec un octet d'apostrophe non échappé toujours intégré dans la chaîne « échappée ».
3. psql sort du littéral et exécute \! (CVE-2025-1094). La chaîne « échappée » est transmise à psql, qui ne traite pas 0xC0 0x27 comme un seul caractère, de sorte que le 0x27 ferme le littéral de chaîne SQL prématurément et que tout ce qui suit est analysé comme une nouvelle entrée. L'attaquant utilise cela pour atteindre la méta-commande \! de psql, qui exécute une commande shell en tant qu'utilisateur du site :
<0xC0>'; \! <cmd> #
Rapid7 a constaté que l'exécution de code à distance en pratique repose toujours sur CVE-2025-1094, et que cela suffit à lui seul : la livraison de l'octet brut 0xC0 dans une trame WebSocket binaire (plutôt qu'une trame texte, où la validation UTF-8 le supprimerait) atteint gskey sans modification et déclenche la rupture SQL sans aucune étape echo -e. Ce détecteur utilise cette approche par trame binaire.
Toute la chaîne est accessible pré-authentification via un seul WebSocket :