## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-SKRAFT9-CVE-2024-12356
## BeyondTrust Remote Support 与 Privileged Remote Access 中经由参数注入与 PostgreSQL 字符串转义绕过实现未认证远程代码执行
> _**道德警告:** 仅限研究、教育与授权测试用途。请勿在未经许可的系统上使用。_
* * *
BeyondTrust Remote Support (RS) 与 Privileged Remote Access (PRA) 是用于代理进入组织内部系统的特权远程会话的设备,因此它们经常暴露于互联网,并在网络中占据受信任的位置。
能够访问设备 WebSocket 端点的未认证攻击者,可通过串联两个漏洞以 site 用户身份执行操作系统命令:设备 `thin-scc-wrapper` 脚本中的参数注入(CVE-2024-12356),以及一个将无效 UTF-8 字节转变为提前中断 SQL 字面量的 PostgreSQL 字符串转义绕过(CVE-2025-1094)。该漏洞路径在任何认证之前即可触达。
本仓库中的 `bt_rs_rce_check.py` 是针对该漏洞链的**非破坏性检测器** 。它驱动真实漏洞利用所使用的完全相同的未认证代码路径,但止步于可达性证明:它唯一要求目标执行的是良性的 `sleep`(基于时间的差分)或向您控制的带外收集器发起良性的主机名/HTTP 查询。它从不打开 shell、写入文件、读取数据、持久化或横向移动。
* **CVE 编号:**
* CVE-2024-12356 — BeyondTrust RS 与 PRA 中的命令/参数注入
* CVE-2025-1094 — PostgreSQL `psql` 无效 UTF-8 SQL 注入缺陷,串联以完成 RCE
* **漏洞类型:**
* 根本原因:CWE-88 参数注入(BeyondTrust 将 CVE-2024-12356 归类为 CWE-77;Rapid7 的分析认为 CWE-88 更为准确)
* 串联缺陷:CWE-89 因不当处理无效 UTF-8 导致的 SQL 注入(CVE-2025-1094)
* 最终影响:CWE-78 操作系统命令注入(未认证 RCE)
* **受影响软件:** BeyondTrust Remote Support (RS) 与 Privileged Remote Access (PRA)。
* **受影响版本:** 24.3.1 及更早版本(所有未修补的本地部署版本,以及披露时的云端构建版本)。
* **修复方案:** BeyondTrust 补丁 BT24-10(自托管设备使用 `BT24-10-ONPREM1` / `BT24-10-ONPREM2`;云端实例已由 BeyondTrust 修补)。
* **评分:** 9.8(严重)`CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H`
* **利用状态:** 已在野外被积极利用;已列入 CISA KEV 目录。
* * *
## 影响
该漏洞链可在 site 用户身份下实现未认证远程代码执行,而该设备的全部用途就是代理进入内部系统的特权访问,因此单个匿名请求即可将暴露的 RS 或 PRA 主机转化为立足点,并以此为跳板攻击该设备所中介的每一个下游系统。
它不需要任何凭据、用户交互或先前访问权限:攻击者来自外部且匿名,唯一前提是能够通过网络访问设备的 WebSocket 端点。
该漏洞在发现已被野外利用后才被披露,于 2024 年 12 月 19 日被加入 CISA 已知被利用漏洞目录,并已被公开关联到 2024 年 12 月美国财政部遭国家支持行为体攻击的事件。
* * *
## 漏洞链
易受攻击的逻辑位于设备的 `thin-scc-wrapper` shell 脚本中,该脚本从未认证的 WebSocket 帧中读取攻击者控制的会话密钥(`gskey`),并将其传递给数据库。完整的 RCE 是三个不同问题的串联。
**1.`thin-scc-wrapper` 中的参数注入(CVE-2024-12356)。** 该包装脚本将不受信任的 `gskey` **不带引号** 地传递给辅助程序,因此 shell 会在 `echo` 运行前将其按单词拆分为参数:
root@kitploit:~
quoted=$(export PHPRC="$BG_app_root/config/php-cli.ini"; echo $gskey | $ingrediRoot/app/dbquote)
以 `-e` 开头的密钥会将 `echo` 变为 `echo -e`,后者会解释反斜杠转义,使攻击者能够向下一阶段的数据流中注入**任意原始字节** ——最重要的是 `\xC0`。攻击者控制的是现有命令的一个 _标志_ ,而非注入新命令,这就是为什么这是参数注入(CWE-88)而非经典命令注入。
**2\. 经由无效 UTF-8 的 PostgreSQL 转义绕过(CVE-2025-1094)。** `dbquote` 使用 PHP 的 `pg_escape_string()` 对该值进行转义,后者调用 libpq 的 `PQescapeStringInternal()`。对于多字节字符,它信任 `pg_encoding_mblen()` 报告的长度,并**逐字复制** 该字符的字节,**而不进行验证** :
root@kitploit:~
len = pg_encoding_mblen(encoding, source);
for (i = 0; i < len; i++) /* copy the character */
*target++ = *source++;
像 `0xC0` 这样的字节声明了一个 2 字节字符,因此转义器会将下一个字节吞入作为其“续字节”——即使该字节是单引号(`0x27`)。因此,序列 `0xC0 0x27` 会带着一个**未转义的单引号字节** 通过“已转义”的字符串。
**3.`psql` 跳出字面量并运行 `\!`(CVE-2025-1094)。** “已转义”的字符串被管道传递给 `psql`,后者不会将 `0xC0 0x27` 视为一个字符,因此 `0x27` 会提前闭合 SQL 字符串字面量,其后的所有内容都会被解析为新输入。攻击者利用这一点触达 `psql` 的 `\!` 元命令,该命令以 site 用户身份运行 shell 命令:
root@kitploit:~
<0xC0>'; \! <cmd> #
Rapid7 发现,实际中的 RCE 总是依赖 **CVE-2025-1094** ,且该漏洞单独即可成立:在**二进制** WebSocket 帧中传递原始 `0xC0` 字节(而非文本帧——文本帧中的 UTF-8 验证会将其剥离)即可使 `gskey` 原样到达并触发 SQL 跳出,完全无需 `echo -e` 步骤。本检测器即采用这种二进制帧方法。
* * *
## 可达性
整个漏洞链可在**认证前** 通过单个 WebSocket 触达:
1. **端点** — 到 `/nw` 的未认证 WebSocket(设备上的 Tornado 处理器)。
2. **应用选择** — 使用 `Sec-WebSocket-Protocol: ingredi support desk customer thin` 标头选择易受攻击的“thin”应用,以 URL 编码形式发送为 `ingredi%20support%20desk%20customer%20thin`。
3. **公司解析** — 目标租户从 HTTP `Host` 标头(映射到已安装的公司)解析,或作为后备方案使用 `X-Ns-Company` 标头。如果两者均未映射到已安装的公司,设备会在处理 `gskey` 之前关闭套接字。
4. **载荷** — 一个以换行符分隔的**二进制** 帧,携带协议版本 `1`、一个 `thinMint` UUID、`authType` `0`(gskey 认证),然后是恶意的 gskey(版本 `1` 意味着没有 `locale_code` 行):
root@kitploit:~
1
<thinMint UUID>
0
<0xC0>'; \! <cmd> #
* * *
## 检测
BT24-10 增加了一个输入验证门,在 `gskey` **到达** `dbquote`/`psql` **之前** 拒绝任何非字母数字的 `gskey`:
root@kitploit:~
elif [[ ! "$gskey" =~ ^[a-zA-Z0-9]{32}$ ]]; then
blog "bad session key given"
...
exit 1
任何包含 `0xC0`、引号或 shell 元字符的密钥都会被拒绝,脚本随即退出,因此已修补的设备不会产生 `1 failure` 回复,也不会执行任何命令。检测器将该行为差异转化为一种**不依赖出口流量** 的基于时间的差分,无需目标具备出站连接能力:
* **对照** — 格式合法的 gskey(`A` × 32)。在已修补和未修补的构建上,这都会到达数据库查询并**快速** 返回 `['2\n', '1 failure\n']`。
* **注入** — `<0xC0>'; \! sleep <delay> #`。在**易受攻击** 的主机上,`psql` 会运行注入的 `sleep`,因此 `1 failure` 回复会**延迟** 约 `<delay>` 秒。在**已修补** 的主机上,gskey 正则表达式会拒绝该密钥,脚本退出,套接字**快速关闭且无回复** 。
由于判定依据是设备自身回复的时序,因此即使目标阻止出站 DNS/HTTP 也能成立——在这种情况下,仅靠 OAST 回调会产生误报。可选的回调模式仅作为佐证,适用于确实允许出站流量的主机。
* * *
## 使用方法
安装唯一依赖:
root@kitploit:~
pip install -r requirements.txt
**差分模式(推荐,不依赖出口流量):**
root@kitploit:~
python3 bt_rs_rce_check.py --target rs.example.com --mode differential
**带 OAST 佐证的差分模式:**
root@kitploit:~
python3 bt_rs_rce_check.py --target rs.example.com \
--oast <your-collector>.oast.pro --mode both
**当`Host` 标头无法解析到租户时,** 提供显式 slug,或提供一个候选 slug 文件(每行一个),通过 `X-Ns-Company` 标头依次尝试:
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
**主要选项:**
**解读结果:**
* **`VULNERABLE`** — 注入的 `1 failure` 回复相对于对照延迟了约 `--delay` 秒。`sleep` 已执行;该主机上的未认证 RCE 漏洞链可利用。
* **`PATCHED`** — 对照快速返回 `1 failure`,但注入被拒绝且无回复。BT24-10 的 gskey 正则已生效,注入从未到达 `psql` 汇点。
* **`UNRESOLVED`(“company did not resolve”)** — _两个_ 探测均未产生 `1 failure`,因此对照也从未到达 gskey 处理器。这**不是** 已修补的结果;设备因 `Host`/公司未映射到已安装的公司而关闭了套接字。请使用正确的虚拟主机(`--target`)或有效的 slug(`--company` / `--company-list`)重试。
* * *
## 修复建议
应用 BT24-10(`BT24-10-ONPREM1` / `BT24-10-ONPREM2`)或升级至 24.3.1 以上版本。由于该漏洞链还依赖 PostgreSQL `psql` 缺陷(CVE-2025-1094),请同时保持 PostgreSQL 客户端工具已修补,并在可行的情况下限制设备 WebSocket 端点的网络暴露。
* * *
## 参考资料
* CVE-2024-12356 — NVD 条目:BeyondTrust RS/PRA 命令/参数注入(CVSS 9.8)。
* CVE-2025-1094 — NVD 条目:PostgreSQL `psql` 无效 UTF-8 / SQL 注入缺陷,串联以完成 RCE。
* BeyondTrust 公告 BT24-10 — 针对 RS/PRA 命令注入的官方厂商安全公告与补丁。
* CISA KEV 目录条目 — CVE-2024-12356,于 2024 年 12 月 19 日添加,以及宣布添加该条目的 CISA 警报。
* Rapid7 分析:CVE-2024-12356 — 重现了未认证 RCE 并发现了串联的 PostgreSQL 缺陷 CVE-2025-1094。
* Metasploit 漏洞利用模块 — `rapid7/metasploit-framework` PR #19877,针对 BeyondTrust RS/PRA 的未认证 RCE。
* * *
## 法律声明
本软件仅供**授权安全测试与防御性研究** 使用。请仅针对您拥有或获得书面明确授权测试的系统运行。它是一个非破坏性检测器,刻意避免武器化的命令执行、数据访问与持久化。您有责任遵守所有适用法律并获得适当授权;作者对滥用行为不承担任何责任。