编码问题引起的RCE分析

admin 2025年4月2日22:28:29评论6 views字数 6128阅读20分25秒阅读模式

一、前  言

二、关键点分析

三、拓展分析

四、总  结

前  言

CVE-2024-12356命令注漏洞影BeyondTrustPrivileged Remote AccessRemote Support系列产品,并实际上依赖于PostgreSQLCVE-2025-1094漏洞。本文从BeyondTrustCVE-2024-12356为场景入口,逐步分析到PostgreSQLCVE-2025-1094,解释引起命令注入的核心编码问题。

关键点分析
CVE-2024-12356命令注入漏洞通过WebSocket访问BeyondTrust认证前路由/nw,将HTTP中的Sec-WebSocket-Protocol子协议头设定为ingredi support desk customer thin(以及设定一些其它类似Host的必需参数),即可访问到thin-scc-wrapper脚本。

01

thin-scc-wrapper分析(CVE-2024-12356)

thin-scc-wrapper文件补丁前后主要变化:

编码问题引起的RCE分析
  • read-t 30 gskey从标准输入(WebSocket数据流)中读取数据,并存储到变量gskey中,该$gskey变量数据用户可控

  • quoted=$(export PHPRC="$BG_app_root/config/php-cli.ini"; echo "$gskey" | $ingrediRoot/app/dbquote) $gskey变量数据数据传递给dbquote脚本处理处理(目的是转义不安全字符),并将其处理结果赋值给quoted

  • $(echo "SELECT COUNT(1) FROM gw_sessions WHERE session_key = $quoted AND session_type = 'sdcust' AND (expiration IS NULL OR expiration>NOW())" | $db)$quoted拼接到字符串中,并通过管道传递给$db执行(即通过psql执行拼接$quoted后的SQL语句)。

补丁中将echo $gskey变为了echo "$gskey",多出了一个双引号。它们之间的区别,可通过下面测试进行体现:

编码问题引起的RCE分析

sh环境中,可以看到echo $testecho "$test"在结果上没有区别,$test作为一个完整的字符串被打印。在bash环境中,可以看到echo $test产生了变化,变量$test字符串的开头一部分-e会被视为echo命令的一个参数(使echo解释xNN形式的数据),后续部分会被echo命令解释输出,其中的x31x32x33x34会被解释为1234;相比而言,在bash环境有双引号时,echo "$test"会原样输出$test,不会做任何解释。因此,修复前echo $gskey | $ingrediRoot/app/dbquote这种写法,意味着可以将$gskey设定为-e xNNxNN...形式的数据,从而向dbquote传入任何攻击者指定的字节数据。

02

dbquote分析(CVE-2025-1094)

前文中 $gskey 可控值被传输到名为dbquote的脚本中,该脚本内容:

编码问题引起的RCE分析

传入的$gskey先通过fgets读取,之后会交给PHP的pg_escape_string进行转义,转义后的结果会放在两个单引号之间并打印到标准输出(最后会存储在thin-scc-wrapper中名为quoted的新变量中)。

上述操作的目的是利用pg_escape_string函数转义特殊字符(如单引号),并使其在后续拼接的 SQL 语句中安全使用。如果pg_escape_string转义没有问题,那么理论上是不会产生SQL注入的,但事实上产生了CVE-2025-1094问题。

pg_escape_string的底层实现:

编码问题引起的RCE分析

可以看到pg_escape_string会进一步调用PostgreSQLPQescapeStringConn/PQescapeString,两者都会调用PQescapeStringInternal

编码问题引起的RCE分析

PQescapeStringInternal底层实现:

编码问题引起的RCE分析

为了解释上述代码,需要先解释一下什么是多字节字符。类似UTF8这样的可变字符,可以是1个字节是1个字符,也可以是2个字节或更多字节构成1个字符。本文中单个字节构成1个字符称为单字节字符,2个或以上的字节构成1个字符,称为多字节字符。上述代码是读取source中的字符进行处理,将其中的特殊字符前添加转义字符,拷贝到target中。在处理逻辑中有如下关键点:

  • source读取一个字节,如果字节最高Bit为0,视为单字节字符;否则视为多字节字符;

  • 如果是单字节字符,判断单字节字符是否为单引号'或右斜线,是的话双倍该单字节字符拷贝到target中(双倍的含义就是转义),不是的话直接将单字节字符拷贝到target中,不进行转义;

  • 如果是多字节字符,先通过pg_encoding_mblen的分析多字节字符的长度len(该长度即几个字节构成一个多字节字符),接着将sourcelen个字节直接拷贝target中。

从上面的关键点来看,多字节字符拷贝的时候没有添加任何其它字符,即不进行任何的转义。那就抛出来一个问题,能不能特殊构造一个多字节字符,该字符存在某个字节为单引号'(这样就有可能在后续引发单引号'闭合触发SQL注入)?

对于双字节字符来说,一个可能的情况是pg_encoding_mblen返回len为2,且对应从source中读取的第2个字节为单引号'。由于source任意字节可控(来自dbquote脚本中pg_escape_string的传入参数),所以前面条件暂可简化为要求pg_encoding_mblenlen2。

所以现在来看一下pg_encoding_mblen的底层实

编码问题引起的RCE分析

pg_encoding_mblen方法会从pg_wchar_tbl表中找到某字符编码对应的函数集合,并从中找到存储的mblen方法。 对与PG_UTF8字符编码来说,相当于要调用上述的pg_utf_mblen方法。在该方法中,如果某字符的第1个字节&0xe0的结果为0xc0,那么就认为该字符占用两个字节。所以,可以构造 0xC00x27 的字节序列,该序列视为双字节字符,其0xC0&0xE0等于0xC0,而且0x27为单引号。这种方式构造的多字节字符会直接从source被拷贝到target,且不会进行任何的转义。

有了上述分析后,直接进行如下三个测试进行验证。

无单引号测试

编码问题引起的RCE分析

结果可以看到未对hey进行任何转义,且首尾额外增加一个单引号。

有单引号测试:

编码问题引起的RCE分析

结果可以看到h'ey'中所有单引号前被额外增加了一个单引号进行转义,且首尾额外增加一个单引号。

特殊构造测试:

编码问题引起的RCE分析

结果可以看到hxC0'ey'xC0后的单引号未被转义,ey后的单引号被转义,且首尾额外增加一个单引号。该方式的结果初步看像是可以绕过单引号闭合,可能可以被后续用于SQL注入,也就是接下来的psql分析。

03

psql分析(CVE-2025-1094)

前文thin-scc-wrapper$(echo "SELECT COUNT(1) FROM gw_sessions WHERE session_key = $quoted AND session_type = 'sdcust' AND (expiration IS NULL OR expiration>NOW())" | $db这部分sql语句最终交由psql执行,其中$quoted可以通过特殊构造测试中的类似方法实现SQL注入。

psql一个PostgreSQL的客户端,其本身支持一些meta-commands and various shell-like features,如下是命令执行的官方文档说明:

编码问题引起的RCE分析

通过如下方式模拟实现SQL注入以及命令执行:

编码问题引起的RCE分析

前文中pg_escape_string转义配合这里的psql,构成了实际上的CVE-2025-1094漏洞。下面是Postgres官方的说明:

编码问题引起的RCE分析

可以看出来,CVE-2025-1094不仅包括PQescapeString,还涉及PQescapeLiteralPQescapeIdentifierPQescapeStringConn

04

触发流程

CVE-2024-12356通过WebSocket访问BeyondTrust认证前路由/nw,将HTTP中的Sec-WebSocket-Protocol子协议头设定为ingredi support desk customer thin(以及设定一些其它类似Host的必需参数),即可访问到thin-scc-wrapper脚本。

thin-scc-wrapper脚本中$gskey变量数据来自WebSocket数据流,用户可控。可通过特殊构造的Invalid UTF-8 0xC00x27绕过dbquote脚本中的pg_escape_string转义即CVE-2025-1094,并拼接到SQL语句中实现SQL注入【注入psql元命令! [ command ] 语句】。

包含SQL注入的字符串,被传递到psql解释,触发元命令! [ command ] 执行。

拓展分析

既然Postgres存在这个问题,那么其它的开源数据库是否有类似的问题呢?

01

Mysql分析

使用Mysql时,类似的转义方法有mysqli_real_escape_string(mysqli $mysql, string $string): string。mysqli_real_escape_string会调用mysql_real_escape_string_quote,而mysql_real_escape_string_quote等同于mysql_real_escape_string

编码问题引起的RCE分析

mysqlnd_libmysql_compat.hmysql_real_escape_string又等同于mysqlnd_real_escape_string

编码问题引起的RCE分析

mysqlnd.hmysqlnd_real_escape_string会调用连接对象的escape_string方法,该方法又调用mysqlnd_cset_escape_quotesmysqlnd_cset_escape_slashes

编码问题引起的RCE分析

上面的escape_string调用mysqlnd_cset_escape_quotes,这部分是多字节字符处理的核心逻辑:

编码问题引起的RCE分析

可以看到其逻辑类似PostgreSQL,如果cset->mb_valid(escapestr, end)调用只检查长度,不检查多字节字符是否Valid,那么应该也有类似Postgres的问题。但进一步查看源码(以UTF8为例),可以发现mb_valid对字节是否合法做了检查。

编码问题引起的RCE分析

可以看出来utf8字符集的mb_valid操作,会对多字节字符进行检查,要求其必须是Valid utf8 character。但前述代码都是在php-src分析,事实上,在mysql-src源码中,也存在mysql_real_escape_string ,这里简单看一下,逻辑和php-src中很类似,也会对多字节字符进行检查,要求其必须是Valid utf8 character

编码问题引起的RCE分析

除去一些无关代码后,上面my_ismbchar对于对于utf8来说,相当于调用my_mb_wc_utf8_prototype进行检测。

编码问题引起的RCE分析

上述过程在获取单个多字节字符的长度时,同时进行了“是否为一个有效UTF8字符”的检查。

因此,从前述源码来看,MysqlUTF8字符集方面应该不存在类似Postgres的问题。

02

Postgres修复

在最新的Postgres源码fe-exec.c中,对于PQescapeStringInternal方法,通过增加pg_encoding_verifymbchar函数调用来进行多字节字符的有效性检查。

编码问题引起的RCE分析

对于UTF8来说, pg_encoding_verifymbcha的检测会调用到pg_utf8_islegal,可以看到该函数会检测是否为一个有效UTF8字符。

编码问题引起的RCE分析
03

新的问题

CVE-2025-1094修复后,postgres对于UTF8的处理看着没什么问题,那么对于gbk的处理是否有问题?

事实上,postgres在服务端不支持gbk编码,但是客户端是支持gbk编码,在源码中有所体现。

编码问题引起的RCE分析

检查之前的pg_wchar_table表,查看gbk相关的长度处理pg_gbk_mblen和字符检查pg_gbk_verifychar

编码问题引起的RCE分析

简单从源码来看,似乎gbk的检查很宽松,是不是有可能存在之前的问题?直接盲测一下,让postgres-server使用UTF8编码,而客户端采用gbk编码。

服务端信息(修复后版本):

编码问题引起的RCE分析

创建dbq脚本(内部用户名/密码等信息用于连接postgre-server)。

编码问题引起的RCE分析

该脚本与前文dbquote逻辑基本一样,主要区别是这里增加了client_encoding='GBK'客户端编码。

执行quoted=$(echo -e "heyxC0'; ! id # " | ./dbq); echo "select $quoted" |  sudo -u postgres psql -e,其输出类似:

编码问题引起的RCE分析

从结果来看,出发了命令执行,也就是说xc0x27序列在client_encoding='GBK' server_encoding=UTF8下依旧可用。此外简单尝试了下,BIG5UHC做为客户端编码,现象也是如此。

这部分内容和PostgreSQL安全团队反馈后,对方回复认为这里的问题算是一种使用上的错误(a problem in how the escape functions are used, not a bug in how the escape functions work),而不是Bug(因为UTF8等编码本身的检测是没有问题的)。所以,这个现象目前在最新版上还是存在的。

结  语

本文分析了因编码问题引起的CVE-2024-12356CVE-2025-1094,解释了产生BeyondTrust命令注入的核心编码问题。基于该编码问题的思想,笔者对比分析了Mysql的代码以及补丁修复后的PostgreSQL代码,并进行了一定的拓展分析。Mysql暂未发现问题,但PostgreSQL在特定“使用错误”场景下,依旧会存在类似CVE-2025-1094的问题。

参考链接

1. CVE-2024-12356 | AttackerKB

【版权说明】
奇安信天工实验室

奇安信天工实验室,专注于漏洞攻防领域技术研究,面向互联网基础设施,以操作系统平台、基础软件应用、网络通信协议、关键网络设备为目标,研究漏洞挖掘、利用、检测等关键技术。漏洞研究成果连续在GeekPwn、天府杯等漏洞破解赛事中斩获奖项,漏洞挖掘方法发表于ACM CCS、Usenix、EuroS&P、BlackHat、HITB等国际重量级会议。

编码问题引起的RCE分析
每周三更新一篇技术文章  点击关注我们吧!

原文始发于微信公众号(奇安信天工实验室):编码问题引起的RCE分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月2日22:28:29
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   编码问题引起的RCE分析https://cn-sec.com/archives/3907354.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息