
PoC en Python para CVE-2026-92805: el XHR del asistente de instalación no autenticado de UVdesk permite la reescritura de DATABASE_URL y la creación de ROLE_SUPER_ADMIN mediante los modos fingerprint y admin.
POC de superadministrador mediante el asistente no autenticado de UVdesk
UVdesk Community Skeleton hasta la versión 1.1.8 — el XHR del asistente de instalación (ConfigureHelpdesk) no tiene autenticación ni comprobación del estado de instalación. Un atacante no autenticado puede reescribir DATABASE_URL y crear un ROLE_SUPER_ADMIN. No existe una etiqueta pública con el parche (v1.1.9 devuelve 404).
Solo para pruebas autorizadas. No ejecutes esto contra sistemas que no sean de tu propiedad o para los que no tengas permiso de prueba.
Requiere: Python 3, solo biblioteca estándar.
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 | Qué hace |
|---|---|
-u / --url | URL base del helpdesk (obligatorio). http:// o https://. Un nombre de host sin esquema se prueba primero como HTTPS y luego como HTTP. Las redirecciones http→https conservan el POST. Los certificados TLS incorrectos se reintentan sin verificación; --insecure omite la verificación desde el principio |
--test | Solo fingerprinting: POST /wizard/xhr/check-requirements (specification=php-version). Sin escritura de .env, sin usuario |
--admin | Cadena completa del asistente: almacena la BD + superusuario en la sesión PHP, escribe DATABASE_URL, migra, crea ROLE_SUPER_ADMIN |
--email / --password / --name | Superadministrador a crear (por defecto [email protected] / PwnedAdmin1! / Pwned Admin) |
--db-host / --db-port / --db-user / --db-pass / --db-name | MySQL tal como lo ve la aplicación PHP (por defecto 127.0.0.1:3306 / uvdesk / uvdesk / uvdesk) |
--create-db | Pide al asistente que ejecute CREATE DATABASE si falta el esquema |
--insecure | Omite la verificación TLS |
--timeout | Segundos de timeout HTTP (por defecto 120; las migraciones pueden ser lentas) |
Endpoint de --test: POST /wizard/xhr/check-requirements. Un JSON 200 con "version" / "status" es PRESENT / VULNERABLE. Nunca accede a load/configurations ni a load/super-user. Tras una instalación finalizada, GET / redirige fuera del HTML del asistente; las rutas XHR siguen respondiendo. Ese es el fallo.
--admin no está autenticado. El asistente cree que es el instalador de primera ejecución. --db-* no es un cliente MySQL en tu máquina; se envían a la aplicación para que PHP pueda conectarse (el caso habitual es 127.0.0.1 en el mismo host).
No tienes que descubrir un nombre de esquema existente. --db-name es un nombre que tú eliges (por defecto uvdesk). --create-db establece el flag createDatabase del asistente para que PHP ejecute CREATE DATABASE si ese nombre no existe. Sin --create-db, un nombre inexistente da NEED_DB ("The requested database was not found"). Crear un nombre nuevo requiere un usuario MySQL con CREATE (un uvdesk@localhost restringido que solo tiene permisos sobre uvdesk.* puede reutilizar uvdesk, pero puede que no pueda crear uvdesk_pwn). --test nunca se comunica con MySQL.
Si ya existe un superadministrador en ese esquema, load/super-user no hace nada — --create-db junto con un --db-name nuevo levanta un esquema propio y apunta DATABASE_URL a él.
Salida estándar: UVDESK, WIZARD_PAGE, PHP, STATUS, PRESENT, VULNERABLE, NOT_VULNERABLE, NOT_FOUND, NEED_DB, ADMIN, LOGIN.

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