
Nicht-destruktiver Detektor für nicht authentifizierte RCE in BeyondTrust Remote Support und PRA, der Argument-Injection und PostgreSQL-Escape-Bypass miteinander verknüpft, um die Ausnutzbarkeit über zeitbasierte Differenzanalyse zu verifizieren.
Ethischer Hinweis: Nur für Forschungs-, Bildungs- und autorisierte Testzwecke. Bitte nicht gegen Systeme ohne Erlaubnis verwenden.
BeyondTrust Remote Support (RS) und Privileged Remote Access (PRA) sind Appliances, die privilegierte Remote-Sitzungen in die internen Systeme einer Organisation vermitteln. Daher sind sie häufig im Internet erreichbar und nehmen eine vertrauenswürdige Position im Netzwerk ein.
Ein nicht authentifizierter Angreifer, der den WebSocket-Endpunkt der Appliance erreichen kann, kann Betriebssystembefehle als der Site-Benutzer ausführen, indem er zwei Schwachstellen miteinander verkettet: eine Argument-Injection im thin-scc-wrapper-Skript der Appliance (CVE-2024-12356) und eine Umgehung des PostgreSQL-String-Escapings, die ein ungültiges UTF-8-Byte in einen vorzeitigen SQL-Literal-Bruch verwandelt (CVE-2025-1094). Der verwundbare Pfad wird vor jeglicher Authentifizierung erreicht.
bt_rs_rce_check.py in diesem Repository ist ein nicht-destruktiver Detektor für diese Kette. Er durchläuft exakt den nicht authentifizierten Codepfad, den der echte Exploit verwendet, stoppt jedoch beim Nachweis der Erreichbarkeit: Das Einzige, was er das Ziel jemals ausführen lässt, ist ein harmloses sleep (eine zeitbasierte Differenzmessung) oder ein harmloser Hostname-/HTTP-Lookup an einen Out-of-Band-Collector, den Sie kontrollieren. Er öffnet niemals eine Shell, schreibt keine Dateien, liest keine Daten, bleibt nicht persistent und bewegt sich nicht lateral.
psql-SQL-Injection-Schwachstelle durch ungültiges UTF-8, verkettet zur vollständigen RCEBT24-10-ONPREM1 / BT24-10-ONPREM2 für selbst gehostete Appliances; Cloud-Instanzen wurden von BeyondTrust gepatcht).CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HDie Kette führt zu nicht authentifizierter Remote-Codeausführung als der Site-Benutzer auf einer Appliance, deren gesamter Zweck darin besteht, privilegierten Zugriff auf interne Systeme zu vermitteln. Eine einzige anonyme Anfrage verwandelt einen exponierten RS- oder PRA-Host in einen Ausgangspunkt und ein Sprungbrett zu jedem nachgelagerten System, das die Appliance vermittelt.
Es sind keine Anmeldeinformationen, keine Benutzerinteraktion und kein vorheriger Zugriff erforderlich: Der Angreifer ist extern und anonym, und die einzige Voraussetzung ist die Netzwerkerreichbarkeit des WebSocket-Endpunkts der Appliance.
Die Schwachstelle wurde offengelegt, nachdem festgestellt wurde, dass sie in freier Wildbahn ausgenutzt wird. Sie wurde am 19. Dezember 2024 in den Katalog bekannter ausgenutzter Schwachstellen der CISA aufgenommen und öffentlich mit dem Datenverstoß vom Dezember 2024 beim US-Finanzministerium in Verbindung gebracht, der einem staatlich geförderten Akteur zugeschrieben wird.
Die verwundbare Logik befindet sich im Shell-Skript thin-scc-wrapper der Appliance, das einen vom Angreifer kontrollierten Sitzungsschlüssel (gskey) aus einem nicht authentifizierten WebSocket-Frame liest und an die Datenbank weiterleitet. Vollständige RCE ist eine Kette aus drei unterschiedlichen Problemen.
1. Argument-Injection in thin-scc-wrapper (CVE-2024-12356). Der Wrapper übergibt den nicht vertrauenswürdigen gskey unquotiert an einen Helfer, sodass die Shell das Wort vor der Ausführung von echo in Argumente aufteilt:
quoted=$(export PHPRC="$BG_app_root/config/php-cli.ini"; echo $gskey | $ingrediRoot/app/dbquote)
Ein Schlüssel, der mit -e beginnt, verwandelt echo in echo -e, das Backslash-Escapes interpretiert und es dem Angreifer ermöglicht, beliebige Rohbytes auszugeben — am wichtigsten \xC0 — in die Daten, die zur nächsten Stufe fließen. Der Angreifer kontrolliert ein Flag eines vorhandenen Befehls, anstatt einen neuen Befehl zu injizieren. Deshalb handelt es sich um Argument-Injection (CWE-88) und nicht um klassische Befehlsinjektion.
2. PostgreSQL-Escape-Umgehung durch ungültiges UTF-8 (CVE-2025-1094). dbquote escaped den Wert mit PHP's pg_escape_string(), das PQescapeStringInternal() von libpq aufruft. Für ein Multibyte-Zeichen vertraut es der Länge, die von pg_encoding_mblen() gemeldet wird, und kopiert die Bytes des Zeichens wörtlich, ohne sie zu validieren:
len = pg_encoding_mblen(encoding, source);
for (i = 0; i < len; i++) /* copy the character */
*target++ = *source++;
Ein Byte wie 0xC0 kündigt ein 2-Byte-Zeichen an, sodass der Escaper das nächste Byte als seine „Fortsetzung" verschluckt — selbst wenn dieses Byte ein einfaches Anführungszeichen (0x27) ist. Die Sequenz 0xC0 0x27 passiert daher mit einem nicht-escapten einfachen Anführungszeichen-Byte, das weiterhin in der „escapten" Zeichenkette eingebettet ist.
3. psql bricht aus dem Literal aus und führt \! aus (CVE-2025-1094). Die „escapete" Zeichenkette wird an psql weitergeleitet, das 0xC0 0x27 nicht als ein Zeichen behandelt. Daher schließt das 0x27 das SQL-String-Literal vorzeitig, und alles danach wird als neue Eingabe geparst. Der Angreifer nutzt dies, um die \!-Meta-Befehl von psql zu erreichen, der einen Shell-Befehl als der Site-Benutzer ausführt:
<0xC0>'; \! <cmd> #
Rapid7 stellte fest, dass RCE in der Praxis immer auf CVE-2025-1094 beruht und dass diese allein ausreicht: Die Zustellung des rohen 0xC0-Bytes innerhalb eines binären WebSocket-Frames (anstatt eines Text-Frames, wo UTF-8-Validierung es entfernen würde) erreicht gskey unverändert und löst den SQL-Ausbruch ohne jeden echo -e-Schritt aus. Dieser Detektor verwendet diesen Binär-Frame-Ansatz.
Die gesamte Kette ist vor der Authentifizierung über einen einzelnen WebSocket erreichbar:
/nw (ein Tornado-Handler auf der Appliance).Sec-WebSocket-Protocol: ingredi support desk customer thin ausgewählt, URL-kodiert als ingredi%20support%20desk%20customer%20thin gesendet.Host-Header aufgelöst (zugeordnet zu einer installierten Firma) oder, als Fallback, aus dem X-Ns-Company-Header. Wenn keiner einer installierten Firma zugeordnet werden kann, schließt die Appliance den Socket, bevor gskey verarbeitet wird.1, eine thinMint-UUID, authType 0 (gskey-Authentifizierung) und dann den bösartigen gskey trägt (Version 1 bedeutet, dass es keine locale_code-Zeile gibt):1
<thinMint UUID>
0
<0xC0>'; \! <cmd> #
BT24-10 fügt ein Eingabevalidierungs-Gate hinzu, das jeden nicht-alphanumerischen gskey bevor er dbquote/psql erreicht, ablehnt:
elif [[ ! "$gskey" =~ ^[a-zA-Z0-9]{32}$ ]]; then
blog "bad session key given"
...
exit 1
Jeder Schlüssel, der 0xC0, ein Anführungszeichen oder ein Shell-Metazeichen enthält, wird abgelehnt und das Skript beendet sich. Eine gepatchte Appliance erzeugt daher keine 1 failure-Antwort und keine Befehlsausführung. Der Detektor verwandelt diesen Verhaltensunterschied in eine egress-unabhängige zeitbasierte Differenzmessung, die keine ausgehende Konnektivität vom Ziel benötigt:
A × 32). Sowohl auf gepatchten als auch auf ungepatchten Builds erreicht dies den DB-Lookup und gibt ['2\n', '1 failure\n'] schnell zurück.<0xC0>'; \! sleep <delay> #. Auf einem verwundbaren Host führt psql das injizierte sleep aus, sodass die 1 failure-Antwort um ungefähr <delay> Sekunden verzögert wird. Auf einem gepatchten Host lehnt die gskey-Regex den Schlüssel ab, das Skript beendet sich und der Socket schließt schnell ohne Antwort.Da das Urteil auf dem Timing der eigenen Antwort der Appliance beruht, gilt es selbst dann, wenn das Ziel ausgehendes DNS/HTTP blockiert — ein Fall, in dem ein OAST-Callback allein ein falsch-negatives Ergebnis liefern würde. Der optionale Callback-Modus dient nur der Bestätigung für Hosts, die ausgehenden Datenverkehr zulassen.
Installieren Sie die eine Abhängigkeit:
pip install -r requirements.txt
Differenzmodus (empfohlen, egress-unabhängig):
python3 bt_rs_rce_check.py --target rs.example.com --mode differential
Differenzmodus mit OAST-Bestätigung:
python3 bt_rs_rce_check.py --target rs.example.com \
--oast <ihr-collector>.oast.pro --mode both
Wenn der Host-Header nicht zu einem Mandanten aufgelöst wird, geben Sie einen expliziten Slug oder eine Datei mit Kandidaten-Slugs an (eine pro Zeile), die nacheinander über den X-Ns-Company-Header versucht werden:
python3 bt_rs_rce_check.py --target rs.example.com --company acme
python3 bt_rs_rce_check.py --target rs.example.com --company-list slugs.txt
Wichtige Optionen:
| Option | Bedeutung |
|---|---|
--target <host> | Virtueller Host / FQDN der Appliance (erforderlich). |
--company <slug> | Expliziter Mandanten-Slug, gesendet als X-Ns-Company. |
--company-list <datei> | Datei mit Kandidaten-Slugs, versucht bis einer aufgelöst wird. |
--oast <domain> | Out-of-Band-Collector-Domain für Callback-Bestätigung. |
--mode {differential,callback,both} | Erkennungsstrategie (Standard differential). |
--delay <sekunden> | sleep-Dauer für den zeitbasierten Test (Standard 9). |
--timeout <sekunden> | Socket-Timeout pro Probe (Standard 25). |
--header 'H: v' | Zusätzlicher roher Anfrage-Header; wiederholbar. |
Interpretation des Ergebnisses:
VULNERABLE — die injizierte 1 failure-Antwort wurde um ungefähr --delay Sekunden relativ zur Kontrolle verzögert. Das sleep wurde ausgeführt; die nicht authentifizierte RCE-Kette ist auf diesem Host ausnutzbar.PATCHED — die Kontrolle gab 1 failure schnell zurück, aber die Injection wurde ohne Antwort abgelehnt. Die BT24-10-gskey-Regex ist aktiv und die Injection erreicht die psql-Senke nie.UNRESOLVED („company did not resolve") — keine der beiden Proben erzeugte ein 1 failure, sodass die Kontrolle auch nie den gskey-Handler erreichte. Dies ist kein gepatchtes Ergebnis; die Appliance schloss den Socket, weil der Host/die Firma keiner installierten Firma zugeordnet werden konnte. Wiederholen Sie den Vorgang mit dem korrekten virtuellen Host (--target) oder einem gültigen Slug (--company / --company-list).Wenden Sie BT24-10 (BT24-10-ONPREM1 / BT24-10-ONPREM2) an oder aktualisieren Sie über 24.3.1 hinaus. Da die Kette auch von der PostgreSQL-psql-Schwachstelle (CVE-2025-1094) abhängt, halten Sie auch die PostgreSQL-Client-Tools gepatcht und beschränken Sie die Netzwerkexposition des WebSocket-Endpunkts der Appliance, wo dies machbar ist.
psql-Schwachstelle durch ungültiges UTF-8 / SQL-Injection, verkettet zur vollständigen RCE.rapid7/metasploit-framework PR #19877, nicht authentifizierte RCE gegen BeyondTrust RS/PRA.Diese Software wird ausschließlich für autorisierte Sicherheitstests und defensive Forschung bereitgestellt. Führen Sie sie ausschließlich gegen Systeme aus, die Sie besitzen oder für die Sie ausdrücklich schriftlich zur Testung autorisiert sind. Es handelt sich um einen nicht-destruktiven Detektor, der bewusst Waffen-basierte Befehlsausführung, Datenzugriff und Persistenz vermeidet. Sie sind allein dafür verantwortlich, alle geltenden Gesetze einzuhalten und eine ordnungsgemäße Autorisierung einzuholen; die Autoren übernehmen keine Haftung für Missbrauch.