Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2024-12356 — Non-destructive detector for unauthenticated RCE in BeyondTrust Remote Support and PRA, chaining argument injection and PostgreSQL escape bypass to verify exploitability via time-based differential. | Kitploit
Tools/GitHubGitHub/skraft9/cve-2024-12356
Vulnerability ScannersVulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingRed Teaming
GitHubskraft9/cve-2024-12356

CVE-2024-12356

Non-destructive detector for unauthenticated RCE in BeyondTrust Remote Support and PRA, chaining argument injection and PostgreSQL escape bypass to verify exploitability via time-based differential.

View Repository
1921 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Unauthenticated Remote Code Execution in BeyondTrust Remote Support and Privileged Remote Access via Argument Injection and a PostgreSQL String-Escape Bypass

Ethical Warning: Research, educational, and authorized testing purposes only. Please do not use against systems without permission.


BeyondTrust Remote Support (RS) and Privileged Remote Access (PRA) are appliances that broker privileged remote sessions into an organization's internal systems, so they are frequently exposed to the internet and hold a trusted position on the network.

An unauthenticated attacker who can reach the appliance's WebSocket endpoint can execute operating-system commands as the site user by chaining two flaws: an argument injection in the appliance's thin-scc-wrapper script (CVE-2024-12356) and a PostgreSQL string-escape bypass that turns an invalid UTF-8 byte into an early SQL-literal break (CVE-2025-1094). The vulnerable path is reached before any authentication.

bt_rs_rce_check.py in this repository is a non-destructive detector for that chain. It drives the exact unauthenticated code path the real exploit uses but stops at proof-of-reachability: the only thing it ever asks the target to run is a benign sleep (a time-based differential) or a benign hostname/HTTP lookup to an out-of-band collector you control. It never opens a shell, writes files, reads data, persists, or moves laterally.

  • CVE IDs:
    • CVE-2024-12356 — command/argument injection in BeyondTrust RS and PRA
    • CVE-2025-1094 — PostgreSQL psql invalid-UTF-8 SQL-injection flaw, chained to complete the RCE
  • Vulnerability Type:
    • Root cause: CWE-88 Argument Injection (BeyondTrust classified CVE-2024-12356 as CWE-77; Rapid7's analysis argues CWE-88 is more accurate)
    • Chained flaw: CWE-89 SQL Injection via improper handling of invalid UTF-8 (CVE-2025-1094)
    • Net impact: CWE-78 OS Command Injection (unauthenticated RCE)
  • Affected Software: BeyondTrust Remote Support (RS) and Privileged Remote Access (PRA).
  • Affected Versions: 24.3.1 and earlier (all unpatched on-prem and, at disclosure, cloud builds).
  • Fix: BeyondTrust patch BT24-10 (BT24-10-ONPREM1 / BT24-10-ONPREM2 for self-hosted appliances; cloud instances were patched by BeyondTrust).
  • Score: 9.8 (Critical) CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
  • Exploitation status: Actively exploited in the wild; listed in the CISA KEV catalog.

Impact

The chain yields unauthenticated remote code execution as the site user on an appliance whose entire purpose is to broker privileged access into internal systems, so a single anonymous request converts an exposed RS or PRA host into a foothold and a pivot toward every downstream system the appliance mediates.

It requires no credentials, no user interaction, and no prior access: the attacker is external and anonymous, and the only prerequisite is network reachability to the appliance's WebSocket endpoint.

The vulnerability was disclosed after it was found being exploited in the wild, was added to the CISA Known Exploited Vulnerabilities catalog on 19 December 2024, and has been publicly linked to the December 2024 breach of the U.S. Department of the Treasury attributed to a state-sponsored actor.


The Vulnerability Chain

The vulnerable logic lives in the appliance's thin-scc-wrapper shell script, which reads an attacker-controlled session key (gskey) from an unauthenticated WebSocket frame and passes it toward the database. Full RCE is a chain of three distinct problems.

1. Argument injection in thin-scc-wrapper (CVE-2024-12356). The wrapper passes the untrusted gskey to a helper unquoted, so the shell word-splits it into arguments before echo runs:

root@kitploit:~
quoted=$(export PHPRC="$BG_app_root/config/php-cli.ini"; echo $gskey | $ingrediRoot/app/dbquote)

A key that begins with -e turns echo into echo -e, which interprets backslash escapes and lets the attacker emit arbitrary raw bytes — most importantly \xC0 — into the data flowing to the next stage. The attacker controls a flag of an existing command rather than injecting a new command, which is why this is argument injection (CWE-88) rather than classic command injection.

2. PostgreSQL escape bypass via invalid UTF-8 (CVE-2025-1094). dbquote escapes the value with PHP's pg_escape_string(), which calls libpq's PQescapeStringInternal(). For a multibyte character it trusts the length reported by pg_encoding_mblen() and copies the character's bytes verbatim, without validating them:

root@kitploit:~
len = pg_encoding_mblen(encoding, source);
for (i = 0; i < len; i++)   /* copy the character */
    *target++ = *source++;

A byte like 0xC0 announces a 2-byte character, so the escaper swallows the next byte as its "continuation" — even when that byte is a single quote (0x27). The sequence 0xC0 0x27 therefore passes through with an unescaped single-quote byte still embedded in the "escaped" string.

3. psql breaks out of the literal and runs \! (CVE-2025-1094). The "escaped" string is piped to psql, which does not treat 0xC0 0x27 as one character, so the 0x27 closes the SQL string literal early and everything after it is parsed as new input. The attacker uses that to reach psql's \! meta-command, which runs a shell command as the site user:

root@kitploit:~
<0xC0>'; \! <cmd> #

Rapid7 found that RCE in practice always turns on CVE-2025-1094, and that it suffices on its own: delivering the raw 0xC0 byte inside a binary WebSocket frame (rather than a text frame, where UTF-8 validation would strip it) reaches gskey unmodified and triggers the SQL breakout with no echo -e step at all. This detector uses that binary-frame approach.


Reachability

The entire chain is reachable pre-authentication over a single WebSocket:

  1. Endpoint — an unauthenticated WebSocket to /nw (a Tornado handler on the appliance).
  2. App selection — the vulnerable "thin" app is selected with the Sec-WebSocket-Protocol: ingredi support desk customer thin header, sent URL-encoded as ingredi%20support%20desk%20customer%20thin.
  3. Company resolution — the target tenant is resolved from the HTTP Host header (mapped to an installed company) or, as a fallback, the X-Ns-Company header. If neither maps to an installed company the appliance closes the socket before gskey is processed.
  4. Payload — a newline-delimited binary frame carrying protocol version 1, a thinMint UUID, authType 0 (gskey auth), then the malicious gskey (version 1 means there is no locale_code line):
root@kitploit:~
1
<thinMint UUID>
0
<0xC0>'; \! <cmd> #

Detection

BT24-10 adds an input-validation gate that rejects any non-alphanumeric gskey before it reaches dbquote/psql:

root@kitploit:~
elif [[ ! "$gskey" =~ ^[a-zA-Z0-9]{32}$ ]]; then
    blog "bad session key given"
    ...
    exit 1

Any key containing 0xC0, a quote, or a shell metacharacter is rejected and the script exits, so a patched appliance produces no 1 failure reply and no command execution. The detector turns that behavioral difference into an egress-independent time-based differential that needs no outbound connectivity from the target:

  • Control — a valid-format gskey (A × 32). On both patched and unpatched builds this reaches the DB lookup and returns ['2\n', '1 failure\n'] quickly.
  • Injection — <0xC0>'; \! sleep <delay> #. On a vulnerable host psql runs the injected sleep, so the 1 failure reply is delayed by roughly <delay> seconds. On a patched host the gskey regex rejects the key, the script exits, and the socket closes fast with no reply.

Because the verdict rests on the timing of the appliance's own reply, it holds even when the target blocks outbound DNS/HTTP — a case where an OAST callback alone would false-negative. The optional callback mode is corroboration only, for hosts that do allow egress.


Usage

Install the one dependency:

root@kitploit:~
pip install -r requirements.txt

Differential mode (recommended, egress-independent):

root@kitploit:~
python3 bt_rs_rce_check.py --target rs.example.com --mode differential

Differential with OAST corroboration:

root@kitploit:~
python3 bt_rs_rce_check.py --target rs.example.com \
    --oast <your-collector>.oast.pro --mode both

When the Host header does not resolve to a tenant, provide an explicit slug, or a file of candidate slugs (one per line) tried in turn via the X-Ns-Company header:

root@kitploit:~
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

Key options:

OptionMeaning
--target <host>Appliance virtual host / FQDN (required).
--company <slug>Explicit tenant slug, sent as X-Ns-Company.
--company-list <file>File of candidate slugs, tried until one resolves.
--oast <domain>Out-of-band collector domain for callback corroboration.
--mode {differential,callback,both}Detection strategy (default differential).
--delay <seconds>sleep duration for the time-based test (default 9).
--timeout <seconds>Per-probe socket timeout (default 25).
--header 'H: v'Extra raw request header; repeatable.

Reading the outcome:

  • VULNERABLE — the injected 1 failure reply was delayed by roughly --delay seconds relative to the control. The sleep executed; the unauthenticated RCE chain is exploitable on this host.
  • PATCHED — the control returned 1 failure fast, but the injection was rejected with no reply. The BT24-10 gskey regex is in place and the injection never reaches the psql sink.
  • UNRESOLVED ("company did not resolve") — neither probe produced a 1 failure, so the control never reached the gskey handler either. This is not a patched result; the appliance closed the socket because the Host/company did not map to an installed company. Retry with the correct virtual host (--target) or a valid slug (--company / --company-list).

Remediation

Apply BT24-10 (BT24-10-ONPREM1 / BT24-10-ONPREM2) or upgrade beyond 24.3.1. Because the chain also depends on the PostgreSQL psql flaw (CVE-2025-1094), keep PostgreSQL client tooling patched as well, and restrict network exposure of the appliance's WebSocket endpoint where feasible.


References

  • CVE-2024-12356 — NVD entry: BeyondTrust RS/PRA command/argument injection (CVSS 9.8).
  • CVE-2025-1094 — NVD entry: PostgreSQL psql invalid-UTF-8 / SQL-injection flaw, chained to complete the RCE.
  • BeyondTrust advisory BT24-10 — official vendor security advisory and patch for the RS/PRA command injection.
  • CISA KEV catalog entry — CVE-2024-12356, added 19 December 2024, and the CISA alert announcing the addition.
  • Rapid7 Analysis: CVE-2024-12356 — recreated the unauthenticated RCE and discovered the chained PostgreSQL flaw CVE-2025-1094.
  • Metasploit exploit module — rapid7/metasploit-framework PR #19877, unauthenticated RCE against BeyondTrust RS/PRA.

Legal

This software is provided for authorized security testing and defensive research only. Run it exclusively against systems you own or are explicitly authorized in writing to test. It is a non-destructive detector that deliberately avoids weaponized command execution, data access, and persistence. You are solely responsible for complying with all applicable laws and for obtaining proper authorization; the authors accept no liability for misuse.

Download Tool