Blind Exploitation

When results are not rendered, use boolean conditions that flip the app's response to leak bits (like blind SQLi). You need any observable difference: success vs error text, status code, or measurable processing time.

Core Boolean Pattern

Assume input lands in a predicate on username:

/users/user[username='<INPUT>']

Inject a universally true clause:

invalid' or '1'='1

If the app reports "success" for the injected value, you confirmed XPath injection (blind).

Name Length, Name, and Children Count

Use XPath functions in boolean checks:

  • Length of root element name:

invalid' or string-length(name(/*[1]))=L and '1'='1
  • Character-by-character name of a node:

invalid' or substring(name(/*[1]),POS,1)='a' and '1'='1
  • Number of children:

invalid' or count(/users/*)=N and '1'='1

Iterate L, POS, N until the response flips to "success".

Enumerating Schema

  • Start at /*[1].

  • Determine name and count(/*).

  • Recurse into each child /*[i].

Automating (Python template)

Time-based Signal (when responses are identical)

XPath has no sleep(), but you can force heavy evaluation to create measurable delay when a condition is true:

  • If the substring condition is true, count((//.)[count(//.)]) triggers exponential traversal and slows the response.

  • If false, that branch is skipped (short-circuit), response remains fast.

Increase nested count() stacks for small documents, but beware of DoS on large ones.

Practical Tips

  • Stabilize the positive/negative signal (match exact success text, status code, or timing threshold).

  • URL-encode payloads when needed; prefer POST to avoid length limits.

  • Narrow string.printable to speed up (e.g., ascii_letters + digits + '{}_:-@./').

  • Cache intermediary findings (lengths, partial names) to resume interrupted runs.

  • Redact secrets/flags from notes; store sensitive outputs separately.

Last updated