Interstellar
Interstellar is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
Interstellar attack path
Interstellar 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 Web evidence, validation, and reusable operator lessons.
Walkthrough flow
Source and route audit
Trust boundary flaw
Exploit request chain
Admin or proof proof
Source coverage
High source coverage
Status: complete. This article is generated from 4 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.
- Web/Interstellar/writeup.md
- htb-challenge/Web/Interstellar/notes.md
- htb-challenge/Web/Interstellar/memory-summary.md
- htb-challenge/Web/Interstellar/hypothesis-board.md
Technical Walkthrough
Writeup
Challenge
- Name: Interstellar
- Category: Web
- Difficulty: Medium
- Mode: hybrid
Summary
Interstellar is a PHP/Smarty web challenge where the intended chain combines an
old URL parser differential with a second-order SQL injection.
The working chain is:
- Register and log in as a normal user.
- Use
communicate.phpas an internal POST gadget with a PHP/cURL parser
differential URL.
- Abuse that internal request to bypass the
<secret redacted> == <TARGET>check on
the name-edit action.
- Store a SQL injection payload as the current user's
name. - Trigger
/, which calls the vulnerablesearchUserstored procedure and
evaluates the stored name inside dynamic SQL.
- Use
SELECT ... INTO OUTFILEto write a small PHP command runner into the
webroot.
- Read the randomized root-level flag path with a shell glob.
Artifact Inventory
Reference analysis/artifact-inventory.json and summarize the relevant files or remote surface.
files/a12c733c-03de-4b2c-9290-59ba1ef202ea.zip: original HTB archive.files/extracted/challenge/src/: PHP/Smarty application source.files/extracted/challenge/init.sql: database schema and stored procedures.files/extracted/challenge/Dockerfile: deployment detail showing the flag is
moved to a randomized root-level *_flag.txt path.
analysis/url-parser-probe-pipe.txt: live validation of the parser
differential URL shape.
analysis/ssrf-edit-probe.txt: live validation that SSRF can mutate the
localhost-only edit path.
solve/solve.py: final reproducible solver.
Analysis
The source audit found three relevant facts:
communicate.phpvalidates a user-supplied URL with<secret redacted>,
parses it with parse_url, requires the parsed host to match
/motherland\.com$/, and then calls cURL using only $parsedUrl['host'].
index.php?action=editis protected by a direct localhost check using
$_SERVER['<secret redacted>'] != '<TARGET>', but accepts new_name without
sanitization when reached locally.
init.sqldefinessearchUser(name)with dynamic SQL:
CONCAT('SELECT * FROM users WHERE name = \'', name, '\'').
The URL payload below passed the PHP-side suffix check but reached localhost
through cURL:
1232://user:pass@<TARGET>:80|motherland.com:80/That was validated non-destructively in analysis/ssrf-edit-probe.txt by
changing a logged-in user's name through the localhost-only edit branch.
The final exploit stores a second-order SQLi payload as the user's name. A later
request to / calls searchUser($_SESSION['name']), which evaluates the
payload in the stored procedure. The payload writes a small PHP command runner
to a random filename in /var/www/html/, then the solver requests it to run
cat /*_flag.txt.
Solve
Run:
cd <local workspace>
python3 scripts/challenge_exec.py Web/Interstellar --phase exploit --output analysis/flag-candidate.txt -- python3 Web/Interstellar/solve/solve.py --base-url http://<TARGET>:32196 --output Web/Interstellar/analysis/flag-candidate.txt --debug-output Web/Interstellar/analysis/exploit-debug.txt
python3 scripts/challenge_harness.py capture-flag Web/Interstellar --from analysis/flag-candidate.txtThe solver creates a fresh account, performs the internal edit through
communicate.php, triggers the SQLi/webshell write, reads the flag, and writes
only the candidate output file for harness capture.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- Parser-differential bugs must be validated against the exact runtime pair.
Here the PHP URL parser and cURL disagreed in a useful way.
- The SSRF was not the end goal; it was a local-origin primitive that unlocked a
second-order SQL injection.
- The randomized flag filename made
INTO OUTFILEmore useful than direct SQL
file reading, because a PHP shell could use filesystem globbing.
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: Interstellar
- Category: Web
- Difficulty: Medium
- Mode: hybrid
- Remote instance: none
- Start time: 2026-06-11T22:55:06Z
- 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 |
|---|---|---|---|---|
files/a12c733c-03de-4b2c-9290-59ba1ef202ea.zip | 166240 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 25 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-11T22:55:06Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-11T22:55:06Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-11T22:56:26Z | hypothesis recorded | hypothesis-board.md | Register/login, then use communicate.php as an SSRF/internal POST gadget: submit URL with host allowed by /motherland\.com$/ and data[action]=edit,data[new_name]=SQLi payload. The internal request carries the <secret redacted> and bypasses <secret redacted> == <TARGET>, storing a malicious session name that later reaches searchUser's dynamic SQL. | Medium | Register/login on remote and post data[action]=edit through communicate.php; verify the index name changes or SQL error appears on subsequent /. |
| 2026-06-11T22:56:26Z | hypothesis recorded | hypothesis-board.md | Exploit Smarty/server-side template injection through a name or response rendering path if SQLi only gives errors. | Medium | Search templates/PHP for display of user-controlled values and validate escaping locally/from rendered remote output. |
| 2026-06-11T23:01:26Z | checkpoint recorded | analysis/checkpoint-analysis-20260611T230126004068Z-3150fb9b.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-11T23:01:55Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-11T23:01:55Z | source audit | analysis/source-audit.md | Source audit recorded | High | Gate before exploit |
| 2026-06-11T23:01:55Z | instrumentation plan | analysis/instrumentation-plan.md | Exploit Interstellar reproducibly and capture the remote flag without printing it. | High | Stop after two webshell write attempts without a new SQL error or file-existence signal; record failure and rerank hypotheses. |
| 2026-06-11T23:02:07Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-11T23:02:07Z | evaluator | analysis/evaluator-20260611T230207486374Z-ca8db40f.md | Proceed | High | Run solve/solve.py through challenge_exec and capture the flag candidate. |
| 2026-06-11T23:03:05Z | exploit | analysis/flag-candidate.txt | Solver used parser-differential SSRF, second-order SQLi, and INTO OUTFILE webshell write to read the randomized flag path | High | Capture flag through harness |
| 2026-06-11T23:03:11Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-11T23:03:57Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
communicate.phpvalidates the parsed host suffix but passes onlyparse_url($url)['host']to cURL.- The nonstandard URL
1232://user:pass@<TARGET>:80|motherland.com:80/reaches localhost on the live service. - The localhost-only edit branch can store an unsanitized
new_namein the active session and database row. searchUserconcatenates the stored name into dynamic SQL, creating a second-order SQL injection.- The final exploit writes a small PHP command runner with
SELECT ... INTO OUTFILEand reads the randomized root-level flag path using a shell glob.
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: Web
- Challenge: Interstellar
- Difficulty: Medium
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
1.
Reusable Lessons
-
Dead Ends
-
Tool Quirks
-
Evidence Paths
-
Ingestion Decision
- Proposed for LightRAG: yes/no
- 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 | Register/login, then use communicate.php as an SSRF/internal POST gadget: submit URL with host allowed by /motherland\.com$/ and data[action]=edit,data[new_name]=SQLi payload. The internal request carries the <secret redacted> and bypasses <secret redacted> == <TARGET>, storing a malicious session name that later reaches searchUser's dynamic SQL. | communicate.php validates url host suffix then cURLs parsed host with http_build_query(data); index.php edit action is localhost-only; init.sql searchUser builds SQL with CONCAT on name. | Register/login on remote and post data[action]=edit through communicate.php; verify the index name changes or SQL error appears on subsequent /. | Medium | Active | |
| 2 | Exploit Smarty/server-side template injection through a name or response rendering path if SQLi only gives errors. | Smarty templates render assigned variables, but default escaping/assignment path needs validation; challenge hint says old bug with twist likely SSRF-to-SQLi rather than direct SSTI. | Search templates/PHP for display of user-controlled values and validate escaping locally/from rendered remote output. | Medium | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit Condition |
|---|
Technical analogy
How to remember this solve
Think of the web app like a building with signs on every door. The solve usually comes from reading the map carefully, finding the door the app forgot to hide, then sending the exact request that proves you understand the route.
For Interstellar, 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.