zwesty
Write-ups / Day 24 / Script
Day 24 · Sat, Oct 24 · Script

Web of Lies

Prey slaughtered

Script triage across 20+ languages, JSP webshell fixtures, analysis-descriptor plans, layered encodings (LYR-), ATT&CK mapping

STTMClaude Homebase Both

Flags are shortened to their first 8 and last 4 characters because they're unique per team.

Challenge ID
script-analysis-day-24-jsp-webshell-source (+ /time_trial, /mastery)
Solved
2026-10-24: all three modes CORRECT on the first submit, by 09:01:40 ET, 20 s after the first start request on this lane (09:01:20 ET) and 1 min 40 s after the 9 AM release. Both timed modes were ranked runs
Player
Zwesty (solo), with Claude Code (Opus 5.5): our automated morning solver (a scheduled script on our Kali VM) did all three modes, with no hands-on work needed

The challenge

"This JSP source is shaped like a webshell: it reads requests and stages server-side work. Recover the order of requests and stages, then separate the inert fixture behavior from the lines that would be real execution primitives in the wild."

Script is cumulative: the Single Solve asked 1,516 questions over one evidence.zip of 162 scripts. Today's new files were five JSP files with 11 questions each (55 in all). For the webshell host:

answer_id Question Format
host-jsp-webshell-jsp-role "Classify the inert source role." enum (benign_utility, downloader, dropper, staged_chain, …)
host-jsp-webshell-jsp-attack Map the decoded ordered behaviour graph to one primary ATT&CK technique (with a stated precedence) ATT&CK ID
host-jsp-webshell-jsp-steps "Recover the ordered behavior graph using > separators." tokens joined by >
host-jsp-webshell-jsp-host-profile "Identify the script host or webshell source container." exact text
host-jsp-webshell-jsp-stage-count, -stage-profile, -next-language Stage count, multi-stage relationship profile, next language in the inert handoff integer / exact text
host-jsp-webshell-jsp-adapter, -campaign, -url, -obfuscation Modelled adapter, campaign ID, URL indicator, ordered encoding profile exact text

The Time Trial asked 1,560 questions in Day 23's timed schema (13 per polyglot file); the Mastery asked them across 8 sets (12,480).

Reading the prompt: what it said we'd need

Clue What it pointed to What I did about it
"This JSP source" New language: JavaServer Pages Five .jsp files: four polyglots and one host-jsp-webshell-jsp.jsp fixture. The solver's generic plan reader covers any polyglot-* or host-* file, so nothing new was needed
"shaped like a webshell" A host fixture with a webshell profile Its plan names host_profile = jsp_webshell (an older PHP fixture is php_webshell)
"reads requests and stages server-side work" Download-then-execute steps The plan's steps: acquire_remote>dispatch_process, stage profile two_stage_download_execute
"Recover the order of requests and stages" Ordered fields steps (joined by >), stage-count, stage-profile, next-language
"separate the inert fixture behavior from the lines that would be real execution primitives" Role and ATT&CK classification, and trusting the decoded plan only when the code agrees The solver uses a plan only if the header agrees with the body; otherwise it stops ("read it by hand")
"Web of Lies" (title) A webshell, and possibly a descriptor that doesn't tell the truth The header/body check is the guard. The one inconsistency found was inside the plan itself (below)

Safety

Static analysis only. Nothing was executed. The scripts sit in a password-protected (WinZip AES) archive and were read as text and decoded in Python; no JSP container, Java runtime, or other interpreter was started. The archives stayed on our Kali VM. For this write-up the JSP source wasn't re-read: what it contains is described from the answers the Game Master accepted and the code that produced them. Indicators below are defanged.

What was in the files

  • Single Solve: evidence.zip, 144,836 bytes, 162 members: Day 23's 157 scripts plus polyglot-jsp-{benign-utility,downloader,launcher,staged-chain}.jsp and host-jsp-webshell-jsp.jsp (1,253 bytes).
  • The webshell host's plan (accepted values): role staged_chain, ATT&CK T1059, adapter operation_graph, 2 stages, steps acquire_remote>dispatch_process, host profile jsp_webshell, obfuscation base64, stage profile two_stage_download_execute, next language jscript, campaign JSP-0f2508fa, URL hxxps://jsp-0f2508fafa[.]example[.]invalid/stage.
  • The plan disagrees with itself. A download-and-execute graph would normally map to a downloader and T1105 (the polyglot-jsp-downloader.jsp plan has the same steps and is downloader/T1105), but the webshell's plan records staged_chain/T1059. The solver sends the plan's own values, and they were accepted, as on Day 23.
  • Time Trial: evidence.zip, 163,210 bytes, also 162 files, in Day 23's timed schema: every file renamed to a 6-hex stem (588efb.jsp), question IDs built from it (polyglot-jsp-588efb-role), host files folded into the polyglot family, and a HUNTRESS_ANALYSIS_V1:LYR-… header naming the encoding layers in the order applied. The five JSP files had roles benign_utility (2), stager, downloader, and persistence_descriptor, with layer lists such as b32_rev_b64 and b64_frag_b64.
  • Mastery: 1,292,954 bytes, 8 sets in the timed schema.

So the timed variants were the same generator as Day 23's timed sets, with five JSP files per set added.

Single Solve

The solver got it in two batches, with no stop. Its core answered 1,386 questions, all 55 new ones included: it finds each polyglot-* or host-* file, parses the analysis header, checks that the header agrees with the body, and returns the plan field the question names. The core flagged 55 values it had seen rejected on other questions before (none, T1105, T1059.007, delayed, and similar) and sent them anyway, as designed; none was rejected. The add-on modules then sent the other 130.

started_at  2026-10-24T13:01:20.478Z
deadline    none (Single Solve)
answers     1,386 core (accepted, remaining 130), then 130 add-on answers
start        608 ms
artifact     398 ms
solve        348 ms
submit      2261 ms   (core 470, add-ons 1789)
TOTAL       3618 ms
result      CORRECT   flag 07da80aa…72b0

Time Trial

CORRECT on the first attempt, ranked. The question IDs were hex stems, so the routing added on Day 23 sent the set to the timed-schema adapter, which answers each file from its own decoded plan. No change was needed for JSP.

started_at  2026-10-24T13:01:29.390Z
deadline    2026-10-24T13:02:19.390Z   (50 s)
answers     1,560
start        673 ms
artifact     450 ms
solve         61 ms
submit       989 ms
TOTAL       2175 ms   (submit +1.69 s after started_at)
result      CORRECT   flag 980f4633…a7df

Mastery

CORRECT on the first attempt, ranked (8 sets, 260 s clock). Day 23's fix that scopes the .ps1 hand-off lookup to one inner zip held across the 8 sets.

started_at  2026-10-24T13:01:36.896Z
deadline    2026-10-24T13:05:56.896Z   (260 s)
answers     12,480 across 8 sets
start       1240 ms
artifact     483 ms   (1.3 MB)
solve        496 ms
submit      1943 ms
TOTAL       4179 ms   (submit +3.59 s after started_at)
result      CORRECT   flag f0977c3e…5daf

Time to solve

All three modes were solved by 09:01:40 ET, 1 min 40 s after release (20 s from the first start request on this lane). The Time Trial and Mastery were both ranked and each went through on the first submit.

Takeaways

  • Yesterday's fix carried today. Day 23's timed-schema adapter and the same-zip hand-off scope were written for GDScript; today's JSP files went through them unchanged in both timed modes.
  • A generic plan reader beats a per-language parser. The solver never needed to understand JSP: it reads the analysis header and checks it against the body, whatever the language.
  • The plan is the answer, even when it looks wrong. The webshell's staged_chain/T1059 doesn't match its download-and-execute steps, but the plan's own values were accepted. Don't "correct" a descriptor value from the rubric unless a rejection says to.
  • The prompt promises more than the questions ask. "The order of requests" sounded like HTTP parameters or verbs; the fields were the usual plan fields.