Challenge / Coding

Cred Hunter

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

EasyPublished 2024-02-23Sanitized local writeup

Scenario

Cred Hunter attack path

Cred Hunter 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.

Cred Hunter sanitized attack graph

Walkthrough flow

01

The remote challenge is an HTTP HTB Coding runner...

02

The challenge input is a mixed dump of strings...

03

Employee emails use a lowercase local part structured...

04

The first name is recovered by removing the final...

05

A valid pair exists when the first name appears as an...

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/Cred-Hunter/writeup.md
  • htb-challenge/Coding/Cred-Hunter/notes.md
  • htb-challenge/Coding/Cred-Hunter/memory-summary.md
  • htb-challenge/Coding/Cred-Hunter/hypothesis-board.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Coding__Cred-Hunter__memory-summary.md.64f7363650.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Coding__Cred-Hunter__notes.md.f2b7621c95.md

Technical Walkthrough

Writeup

Challenge

  • Name: Cred-Hunter
  • Category: Coding
  • Difficulty: Easy
  • Mode: remote

Summary

Cred Hunter is a remote HTB Coding runner. The task is to parse a mixed dump of strings, identify employee email addresses, identify credential-string candidates, then output every valid email/credential pair where the employee's first name appears inside the credential string.

The working solution classifies Cygnus employee emails, extracts the first name from the local part by removing the final last-initial character, checks exact substring matches against non-email credential strings, sorts the unique pairs, and submits the answer through the runner.

Artifact Inventory

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

  • analysis/remote/root-http.txt: confirms the remote surface is an HTTP Coding runner.
  • analysis/remote/prompts.js: frontend runner JavaScript and challenge prompt source.
  • analysis/remote/initial-nc-probe.txt: confirms this is not a useful raw socket prompt.
  • analysis/remote/run-response.json: saved runner response from the successful /run submission.
  • solve/solution.py: submitted Python solution.
  • solve/solve.py: local submitter that posts solution.py to /run and stores the flag candidate under loot/.

Analysis

The prompt recovered from the remote HTTP page states that the input is a mixed dump of employee emails and credential strings. Employee emails use a lowercase firstname + last_initial local part before an organization domain. Credential strings are entries that do not follow the employee email format.

The important matching rule is exact and case-sensitive: a pair is valid when the extracted first name appears as a substring inside a credential string. The prompt explicitly says uppercase-to-lowercase conversion is not required, so the solution preserves input case.

The output must be sorted lexicographically by email, with multiple credentials for the same email sorted lexicographically. Sorting the unique (email, credential) tuples directly satisfies both requirements.

The implementation treats only lowercase Cygnus-style organization emails as employees. Anything else, including non-matching email-like garbage, remains a credential candidate. This avoids false positives from arbitrary @ strings.

Solve

solve/solution.py performs the challenge logic:

  1. Read N and the following dump strings.
  2. Classify employee emails with a Cygnus-domain regex.
  3. Extract first_name from the local part by removing the final last-initial character.
  4. Treat every non-matching string as a credential candidate.
  5. Record every exact first-name substring match.
  6. Print sorted unique pairs in the required two-column format.

solve/solve.py submits the solution to the remote /run endpoint, saves the full response to analysis/remote/run-response.json, extracts only the flag candidate into loot/flag-candidate.txt, and leaves final validation to the harness.

Flag

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

Lessons

  • For HTB Coding runners, first determine whether the service is HTTP or raw socket. This one exposes /run.
  • Preserve the exact matching semantics from the prompt. Here, lowercasing would be an unnecessary mutation.
  • Do not classify every @ string as an employee email; use the stated organization email structure.
  • Keep the flag capture path harness-managed so future writeups can explain the solve without leaking the raw flag.

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: Cred-Hunter
  • Category: Coding
  • Difficulty: Easy
  • Mode: remote
  • Remote instance: <TARGET>:30415
  • Start time: 2026-06-08T00:26:39Z
  • 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-08T00:26:39Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-08T00:26:50Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-08T00:26:50Zhypothesis recordedhypothesis-board.mdRemote Coding service likely exposes an HTTP runner; identify exact credential matching input/output before submission.MediumProbe HTTP root, inspect prompt and JavaScript, then implement the stated parsing/matching algorithm.
2026-06-08T00:27:13Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-08T00:27:13Zcheckpoint recordedanalysis/checkpoint-triage-20260608T002713220596Z-8b70eb88.mdCheckpoint for TRIAGEHighUse checkpoint to drive next decision
2026-06-08T00:28:23Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-08T00:28:23Zhypothesis recordedhypothesis-board.mdSubmit parser that classifies Cygnus employee emails, extracts first names from localpart[:-1], and emits sorted pairs where first name is a credential substring.MediumRun solution against sample, then submit through /run and capture flag if all tests pass.
2026-06-08T00:28:33Zevaluatoranalysis/evaluator-20260608T002833848501Z-b0d10d3b.mdProceedHighRun solve/solve.py, capture flag through harness, then complete if successful.
2026-06-08T00:28:55Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-08T00:31:36Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • The service is a standard HTTP HTB Coding runner, not a useful raw socket prompt.
  • The useful execution surface is /run, which accepts Python code through JSON.
  • Employee emails are lowercase Cygnus-style addresses where the local part is firstname + last_initial.
  • The first name is recovered by removing the final local-part character.
  • Credential candidates are non-employee-email strings.
  • A valid pair requires an exact case-sensitive first-name substring match.
  • The solution prints sorted unique email/credential pairs.
  • solve/solution.py passed the runner, and the harness captured the 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: Cred-Hunter
  • 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. The remote challenge is an HTTP HTB Coding runner with a /run endpoint.
  2. The challenge input is a mixed dump of strings containing employee emails and credential candidates.
  3. Employee emails use a lowercase local part structured as firstname + last_initial and a Cygnus-style company domain.
  4. The first name is recovered by removing the final character from the email local part.
  5. A valid pair exists when the first name appears as an exact substring inside a credential string.
  6. Non-employee-email strings are treated as credential candidates.
  7. Unique (email, credential) pairs are sorted lexicographically and printed in the required two-column format.
  8. The submitted solution passed the runner and the harness captured the flag under loot/.

Reusable Lessons

  • For Coding challenges, identify the runner interface first. HTTP /run submissions need a local submitter wrapper; raw sockets need a different harness.
  • Preserve prompt semantics exactly. Here, no case normalization is required.
  • Employee-email classification should be stricter than "string contains @"; non-matching email-like values may be garbage or credential candidates.
  • Sorting tuple pairs directly is a simple way to satisfy email-first and credential-second ordering.

Dead Ends

  • Treating the challenge as a raw socket service was not useful; the service is HTTP.
  • Lowercasing credential candidates or first names is unnecessary and could create false matches.
  • Treating every @-containing string as an employee email would risk misclassification.

Tool Quirks

  • The frontend JavaScript posts Python code to /run as JSON with {"code": "...", "language": "python"}.
  • The successful runner response was stored locally, while the raw flag was captured only through the harness into loot/.

Evidence Paths

  • analysis/remote/root-http.txt
  • analysis/remote/prompts.js
  • analysis/remote/initial-nc-probe.txt
  • analysis/remote/run-response.json
  • solve/solution.py
  • solve/solve.py
  • loot/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.

RankPathEvidenceMissing ProofCheapest ValidationConfidenceStatus
1Remote Coding service likely exposes an HTTP runner; identify exact credential matching input/output before submission.Challenge provides remote host <TARGET>:30415 and a credential matching scenario.Probe HTTP root, inspect prompt and JavaScript, then implement the stated parsing/matching algorithm.MediumActive
1Submit parser that classifies Cygnus employee emails, extracts first names from localpart[:-1], and emits sorted pairs where first name is a credential substring.Problem statement in analysis/remote/root-http.txt specifies first-name matching, exact case, and lexicographic ordering by email/credential.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: Cred-Hunter
  • 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. The remote challenge is an HTTP HTB Coding runner with a /run endpoint.
  2. The challenge input is a mixed dump of strings containing employee emails and credential candidates.
  3. Employee emails use a lowercase local part structured as firstname + last_initial and a Cygnus-style company domain.
  4. The first name is recovered by removing the final character from the email local part.
  5. A valid pair exists when the first name appears as an exact substring inside a credential string.
  6. Non-employee-email strings are treated as credential candidates.
  7. Unique (email, credential) pairs are sorted lexicographically and printed in the required two-column format.
  8. The submitted solution passed the runner and the harness captured the flag under loot/.

Reusable Lessons

  • For Coding challenges, identify the runner interface first. HTTP /run submissions need a local submitter wrapper; raw sockets need a different harness.
  • Preserve prompt semantics exactly. Here, no case normalization is required.
  • Employee-email classification should be stricter than "string contains @"; non-matching email-like values may be garbage or credential candidates.
  • Sorting tuple pairs directly is a simple way to satisfy email-first and credential-second ordering.

Dead Ends

  • Treating the challenge as a raw socket service was not useful; the service is HTTP.
  • Lowercasing credential candidates or first names is unnecessary and could create false matches.
  • Treating every @-containing string as an employee email would risk misclassification.

Tool Quirks

  • The frontend JavaScript posts Python code to /run as JSON with {"code": "...", "language": "python"}.
  • The successful runner response was stored locally, while the raw flag was captured only through the harness into loot/.

Evidence Paths

  • analysis/remote/root-http.txt
  • analysis/remote/prompts.js
  • analysis/remote/initial-nc-probe.txt
  • analysis/remote/run-response.json
  • solve/solution.py
  • solve/solve.py
  • loot/flag.txt

Ingestion Decision

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

Notes

Notes

Scope

  • Challenge: Cred-Hunter
  • Category: Coding
  • Difficulty: Easy
  • Mode: remote
  • Remote instance: <TARGET>:30415
  • Start time: 2026-06-08T00:26:39Z
  • 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-08T00:26:39Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-08T00:26:50Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-08T00: <REDACTED>, inspect prompt and JavaScript, then implement the stated parsing/matching algorithm.
2026-06-08T00:27:13Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-08T00:27:13Zcheckpoint recordedanalysis/checkpoint-triage-20260608T002713220596Z-8b70eb88.mdCheckpoint for TRIAGEHighUse checkpoint to drive next decision
2026-06-08T00:28:23Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-08T00: <REDACTED>, extracts first names from localpart[: <REDACTED>, and emits sorted pairs where first name is a credential substring.MediumRun solution against sample, then submit through /run and capture flag if all tests pass.
2026-06-08T00: <REDACTED>, capture flag through harness, then complete if successful.
2026-06-08T00: <REDACTED>
2026-06-08T00:31:36Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • The service is a standard HTTP HTB Coding runner, not a useful raw socket prompt.
  • The useful execution surface is /run, which accepts Python code through JSON.
  • Employee emails are lowercase Cygnus-style addresses where the local part is firstname + last_initial.
  • The first name is recovered by removing the final local-part character.
  • Credential candidates are non-employee-email strings.
  • A valid pair requires an exact case-sensitive first-name substring match.
  • The solution prints sorted unique email/credential pairs.
  • solve/solution.py passed the runner, and the harness captured the 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 Cred Hunter, 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.