MagicalPalindrome
Name: - Category: - Difficulty: Raw flag is stored in
Scenario
MagicalPalindrome attack path
Name: - Category: - Difficulty: Raw proof is stored in
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
Moderate source coverage
Status: partial. This article is generated from 4 sanitized Markdown sources and keeps raw flags, credentials, keys, cookies, and reusable secrets out of the rendered blog.
Moderate confidence: the page is useful for review, but it should be treated as partial because the available source material is thinner or less narrative-complete.
- Web/MagicalPalindrome/writeup.md
- htb-challenge/Web/MagicalPalindrome/notes.md
- htb-challenge/Web/MagicalPalindrome/memory-summary.md
- htb-challenge/Web/MagicalPalindrome/hypothesis-board.md
Technical Walkthrough
Writeup
Challenge
- Name:
- Category:
- Difficulty:
Summary
Artifact Inventory
Analysis
Solve
Flag
Raw flag is stored in loot/flag.txt.
Lessons
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: Magical Palindrome
- Category: Web
- Difficulty: Very Easy
- Target: http://<TARGET>:30732/
- Started: 2026-05-07
Evidence Ledger
| Timestamp | Action | Finding | Next |
|---|---|---|---|
| 00:00 | Extract zip, read source | Hono app, palindrome check, nginx 75-byte body limit | Analyze constraints |
| 00:01 | Read nginx.conf | client_max_body_size 75 — body must be under 75 bytes | Find type confusion |
| 00:03 | Tried array of 1001 strings | 413 — payload too large | Try gzip |
| 00:04 | Tried gzip compression | Passed nginx (46 bytes) but 500 — server can't decompress | Type confusion |
| 00:08 | Sent object with string length | Flag returned! 52-byte payload passes all checks | Done |
Vulnerability
- Type: JSON type confusion + JavaScript coercion
- Constraint: nginx limits body to 75 bytes, palindrome needs
.length >= 1000 - Trick: Pass an object with
"length": "1001"(STRING, not number)
- "1001" < 1000 → JS coerces to 1001 < 1000 → false (passes length check)
- Array("1001") creates ["1001"] (1-element array, NOT 1001-element sparse array)
- Loop runs only ONCE (index 0), needs only properties "0" and "1000"
- Payload: {"palindrome":{"length":"1001","0":"a","1000":"a"}} = 52 bytes
| 2026-05-27T23:35:17Z | backfill | challenge-state.json | Legacy workspace backfilled with deterministic state | High | Validate before further work |
Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category:
- Challenge:
- Difficulty:
- Source 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
| Rank | Path | Evidence | Missing Proof | Cheapest Validation | Confidence | Status |
|---|
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 MagicalPalindrome, 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.