
Detector non distruttivo per RCE non autenticata in BeyondTrust Remote Support e PRA, che combina l'iniezione di argomenti e il bypass dell'escape di PostgreSQL per verificare la sfruttabilità tramite differenziale basato sul tempo.
Avvertenza Etica: Solo a scopo di ricerca, formazione e test autorizzati. Non utilizzare contro sistemi senza autorizzazione.
BeyondTrust Remote Support (RS) e Privileged Remote Access (PRA) sono appliance che fanno da intermediari per sessioni remote privilegiate verso i sistemi interni di un'organizzazione, pertanto sono spesso esposte a internet e occupano una posizione di fiducia sulla rete.
Un attaccante non autenticato che riesce a raggiungere l'endpoint WebSocket dell'appliance può eseguire comandi del sistema operativo come utente site combinando due vulnerabilità: un'iniezione di argomenti nello script thin-scc-wrapper dell'appliance (CVE-2024-12356) e un bypass dell'escape delle stringhe PostgreSQL che trasforma un byte UTF-8 non valido in un'interruzione anticipata del letterale SQL (CVE-2025-1094). Il percorso vulnerabile viene raggiunto prima di qualsiasi autenticazione.
bt_rs_rce_check.py in questo repository è un rilevatore non distruttivo per quella catena. Pilota l'esatto percorso di codice non autenticato utilizzato dal vero exploit ma si ferma alla prova di raggiungibilità: l'unica cosa che chiede mai al target di eseguire è una sleep innocua (una differenziale basata sul tempo) o una ricerca innocua di hostname/HTTP verso un collettore out-of-band che controlli tu. Non apre mai una shell, non scrive file, non legge dati, non persiste e non si muove lateralmente.
psql PostgreSQL per UTF-8 non valido, concatenata per completare la RCEBT24-10-ONPREM1 / BT24-10-ONPREM2 per appliance self-hosted; le istanze cloud sono state patchate da BeyondTrust).CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HLa catena produce l'esecuzione remota di codice non autenticata come utente site su un'appliance il cui intero scopo è fare da intermediario per l'accesso privilegiato ai sistemi interni, quindi una singola richiesta anonima converte un host RS o PRA esposto in un punto d'appoggio e in un pivot verso ogni sistema a valle che l'appliance media.
Non richiede credenziali, alcuna interazione con l'utente e alcun accesso precedente: l'attaccante è esterno e anonimo, e l'unico prerequisito è la raggiungibilità di rete dell'endpoint WebSocket dell'appliance.
La vulnerabilità è stata divulgata dopo essere stata trovata sfruttata in natura, è stata aggiunta al catalogo delle Vulnerabilità Note Sfruttate CISA il 19 dicembre 2024, ed è stata pubblicamente collegata alla violazione di dicembre 2024 del Dipartimento del Tesoro degli Stati Uniti attribuita a un attore sponsorizzato da uno stato.
La logica vulnerabile risiede nello script shell thin-scc-wrapper dell'appliance, che legge una chiave di sessione controllata dall'attaccante (gskey) da un frame WebSocket non autenticato e la passa verso il database. La RCE completa è una catena di tre problemi distinti.
1. Iniezione di argomenti in thin-scc-wrapper (CVE-2024-12356). Il wrapper passa la gskey non attendibile a un helper senza virgolette, quindi la shell la divide in argomenti prima che venga eseguita echo:
quoted=$(export PHPRC="$BG_app_root/config/php-cli.ini"; echo $gskey | $ingrediRoot/app/dbquote)
Una chiave che inizia con -e trasforma echo in echo -e, che interpreta le sequenze di escape con barra rovesciata e consente all'attaccante di emettere byte grezzi arbitrari — soprattutto \xC0 — nei dati che fluiscono verso la fase successiva. L'attaccante controlla un flag di un comando esistente piuttosto che iniettare un nuovo comando, motivo per cui questa è un'iniezione di argomenti (CWE-88) piuttosto che una classica iniezione di comandi.
2. Bypass dell'escape PostgreSQL tramite UTF-8 non valido (CVE-2025-1094). dbquote esegue l'escape del valore con pg_escape_string() di PHP, che chiama PQescapeStringInternal() di libpq. Per un carattere multibyte si fida della lunghezza riportata da pg_encoding_mblen() e copia i byte del carattere parola per parola, senza validarli:
len = pg_encoding_mblen(encoding, source);
for (i = 0; i < len; i++) /* copy the character */
*target++ = *source++;
Un byte come 0xC0 annuncia un carattere di 2 byte, quindi l'escaping ingloba il byte successivo come sua "continuazione" — anche quando quel byte è un apice singolo (0x27). La sequenza 0xC0 0x27 passa quindi con un byte di apice singolo non escapato ancora incorporato nella stringa "escapata".
3. psql esce dal letterale ed esegue \! (CVE-2025-1094). La stringa "escapata" viene passata a psql, che non tratta 0xC0 0x27 come un unico carattere, quindi 0x27 chiude il letterale della stringa SQL anticipatamente e tutto ciò che segue viene analizzato come nuovo input. L'attaccante lo usa per raggiungere il meta-comando \! di psql, che esegue un comando shell come utente site:
<0xC0>'; \! <cmd> #
Rapid7 ha scoperto che la RCE in pratica dipende sempre da CVE-2025-1094, e che essa è sufficiente da sola: consegnare il byte grezzo 0xC0 all'interno di un frame WebSocket binario (piuttosto che un frame di testo, dove la validazione UTF-8 lo eliminerebbe) raggiunge gskey senza modifiche e innesca la rottura SQL senza alcun passaggio echo -e. Questo rilevatore utilizza quell'approccio con frame binario.
L'intera catena è raggiungibile pre-autenticazione tramite un singolo WebSocket: