Overview

The machine starts by enumerating wordpress on port 80 to discover the outdated modular-connector plugin that allows auth bypass via CVE-2026-23550 to log in as streetcoderadmin, uploading a malicious plugin to get remote code execution and shell as www-data to find the user flag. Checking group membership reveals docker privileges that allow mounting the host filesystem with chroot to get shell as root.


Enumeration

We start with nmap scan as usual

Only two ports are open:

  • port 22 for SSH
  • port 80 hosting WordPress

Port 80

Just a static page, nothing else is there.

Nmap scan earlier confirmed it is WordPress, and we can access wp-admin as you can see

I start by looking for usernames, and you can see there is one user called streetcoderadmin

Tried to brute force the user's password but we got nothing, so another way in is outdated vulnerable plugins, but the /plugins returned 200 OK with empty response, but it doesn't mean there isn't any plugins; we were just asking nicely.

We can brute force the plugins using already known plugins names.

And as you can see, this returned 2 plugins: one is akismet that wpscan can't get its version, but there is this modular connector AKA Modular DS with the version 2.5.0

WordPress Auth Bypass

Quick search about that version, it is vulnerable to auth bypass CVE-2026-23550.

How does that happen? The plugin exposes /api/modular-connector/login/... for its parent-site management service, which is fine, but the route matching was too loose: adding ?origin=mo (+ any type=) flips it into "direct request" mode, where auth only checks that the site has an active Modular connection, not that the caller is authorized. Login route then logs in as the site admin by default when no user ID is specified.

So visiting http://10.1.76.247/api/modular-connector/login/poc?origin=mo&type=foo redirected us to the admin page logged in as streetcoderadmin.

We go directly for the easy RCE via the themes manipulation, but it is sanitized and we can't change PHP, only HTML.

Shell as www-data

One other way to get RCE via WordPress is by using plugins; we can install a malicious plugin that gets executed on every page visit, executing whatever code we set it to.

So I used the plugin from xanhack and just modified the system command for direct reverse shell instead of webshell.

Then we zip the plugin.

bash
┌─[]─[10.200.85.72]─[jimmex@attacker]─[~/HSM/Dark/wordpress-rce-plugin]
└──╼ [★]$ zip plugins.zip *
  adding: index.php (deflated 54%)
  adding: README.md (deflated 44%)

Now we go to the plugins section and upload the plugin, then we click Install Now.

After installing it, we have to activate the plugin so it would get executed when any page is visited.

Then we start our listener and visit any page on the site, and we'll get a shell as www-data.

The user flag is under the www-data home directory, which is /var/www.

bash
www-data@dark:/var/www/172_16_1_84_/public$ cd ~
www-data@dark:/var/www$ cat user.txt 
flag{w0redPress-2026-23550}
www-data@dark:/var/www$

Privilege Escalation

Looking for the groups we're in as www-data, we are members of the docker group. This means we can pull some image, creating a container and mounting the host's root inside the container, and because containers spawn as root by default with UID 0, and the kernel just compares the UID and lets us in to the root desktop.

bash
www-data@dark:/var/www/172_16_1_84_/public$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data),121(docker)
www-data@dark:/var/www/172_16_1_84_/public$

So we create a container using the alpine image (this is pulled from Docker Hub) and we get a shell as root inside it, where we can read the host's root system.

yaml
www-data@dark:/var/www$ docker run -v /:/mnt --rm -it alpine chroot /mnt /bin/bash
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
55afa1ecc21d: Pull complete 
Digest: sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b
Status: Downloaded newer image for alpine:latest
groups: cannot find name for group ID 11
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

root@37c62ac8d6cf:/# whoai
Command 'whoai' not found, did you mean:
  command 'whoami' from deb coreutils (8.32-4.1ubuntu1.3)
Try: sudo apt install <deb name>
root@37c62ac8d6cf:/# cat /root/root.txt
flag{docker-is-fun-0385}
root@37c62ac8d6cf:/# 

If we're looking for a full shell as root on the host system, we can drop an SSH key on the mount, and because it is a bind mount, the container and the host system both share the same underlying storage, and whatever was written on the container gets reflected.

Path

here is what we did Pasted image 20260825100232.png

Resources