
Laboratorio Docker que reproduce CVE-2026-10795: omisión de autenticación de UpdraftPlus UpdraftCentral encadenada a la instalación de complementos para RCE. Incluye objetivos vulnerables/parcheados, exploit PoC y recorrido a nivel de código fuente.
Este repositorio contiene un laboratorio Docker local para reproducir y validar CVE-2026-10795, una vulnerabilidad de omisión de autenticación no autenticada que afecta al plugin UpdraftPlus de WordPress a través de su capa de comunicación remota UpdraftCentral.
El comportamiento vulnerable existe en el flujo de manejo de mensajes RPC de UpdraftCentral. En las versiones vulnerables, un mensaje RPC falsificado con format=1 puede omitir la verificación de firma, activar una ruta fallida de descifrado RSA y aun así llegar al descifrado simétrico con un comportamiento predecible de clave nula/IV nulo. Esto permite que un mensaje RPC cifrado y manipulado sea aceptado y despachado como un comando de UpdraftCentral.
Este laboratorio compara dos versiones de UpdraftPlus:
| Servicio | Versión de UpdraftPlus | Propósito | URL |
|---|---|---|---|
vuln | 1.26.4 | Objetivo de comparación vulnerable | http://127.0.0.1:8081 |
patched | 1.26.5 | Objetivo de comparación parcheado | http://127.0.0.1:8082 |
La cadena demostrada es:```text Unauthenticated attacker → forged UpdraftCentral RPC request → format=1 signature verification bypass → failed RSA decrypt not rejected in vulnerable version → predictable zero-key/zero-IV decrypt path → forged JSON RPC command accepted → privileged UpdraftCentral command dispatch → plugin.upload_plugin → install and activate marker plugin → hard-coded /usr/bin/id proof endpoint
La vulnerabilidad principal es la omisión de autenticación. El laboratorio demuestra que la omisión puede encadenarse a un impacto de tipo RCE cuando está presente un estado de clave UpdraftCentral privilegiado, porque UpdraftCentral expone comandos legítimos de gestión de plugins que pueden instalar y activar plugins de WordPress.
No se trata de una vulnerabilidad directa de inyección de comandos. La prueba de ejecución de código proviene de abusar de la funcionalidad autenticada de instalación de plugins tras omitir el límite de autenticación RPC.
Este laboratorio está diseñado únicamente para investigación local controlada, comprensión a nivel de código fuente y demostración en portafolio.
## Datos verificados
| Afirmación | Evidencia | Cómo verificarlo en este laboratorio |
| --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| UpdraftPlus 1.26.4 es vulnerable en este laboratorio. | El servicio vulnerable acepta un mensaje RPC falsificado con `format=1` y despacha `plugin.upload_plugin`. | Ejecuta `python3 poc/poc.py --url http://127.0.0.1:8081`. |
| UpdraftPlus 1.26.5 bloquea el mensaje falsificado en este laboratorio. | El servicio parcheado no devuelve un cuerpo de respuesta RPC y no despacha el comando falsificado. | Ejecuta `python3 poc/poc.py --url http://127.0.0.1:8082`. |
| El problema es una omisión de autenticación en la capa RPC de UpdraftCentral. | Una solicitud RPC falsificada sin autenticación puede llegar al despacho de comandos en la versión vulnerable. | Compara el comportamiento de `--ping` entre los puertos `8081` y `8082`. |
| El laboratorio no preinstala el plugin marcador. | La configuración solo instala WordPress, UpdraftPlus y un estado de clave UpdraftCentral local. | Comprueba `/wp-json/cve-lab/v1/id` antes de ejecutar el PoC. |
| El PoC instala el plugin marcador mediante RPC falsificado. | El PoC envía `plugin.upload_plugin` con una carga útil de plugin en ZIP en el campo de datos RPC. | Ejecuta el PoC y luego solicita `/wp-json/cve-lab/v1/id`. |
| El objetivo vulnerable alcanza un impacto de tipo RCE. | El plugin marcador expone un endpoint codificado que devuelve la salida de `/usr/bin/id`. | El objetivo vulnerable devuelve `uid=33(www-data) gid=33(www-data)`. |
| El objetivo parcheado no instala el plugin marcador. | El endpoint marcador devuelve `404 rest_no_route` en el servicio parcheado. | Ejecuta el PoC contra `http://127.0.0.1:8082`. |
| El laboratorio requiere un estado de clave UpdraftCentral. | El despacho de UpdraftCentral depende de una entrada de clave local y sus metadatos asociados. | Revisa `scripts/setup-wordpress.sh`. |
## Supuestos y desconocidos
Este laboratorio siembra intencionalmente un estado de clave UpdraftCentral local para reproducir una condición del sitio en la que se ha configurado el control remoto.
El estado de clave sembrado es un requisito previo del laboratorio, no la vulnerabilidad en sí. Permite que el laboratorio ejercite de forma consistente la ruta vulnerable de análisis y descifrado RPC.
El laboratorio no afirma que toda instalación de UpdraftPlus sea explotable de inmediato. La cadena demostrada depende de la presencia de una entrada de clave local de UpdraftCentral asociada a un usuario privilegiado de WordPress.
El laboratorio demuestra un impacto controlado de tipo RCE instalando un plugin marcador que expone un endpoint de prueba codificado con `/usr/bin/id`. No proporciona una shell web genérica, un parámetro arbitrario de ejecución de comandos, una reverse shell, un mecanismo de persistencia, robo de credenciales ni devoluciones de llamada externas.
El PoC está limitado a objetivos locales únicamente y rechaza nombres de host no locales por defecto.
## Resumen de la causa raíz
La causa raíz es una validación incorrecta de los mensajes RPC de UpdraftCentral en versiones vulnerables de UpdraftPlus.
El flujo RPC vulnerable acepta un mensaje con `format=1`. La ruta de `format=1` no requiere la misma verificación de firma que los formatos de mensaje más recientes.
El problema de alto nivel es:```text
format=1 message
→ signature verification is bypassed
→ RSA decrypt of the symmetric key can fail
→ failed decrypt result is not rejected
→ false is passed into the symmetric cipher as a key
→ phpseclib normalizes this into a predictable null key path
→ attacker-controlled encrypted JSON can decrypt successfully
→ command is dispatched
En el comportamiento vulnerable, el descifrado RSA puede devolver:```text false
En lugar de rechazar ese resultado de descifrado fallido, el flujo vulnerable continúa y pasa el valor a la capa de descifrado simétrico.
El patrón vulnerable efectivo es:```php
$sym_key = $rsa->decrypt($sym_key);
$rij->setKey($sym_key);
$decrypted = $rij->decrypt($ciphertext);
The problem is that $sym_key is not validated before it is used.
When $sym_key is false, the cipher setup follows a predictable null key/null IV behavior. This makes it possible to craft an encrypted RPC payload using a known zero key and zero IV.
The patched version adds a guard before the symmetric key is used:```php if (false === $sym_key || !is_string($sym_key) || strlen($sym_key) < 16) { return false; }
Esto cambia el límite de confianza.
Antes del parche:```text
failed RSA decrypt result could still reach symmetric decrypt
Después del parche:```text failed RSA decrypt result is rejected before command dispatch
This is why the vulnerable service dispatches the forged RPC command, while the patched service does not.
## Why an Authentication Bypass Can Lead to Code Execution