Wander
Wander is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
Wander attack path
Wander is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Objective
Challenge walkthrough focused on Hardware evidence, validation, and reusable operator lessons.
Walkthrough flow
Identify the web-exposed PJL command form at /jobs.
Validate PJL forwarding with harmless INFO commands.
Enumerate the normal printer filesystem with .
Use PJL filesystem path traversal from 0:/../../ to...
List 0:/../../home/default and find readyjob.
Source coverage
High source coverage
Status: complete. This article is generated from 6 sanitized Markdown sources and keeps raw flags, credentials, keys, cookies, and reusable secrets out of the rendered blog.
High confidence: the page is reconstructed from a primary walkthrough plus multiple supporting notes or evidence sources. Treat the chain as source-backed, while still checking the listed source files for sensitive values.
- Hardware/Wander/writeup.md
- htb-challenge/Hardware/Wander/notes.md
- htb-challenge/Hardware/Wander/memory-summary.md
- htb-challenge/Hardware/Wander/hypothesis-board.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Hardware__Wander__memory-summary.md.0d44ee46b8.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Hardware__Wander__notes.md.d675ae1359.md
Technical Walkthrough
Writeup
Challenge
- Name: Wander
- Category: Hardware
- Difficulty: Easy
- Mode: remote
Summary
The web app exposed a PJL command form at /jobs and proxied those commands to a simulated printer. Standard INFO commands confirmed the PJL interface, but the useful issue was filesystem traversal through PJL file commands. Listing 0:/../../ escaped the printer web content root and exposed /home/default/readyjob; uploading that file revealed the print job metadata containing the challenge flag.
Artifact Inventory
Reference analysis/artifact-inventory.json and summarize the relevant files or remote surface.
- Remote-only challenge; no ZIP or firmware artifact was provided.
analysis/http-jobs-initial.txtrecords the/jobsform withname="pjl".analysis/pjl-targeted-probe.txtrecords liveINFOand root filesystem behavior.analysis/pjl-fs-recursive.txtrecords the normal exposed printer filesystem.analysis/pjl-path-traversal-readyjob.txtrecords the validated traversal path, with the raw flag redacted.
Analysis
/jobsexposes a POST form to/printerwith a PJL command field.@PJL INFO IDreturnedHTB Printer, proving the form forwards PJL to the backend.@PJL <secret redacted> NAME="0:" ENTRY=1 COUNT=50listed printer directories such asPJL,PostScript,saveDevice, andwebServer.- Normal recursive listing only exposed firmware-like web content and empty key/security files.
- The path
0:/../../escaped that root and listed host-like directories includinghome. 0:/../../home/defaultcontainedreadyjob, a 457-byte file.@PJL FSUPLOAD NAME="0:/../../home/default/readyjob" OFFSET=0 SIZE=1000returned the print job, including a PJL flag comment and a hold key.
Solve
Run:
python3 Hardware/Wander/solve/solve.py --base-url http://<TARGET>:30391The solver sends one FSUPLOAD command for 0:/../../home/default/readyjob, extracts the FLAG = "..." comment, and prints the flag for harness capture.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- PJL filesystem commands can expose a printer's virtual filesystem and, in this challenge, allowed traversal outside the normal printer web root.
- External writeups or research should be treated as hints only; the decisive evidence here was the current-instance transcript in
analysis/pjl-path-traversal-readyjob.txt. - Avoid stripping HTML blindly from
FSUPLOADresults, because uploaded files may legitimately contain HTML-like content.
Source-Backed Dossier
The sections below are merged from companion Markdown notes for the same case. They are rendered after sanitization so the article stays precise without publishing raw flags, credentials, or target-specific secrets.
Notes
Scope
- Challenge: Wander
- Category: Hardware
- Difficulty: Easy
- Mode: remote
- Remote instance: none
- Start time: 2026-06-10T10:01:41Z
- Operator: harness
- State file:
challenge-state.json
Harness Status
- Current phase: see
challenge-state.json - Next allowed actions: see
next-action.json - Raw flags and sensitive material stay in
loot/only. Do not paste them here.
Artifact Inventory
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
| — | 0 | — | remote-only or no provided files | No local artifacts found under files/ |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-10T10:01:41Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-10T10:01:41Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-10T10:02:44Z | hypothesis recorded | hypothesis-board.md | Use the web-exposed PJL interface to enumerate printer identity, variables, configuration, and filesystem content until the PIN/flag is disclosed. | Medium | POST harmless PJL INFO commands first, then enumerate only response-backed PJL filesystem or variable surfaces. |
| 2026-06-10T10:02:44Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-10T10:02:45Z | checkpoint recorded | analysis/checkpoint-hypothesis_ready-20260610T100245020450Z-177d1749.md | Checkpoint for <secret redacted> | High | Use checkpoint to drive next decision |
| 2026-06-10T10:02:45Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-10T10:02:45Z | evaluator | analysis/evaluator-20260610T100245121028Z-558b8d78.md | Proceed | High | POST PJL INFO commands, record responses, and derive the next bounded PJL command set. |
| 2026-06-10T10:10:45Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-10T10:11:54Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-10T10:12:45Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-10T10:12:47Z | checkpoint recorded | analysis/checkpoint-analysis-20260610T101247930992Z-43f67866.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-10T10:13:59Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
/jobsexposes a PJL command form that posts to/printer.@PJL INFO IDreturnsHTB Printer, confirming live PJL forwarding.- Normal PJL filesystem enumeration exposes
PJL,PostScript,saveDevice, andwebServer. - PJL path traversal using
0:/../../escapes the normal printer content root. 0:/../../home/default/readyjobis readable viaFSUPLOADand contains the challenge flag marker.- Repro solver:
solve/solve.py. - Raw flag is stored only in
loot/flag.txt.
RAG / Advisory Memory
RAG output is advisory only. Record evaluated retrievals with:
scripts/challenge_harness.py rag-record <workspace> --query "..." --tag MATCHED|PARTIAL|MISSING|<secret redacted>|GENERIC --validation "..."Secrets/Flags
Raw flags and sensitive material stay in loot/ only. Use scripts/challenge_harness.py capture-flag to validate and record flag capture without printing the value.
Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category: Hardware
- Challenge: Wander
- Difficulty: Easy
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
- Identify the web-exposed PJL command form at
/jobs. - Validate PJL forwarding with harmless
INFOcommands. - Enumerate the normal printer filesystem with
<secret redacted>. - Use PJL filesystem path traversal from
0:/../../to escape the printer content root. - List
0:/../../home/defaultand findreadyjob. - Read
readyjobwithFSUPLOAD; the print job metadata contains the flag marker and a printer hold key.
Reusable Lessons
- For printer/PJL challenges, test
INFO IDandINFO STATUSfirst to prove transport, then move to<secret redacted>,FSQUERY, andFSUPLOAD. - Path traversal may work inside PJL filesystem names even when normal HTTP routes are not useful.
- Preserve raw
FSUPLOADcontent carefully; generic HTML stripping can hide useful file contents. - Treat public challenge research as advisory and require live validation before accepting it.
Dead Ends
- Direct HTTP paths such as
/pin,/unlock,/flag, and ChaiServer dispatcher routes returned 404. - Broad
INFO <secret redacted>,INFO CONFIG, and directINQUIRE PIN/PASSWORDstyle commands did not disclose useful state. - Normal webServer files exposed firmware-like content but no flag until traversal into
/home/default/readyjob.
Tool Quirks
- The web app embeds PJL responses inside the HTML page under the printer form.
0:/pathworks as a PJL filesystem syntax;0:pathand0:\pathfailed in this instance.FSUPLOADoutput can include HTML or PJL control markers, so extraction should slice from@PJL FSUPLOADand stop at the page wrapper.
Evidence Paths
analysis/http-jobs-initial.txtanalysis/pjl-targeted-probe.txtanalysis/pjl-fs-recursive.txtanalysis/pjl-path-traversal-readyjob.txtsolve/solve.pyloot/flag.txt
Ingestion Decision
- Proposed for LightRAG: yes
- Requires user approval before ingestion: yes
Hypothesis Board
Keep no more than 3 active hypotheses on Easy/Medium and 5 on Hard unless the user explicitly asks for breadth.
| Rank | Path | Evidence | Missing Proof | Cheapest Validation | Confidence | Status |
|---|---|---|---|---|---|---|
| 1 | Use the web-exposed PJL interface to enumerate printer identity, variables, configuration, and filesystem content until the PIN/flag is disclosed. | /jobs contains a form posting pjl to /printer with placeholder @PJL INFO ID. | POST harmless PJL INFO commands first, then enumerate only response-backed PJL filesystem or variable surfaces. | Medium | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit Condition |
|---|
Memory Summary
approval_required: true
Sanitized Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category: Hardware
- Challenge: Wander
- Difficulty: Easy
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
- Identify the web-exposed PJL command form at
/jobs. - Validate PJL forwarding with harmless
INFOcommands. - Enumerate the normal printer filesystem with
<secret redacted>. - Use PJL filesystem path traversal from
0:/../../to escape the printer content root. - List
0:/../../home/defaultand findreadyjob. - Read
readyjobwithFSUPLOAD; the print job metadata contains the flag marker and a printer hold key.
Reusable Lessons
- For printer/PJL challenges, test
INFO IDandINFO STATUSfirst to prove transport, then move to<secret redacted>,FSQUERY, andFSUPLOAD. - Path traversal may work inside PJL filesystem names even when normal HTTP routes are not useful.
- Preserve raw
FSUPLOADcontent carefully; generic HTML stripping can hide useful file contents. - Treat public challenge research as advisory and require live validation before accepting it.
Dead Ends
- Direct HTTP paths such as
/pin,/unlock,/flag, and ChaiServer dispatcher routes returned 404. - Broad
INFO <secret redacted>,INFO CONFIG, and directINQUIRE PIN/PASSWORDstyle commands did not disclose useful state. - Normal webServer files exposed firmware-like content but no flag until traversal into
/home/default/readyjob.
Tool Quirks
- The web app embeds PJL responses inside the HTML page under the printer form.
0:/pathworks as a PJL filesystem syntax;0:pathand0:\pathfailed in this instance.FSUPLOADoutput can include HTML or PJL control markers, so extraction should slice from@PJL FSUPLOADand stop at the page wrapper.
Evidence Paths
analysis/http-jobs-initial.txtanalysis/pjl-targeted-probe.txtanalysis/pjl-fs-recursive.txtanalysis/pjl-path-traversal-readyjob.txtsolve/solve.pyloot/flag.txt
Ingestion Decision
- Proposed for LightRAG: yes
- Requires user approval before ingestion: yes
Notes
Notes
Scope
- Challenge: Wander
- Category: Hardware
- Difficulty: Easy
- Mode: remote
- Remote instance: none
- Start time: 2026-06-10T10:01:41Z
- Operator: harness
- State file:
challenge-state.json
Harness Status
- Current phase: see
challenge-state.json - Next allowed actions: see
next-action.json - Raw flags and sensitive material stay in
loot/only. Do not paste them here.
Artifact Inventory
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
| — | 0 | — | remote-only or no provided files | No local artifacts found under files/ |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-10T10:01:41Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-10T10:01:41Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-10T10: <REDACTED>, variables, configuration, and filesystem content until the PIN/flag is disclosed. | Medium | POST harmless PJL INFO commands first, then enumerate only response-backed PJL filesystem or variable surfaces. | |||
| 2026-06-10T10:02:44Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-10T10:02:45Z | checkpoint recorded | analysis/checkpoint-hypothesis_ready-20260610T100245020450Z-177d1749.md | Checkpoint for <secret redacted> | High | Use checkpoint to drive next decision |
| 2026-06-10T10:02:45Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-10T10:02:45Z | evaluator | analysis/evaluator-20260610T100245121028Z-558b8d78.md | Proceed | High | POST PJL INFO commands, record responses, and derive the next bounded PJL command set. |
| 2026-06-10T10: <REDACTED> | |||||
| 2026-06-10T10: <REDACTED> | |||||
| 2026-06-10T10:12:45Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-10T10:12:47Z | checkpoint recorded | analysis/checkpoint-analysis-20260610T101247930992Z-43f67866.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-10T10:13:59Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
/jobsexposes a PJL command form that posts to/printer.@PJL INFO IDreturnsHTB Printer, confirming live PJL forwarding.- Normal PJL filesystem enumeration exposes
PJL,PostScript,saveDevice, andwebServer. - PJL path traversal using
0:/../../escapes the normal printer content root. - `0: <REDACTED>
- Repro solver:
solve/solve.py. - Raw flag is stored only in
loot/flag.txt.
RAG / Advisory Memory
RAG output is advisory only. Record evaluated retrievals with:
scripts/challenge_harness.py rag-record <workspace> --query "..." --tag MATCHED|PARTIAL|MISSING|<secret redacted>|GENERIC --validation "..."Secrets/Flags
Raw flags and sensitive material stay in loot/ only. Use scripts/challenge_harness.py capture-flag to validate and record flag capture without printing the value.
Technical analogy
How to remember this solve
Think of the hardware challenge like following copper tracks on a circuit board. The useful clue is usually where signals enter, where they are transformed, and which debug or storage path exposes hidden state.
For Wander, keep the mental model simple: identify the trusted assumption, prove it with the smallest safe test, then automate or repeat only the part that directly leads to the flag.