Challenge / Coding

Pivot Easy

Pivot Easy is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator

EasyPublished 2024-03-10Sanitized local writeup

Scenario

Pivot Easy attack path

Pivot Easy 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 Coding evidence, validation, and reusable operator lessons.

Pivot Easy sanitized attack graph

Walkthrough flow

01

Fingerprinted the remote as the standard HTB Coding...

02

Captured the prompt from the root page and identified...

03

Chose Dijkstra because edge weights are non-uniform...

04

Implemented host-name-to-ID mapping, adjacency lists,...

05

Submitted the Python solution through /run.

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.

100% coverage
Evidence verdict

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.

  • Coding/Pivot-Easy/writeup.md
  • htb-challenge/Coding/Pivot-Easy/notes.md
  • htb-challenge/Coding/Pivot-Easy/memory-summary.md
  • htb-challenge/Coding/Pivot-Easy/hypothesis-board.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Coding__Pivot-Easy__memory-summary.md.fcd9210e11.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Coding__Pivot-Easy__notes.md.a7330e1a22.md

Technical Walkthrough

Writeup

Challenge

  • Name: Pivot-Easy
  • Category: Coding
  • Difficulty: Easy
  • Mode: remote

Summary

Pivot Easy is a remote HTB Coding runner. The prompt describes a directed weighted graph of hosts and pivot risks, then asks for the minimum cumulative detection risk from a compromised host to the Core Administration Server. The correct solution is Dijkstra's shortest-path algorithm with a host-name-to-ID map and a heap.

Artifact Inventory

Reference analysis/artifact-inventory.json and summarize the relevant files or remote surface.

  • analysis/remote/root-http.txt: captured the full challenge prompt and frontend runner.
  • analysis/remote/prompts.js: captured the default language templates.
  • analysis/remote/initial-nc-probe.txt: confirmed the port accepts TCP but the useful interface is HTTP.
  • solve/solution.py: submitted algorithm implementation.
  • solve/solve.py: reproducible submitter for /run.
  • analysis/remote/run-response.json: saved runner response from the successful submission.

Analysis

The prompt states that each pivot path is unidirectional and has a detection risk. The required output is a single integer: the minimum cumulative risk from the starting host to the target host. Since edge weights are non-uniform and the constraints are large (N up to 150000 and M up to 1000000), BFS and adjacency matrices are inappropriate.

The implementation maps each host name to an integer ID as it is encountered, stores outgoing edges in adjacency lists, and runs Dijkstra with heapq. The algorithm exits as soon as the target is popped from the heap, which avoids unnecessary work on large hidden cases.

Solve

The submitted code is in solve/solution.py. It supports both likely first-line formats:

  • N M start target
  • N M followed by a second line containing start target

The submitter in solve/solve.py posts the solution to /run as Python, saves the raw JSON response to analysis/remote/run-response.json, and writes any returned flag candidate to loot/flag-candidate.txt. The harness then validates and stores the flag in loot/flag.txt.

Flag

Raw flag is stored in loot/flag.txt and intentionally not reproduced here.

Lessons

  • For weighted graph routing problems, confirm whether edges are directed before choosing the algorithm.
  • Large constraints rule out adjacency matrices and all-pairs algorithms.
  • Treat host labels as opaque strings; map them to integer IDs for performance.
  • Save the /run response so failed hidden tests can be debugged without rerunning blindly.

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: Pivot-Easy
  • Category: Coding
  • Difficulty: Easy
  • Mode: remote
  • Remote instance: <TARGET>:30290
  • Start time: 2026-06-07T23:43:27Z
  • 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

FileSizeSHA256TypeNotes
0remote-only or no provided filesNo local artifacts found under files/

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-07T23:43:27Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-07T23:43:38Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T23:43:38Zhypothesis recordedhypothesis-board.mdRemote Coding service likely exposes an HTTP runner or challenge API; identify protocol and problem format before submitting code.MediumProbe HTTP root and raw TCP banner, then inspect page JavaScript/API endpoints if HTTP is present.
2026-06-07T23:43:54Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-07T23:43:54Zcheckpoint recordedanalysis/checkpoint-triage-20260607T234354500083Z-2c1efa2a.mdCheckpoint for TRIAGEHighUse checkpoint to drive next decision
2026-06-07T23:45:02Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T23:45:02Zhypothesis recordedhypothesis-board.mdSubmit heap-based Dijkstra solution for directed weighted graph with host-name mapping.MediumRun solution against sample, then submit through /run and capture flag if all tests pass.
2026-06-07T23:45:12Zevaluatoranalysis/evaluator-20260607T234512105821Z-4b01b905.mdProceedHighRun solve/solve.py, capture flag through harness, then complete if successful.
2026-06-07T23:45:53Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-07T23:46:33Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • Remote service is the standard HTB Coding HTTP runner.
  • Useful endpoint is POST /run, as shown in analysis/remote/root-http.txt.
  • The challenge is a directed weighted shortest-path problem over host names.
  • Constraints require an efficient single-source shortest-path algorithm.
  • solve/solution.py uses Dijkstra with a heap, adjacency lists, and host-name ID mapping.
  • The solver supports both N M start target and N M plus a second start target line.
  • solve/solve.py submitted the code and stored the successful response in analysis/remote/run-response.json.
  • The harness captured the validated flag into loot/flag.txt.

RAG / Advisory Memory

RAG output is advisory only. Record evaluated retrievals with:

bash
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: Coding
  • Challenge: Pivot-Easy
  • 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.

  1. Fingerprinted the remote as the standard HTB Coding HTTP runner.
  2. Captured the prompt from the root page and identified a directed weighted shortest-path problem.
  3. Chose Dijkstra because edge weights are non-uniform and constraints are large.
  4. Implemented host-name-to-ID mapping, adjacency lists, and a heapq priority queue.
  5. Submitted the Python solution through /run.
  6. Captured the returned flag through the harness without printing it.

Reusable Lessons

  • Use Dijkstra for single-source shortest path when weights are non-negative and non-uniform.
  • Map arbitrary string node labels to compact integer IDs before building large graphs.
  • Support minor input-format variation when the prompt wording and example differ slightly.

Dead Ends

  • Raw TCP probe was not the useful interface; HTTP /run was the correct runner path.
  • BFS was rejected because risks are weighted.

Tool Quirks

  • The frontend JavaScript posts JSON to /run with fields code and language.
  • The runner returns JSON; successful responses can contain the flag inside the response body.

Evidence Paths

  • analysis/remote/root-http.txt
  • analysis/remote/prompts.js
  • analysis/remote/run-response.json
  • solve/solution.py
  • solve/solve.py

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.

RankPathEvidenceMissing ProofCheapest ValidationConfidenceStatus
1Remote Coding service likely exposes an HTTP runner or challenge API; identify protocol and problem format before submitting code.Challenge provides only remote host <TARGET>:30290 and a graph/pathfinding scenario.Probe HTTP root and raw TCP banner, then inspect page JavaScript/API endpoints if HTTP is present.MediumActive
1Submit heap-based Dijkstra solution for directed weighted graph with host-name mapping.Problem statement in analysis/remote/root-http.txt specifies lowest cumulative detection risk over unidirectional weighted paths and large graph constraints.Run solution against sample, then submit through /run and capture flag if all tests pass.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition

Memory Summary

approval_required: true

Sanitized Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: Coding
  • Challenge: Pivot-Easy
  • 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.

  1. Fingerprinted the remote as the standard HTB Coding HTTP runner.
  2. Captured the prompt from the root page and identified a directed weighted shortest-path problem.
  3. Chose Dijkstra because edge weights are non-uniform and constraints are large.
  4. Implemented host-name-to-ID mapping, adjacency lists, and a heapq priority queue.
  5. Submitted the Python solution through /run.
  6. Captured the returned flag through the harness without printing it.

Reusable Lessons

  • Use Dijkstra for single-source shortest path when weights are non-negative and non-uniform.
  • Map arbitrary string node labels to compact integer IDs before building large graphs.
  • Support minor input-format variation when the prompt wording and example differ slightly.

Dead Ends

  • Raw TCP probe was not the useful interface; HTTP /run was the correct runner path.
  • BFS was rejected because risks are weighted.

Tool Quirks

  • The frontend JavaScript posts JSON to /run with fields code and language.
  • The runner returns JSON; successful responses can contain the flag inside the response body.

Evidence Paths

  • analysis/remote/root-http.txt
  • analysis/remote/prompts.js
  • analysis/remote/run-response.json
  • solve/solution.py
  • solve/solve.py

Ingestion Decision

  • Proposed for LightRAG: yes
  • Requires user approval before ingestion: yes

Notes

Notes

Scope

  • Challenge: Pivot-Easy
  • Category: Coding
  • Difficulty: Easy
  • Mode: remote
  • Remote instance: <TARGET>:30290
  • Start time: 2026-06-07T23:43:27Z
  • 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

FileSizeSHA256TypeNotes
0remote-only or no provided filesNo local artifacts found under files/

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-07T23:43:27Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-07T23:43:38Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T23:43:38Zhypothesis recordedhypothesis-board.mdRemote Coding service likely exposes an HTTP runner or challenge API; identify protocol and problem format before submitting code.MediumProbe HTTP root and raw TCP banner, then inspect page JavaScript/API endpoints if HTTP is present.
2026-06-07T23:43:54Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-07T23:43:54Zcheckpoint recordedanalysis/checkpoint-triage-20260607T234354500083Z-2c1efa2a.mdCheckpoint for TRIAGEHighUse checkpoint to drive next decision
2026-06-07T23:45:02Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T23: <REDACTED>, then submit through /run and capture flag if all tests pass.
2026-06-07T23: <REDACTED>, capture flag through harness, then complete if successful.
2026-06-07T23: <REDACTED>
2026-06-07T23:46:33Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • Remote service is the standard HTB Coding HTTP runner.
  • Useful endpoint is POST /run, as shown in analysis/remote/root-http.txt.
  • The challenge is a directed weighted shortest-path problem over host names.
  • Constraints require an efficient single-source shortest-path algorithm.
  • solve/solution.py uses Dijkstra with a heap, adjacency lists, and host-name ID mapping.
  • The solver supports both N M start target and N M plus a second start target line.
  • solve/solve.py submitted the code and stored the successful response in analysis/remote/run-response.json.
  • The harness captured the validated flag into loot/flag.txt.

RAG / Advisory Memory

RAG output is advisory only. Record evaluated retrievals with:

bash
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 it like turning a word problem into a repeatable calculator. Once the rule is clear, the solve is making the computer do the boring part consistently.

For Pivot Easy, 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.