pgAdmin 4在为修复Issue 9320而引入的PLAIN恢复元命令过滤器中,存在一个安全缺陷。该过滤器无法识别以UTF-8字节顺序标记(BOM,即EF BB BF)或其他特殊字节序列开头的SQL文件。过滤器内部的has_meta_commands()函数使用正则表达式扫描文件的原始字节,但正则表达式未将BOM等特殊字节视为可忽略的前导字符。这导致诸如 \! 之类的危险元命令无法被有效检测。
当pgAdmin使用 --file 参数调用psql来恢复此类文件时,psql会去除文件开头的BOM字节,从而正常解析并执行文件中包含的元命令。攻击者可利用此绕过机制,在数据库恢复操作期间执行任意远程命令,构成严重的网络安全风险。

受影响版本
- 已确认受影响:pgAdmin 9.10 快照(提交 63ee8120...)。
- 可能受影响:任何包含提交
1d397395... 中补丁的版本,具体取决于 has_meta_commands() 函数的实现。
- 版本状态说明:
- 9.11及以上版本:普通恢复操作已在psql的受限模式(
\restrict)下运行,元命令会被psql自身阻止,因此不受此漏洞影响。
- 9.10版本:易受此过滤器绕过攻击。
技术细节
漏洞核心位于以下文件及函数中:
- 文件路径:
web/pgadmin/tools/restore/__init__.py
- 相关函数:
has_meta_commands()
以下是从已修复版本中提取的相关函数代码,展示了其检测逻辑:
def has_meta_commands(path, chunk_size=8 * 1024 * 1024):
pattern = re.compile(br'(^|\n)[ \t]*\\')
with open(path, "rb") as f:
prev_tail = b""
while chunk := f.read(chunk_size):
data = prev_tail + chunk
if pattern.search(data):
return True
prev_tail = data[-10:]
return False
漏洞成因分析
- SQL文件以二进制模式(
"rb")打开进行扫描。
- 正则表达式
br'(^|\n)[ \t]*\\' 仅将反斜杠(\)前的空格和制表符视为可忽略字符。
- 如果在反斜杠前放置UTF-8 BOM(
EF BB BF)或类似的特殊字节序列,该正则表达式将无法匹配到元命令。
- 因此,pgAdmin会错误地判定该SQL文件不包含任何元命令,允许其进入恢复流程。
- 在调用
psql执行时,psql会剥离文件开头的BOM,从而正常识别并执行元命令,导致安全过滤逻辑被绕过。
概念验证(PoC)
以下示例展示了可绕过过滤的有效载荷与正常被拦截的载荷对比。
利用BOM绕过的有效载荷:
\xef\xbb\xbf\!echo HACKED_FROM_BOM > /tmp/bom_ran
SELECT 1;
理应被拦截的控制载荷(无BOM):
\!echo SHOULD_BE_BLOCKED
SELECT 1;
此漏洞的修复涉及更新has_meta_commands()函数的过滤逻辑,使其能够识别并正确处理文件开头的各种字节顺序标记及不可见字符,确保安全检测的完整性。
|