
Docker lab reproducing CVE-2026-10795: UpdraftPlus UpdraftCentral authentication bypass chained to plugin installation for RCE. Includes vulnerable/patched targets, PoC exploit, and source-level walkthrough.
This repository contains a local Docker lab for reproducing and validating CVE-2026-10795, an unauthenticated authentication bypass vulnerability affecting the UpdraftPlus WordPress plugin through its UpdraftCentral remote communication layer.
The vulnerable behavior exists in the UpdraftCentral RPC message handling flow. In vulnerable versions, a forged format=1 RPC message can bypass signature verification, trigger a failed RSA decrypt path, and still reach symmetric decryption with a predictable null key/null IV behavior. This allows a crafted encrypted RPC message to be accepted and dispatched as an UpdraftCentral command.
This lab compares two UpdraftPlus versions:
| Service | UpdraftPlus version | Purpose | URL |
|---|---|---|---|
vuln | 1.26.4 | Vulnerable comparison target | http://127.0.0.1:8081 |
patched | 1.26.5 | Patched comparison target | http://127.0.0.1:8082 |
The demonstrated chain is:
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
The primary vulnerability is authentication bypass. The lab demonstrates that the bypass can be chained to an RCE-style impact when a privileged UpdraftCentral key state is present, because UpdraftCentral exposes legitimate plugin management commands that can install and activate WordPress plugins.
This is not a direct command injection vulnerability. The code execution proof comes from abusing authenticated plugin installation functionality after bypassing the RPC authentication boundary.
This lab is designed for controlled local research, source-level understanding, and portfolio demonstration only.
| Claim | Evidence | How to verify in this lab |
|---|---|---|
| UpdraftPlus 1.26.4 is vulnerable in this lab. | The vulnerable service accepts a forged format=1 RPC message and dispatches plugin.upload_plugin. | Run python3 poc/poc.py --url http://127.0.0.1:8081. |
| UpdraftPlus 1.26.5 blocks the forged message in this lab. | The patched service returns no RPC response body and does not dispatch the forged command. | Run python3 poc/poc.py --url http://127.0.0.1:8082. |
| The issue is an authentication bypass in the UpdraftCentral RPC layer. | A forged unauthenticated RPC request can reach command dispatch in the vulnerable version. | Compare --ping behavior between ports 8081 and 8082. |
| The lab does not pre-install the marker plugin. | The setup only installs WordPress, UpdraftPlus, and a local UpdraftCentral key state. | Check /wp-json/cve-lab/v1/id before running the PoC. |
| The PoC installs the marker plugin through forged RPC. | The PoC sends plugin.upload_plugin with a ZIP plugin payload in the RPC data field. | Run the PoC and then request /wp-json/cve-lab/v1/id. |
| The vulnerable target reaches RCE-style impact. | The marker plugin exposes a hard-coded endpoint that returns /usr/bin/id output. | The vulnerable target returns uid=33(www-data) gid=33(www-data). |
| The patched target does not install the marker plugin. | The marker endpoint returns 404 rest_no_route on the patched service. | Run the PoC against http://127.0.0.1:8082. |
| The lab requires an UpdraftCentral key state. | UpdraftCentral dispatch depends on a local key entry and associated metadata. | Review scripts/setup-wordpress.sh. |
This lab intentionally seeds a local UpdraftCentral key state to reproduce a site condition where remote control has been configured.
The seeded key state is a lab prerequisite, not the vulnerability itself. It allows the lab to consistently exercise the vulnerable RPC parsing and decryption path.
The lab does not claim that every UpdraftPlus installation is immediately exploitable. The demonstrated chain depends on the presence of an UpdraftCentral local key entry that is associated with a privileged WordPress user.
The lab demonstrates a controlled RCE-style impact by installing a marker plugin that exposes a hard-coded /usr/bin/id proof endpoint. It does not provide a generic web shell, arbitrary command execution parameter, reverse shell, persistence mechanism, credential theft, or external callback.
The PoC is scoped to local targets only and refuses non-local hostnames by default.
The root cause is improper validation of UpdraftCentral RPC messages in vulnerable versions of UpdraftPlus.
The vulnerable RPC flow accepts a format=1 message. The format=1 path does not require the same signature verification as newer message formats.
The high-level issue is:
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
In vulnerable behavior, RSA decryption can return:
false
Instead of rejecting that failed decrypt result, the vulnerable flow continues and passes the value into the symmetric decryption layer.
The effective vulnerable pattern is:
$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:
if (false === $sym_key || !is_string($sym_key) || strlen($sym_key) < 16) {
return false;
}
This changes the trust boundary.
Before the patch:
failed RSA decrypt result could still reach symmetric decrypt
After the patch:
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.
CVE-2026-10795 is best described as an authentication bypass because the root flaw is in the RPC authentication and message verification layer.
However, after that authentication boundary is bypassed, the attacker-controlled RPC message can reach privileged UpdraftCentral commands.
One important command path is:
plugin.upload_plugin