Pentest Reporting
Professional report structure, CVSS scoring, evidence documentation, executive summaries, and remediation guidance.
Real-World Analogy
A doctor who finds a tumor but writes an illegible report helps no one. The penetration test exists to improve security — the report is the deliverable. A clear report that drives remediation is more valuable than a sophisticated attack that produces nothing actionable.
Why Reporting Is the Hard Part
Most pentest training focuses on attack techniques. Most penetration testers fail at reporting. A report that:
- Contains findings without evidence = dismissed as false positive
- Has technical depth but no executive summary = not read by decision-makers
- Lists vulnerabilities without remediation = client doesn’t know what to do
- Uses unexplained jargon = misunderstood, misimplemented
The measure of a pentest is whether security improved. That requires a good report.
Report Structure
1. Cover Page
- Engagement title
- Client name
- Testing dates
- Report date
- Classification (Confidential)
- Assessment team
2. Executive Summary (1-2 pages)
- Non-technical audience: C-suite, board
- What was tested, what was found, overall risk posture
- Top 3-5 critical findings
- Risk rating (Critical/High/Medium/Low/Info counts)
- Key recommendations in plain English
3. Scope and Methodology
- What was in scope (IP ranges, domains, URLs)
- What was out of scope
- Testing methodology used (PTES, OWASP, OSSTMM)
- Testing dates and restrictions
4. Findings (bulk of the report)
- One section per finding
- Ordered by severity (Critical first)
5. Appendices
- Detailed scan output
- Tool commands and full evidence
- Successful credentials list
- Complete URL lists tested Finding Documentation Template
Each finding follows this structure:
## FIND-001: SQL Injection in User Search Endpoint
**Severity:** Critical
**CVSS v3.1 Score:** 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
**Affected Component:** https://app.example.com/api/users/search
**CWE:** CWE-89 (SQL Injection)
### Description
The user search endpoint (`/api/users/search?q=`) is vulnerable to SQL injection.
The `q` parameter is directly concatenated into a SQL query without sanitization
or parameterization, allowing an attacker to modify the query structure.
### Impact
An unauthenticated attacker can:
1. Extract all records from the database, including user credentials and PII
2. Modify or delete database records
3. Potentially execute operating system commands if the database user has
elevated privileges (tested: `xp_cmdshell` was not available)
During testing, we extracted 15,847 user records including email addresses,
bcrypt password hashes, and home addresses. We did not exfiltrate or retain this data.
### Evidence
**Request:** GET /api/users/search?q=admin’+OR+‘1’=‘1 HTTP/1.1 Host: app.example.com Authorization: Bearer [redacted]
**Response (truncated):**
```json
{
"users": [
{"id": 1, "email": "admin@example.com", "role": "superadmin"},
{"id": 2, "email": "alice@example.com", "role": "user"},
... (15,845 additional records)
],
"total": 15847
} Screenshot: [SCREENSHOT-001.png]
SQLmap output confirming injection:
[14:23:11] [INFO] GET parameter 'q' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable
[14:23:11] [INFO] the back-end DBMS is MySQL Remediation
Immediate (within 24 hours):
- Disable the
/api/users/searchendpoint until patched
Short-term (within 1 week):
- Replace string concatenation with parameterized queries:
// Vulnerable (current code):
const query = `SELECT * FROM users WHERE name LIKE '%${userInput}%'`;
// Fixed (parameterized query):
const query = 'SELECT * FROM users WHERE name LIKE ?';
const results = await db.query(query, [`%${userInput}%`]); Long-term:
- Implement a Web Application Firewall with SQL injection rules
- Add database activity monitoring to alert on bulk data access
- Conduct SQL injection training for the development team
- Add automated SAST scanning to the CI pipeline (Semgrep, Checkmarx)
References
- OWASP SQL Injection: https://owasp.org/www-community/attacks/SQL_Injection
- CWE-89: https://cwe.mitre.org/data/definitions/89.html
- OWASP Testing Guide: WSTG-INPV-05
## Executive Summary Template
```markdown
## Executive Summary
### Engagement Overview
[Consulting firm] conducted a penetration test of [Company]'s web application and
supporting infrastructure from [start date] to [end date]. The assessment was
authorized under the scope of work signed on [date].
### Overall Risk Posture
The assessment identified **27 vulnerabilities**, including **3 Critical** and
**6 High severity** issues. A critical SQL injection vulnerability allows
unauthenticated access to the entire customer database (15,847 records). Additionally,
two separate pathways to complete administrative compromise were identified.
| Severity | Count |
|----------|-------|
| Critical | 3 |
| High | 6 |
| Medium | 11 |
| Low | 7 |
### Key Findings
1. **SQL Injection (Critical)** — Unauthenticated attackers can extract all customer
data. Patch within 24 hours. (FIND-001)
2. **Default Credentials on Admin Panel (Critical)** — The admin dashboard is accessible
with credentials "admin/admin". Change immediately. (FIND-003)
3. **Unpatched Server (High)** — The web server runs Apache 2.4.29, which has
multiple known vulnerabilities. Update to 2.4.57. (FIND-008)
### Recommendations
Immediate actions (within 24 hours):
- Disable the user search API endpoint
- Change admin dashboard credentials
- Apply emergency WAF rules for SQL injection patterns
Short-term (within 30 days):
- Implement parameterized queries across all database interactions
- Patch Apache to the latest stable version
- Enable multi-factor authentication for all admin accounts
Long-term (within 90 days):
- Establish a vulnerability management program
- Integrate security testing into the development pipeline
- Conduct developer security training CVSS Scoring in Practice
Scoring matrix for common finding types:
SQL Injection (unauthenticated, full DB read):
AV:N AC:L PR:N UI:N S:U C:H I:H A:H = 9.8 (Critical)
Stored XSS (affects all users):
AV:N AC:L PR:L UI:R S:C C:H I:L A:N = 8.0 (High)
IDOR (access another user's data):
AV:N AC:L PR:L UI:N S:U C:H I:N A:N = 6.5 (Medium)
Information Disclosure (server version in header):
AV:N AC:L PR:N UI:N S:U C:L I:N A:N = 5.3 (Medium)
Missing security header (X-Frame-Options):
AV:N AC:H PR:N UI:R S:U C:L I:L A:N = 4.2 (Medium) Use first.org/cvss/calculator/3.1 — don’t calculate manually.
Evidence Collection During Testing
# Screenshot every finding as you find it — don't wait to the end
# Naming: FIND-001-sql-injection-request.png
# Tools: flameshot (Linux), Greenshot (Windows)
# Save all HTTP requests/responses
# Burp Suite: right-click → Save Item → save as .txt
# Export Burp project at end of engagement
# Burp Suite Pro → Project → Save a copy
# Nmap output
sudo nmap -sV -sC -oA scan-results 192.168.1.100
# Keep all tool output
nikto -h http://target.com 2>&1 | tee nikto-output.txt
sqlmap -u "..." --dump 2>&1 | tee sqlmap-output.txt
# Terminal session recording
script -a pentest-session.log # records everything typed and output Bug Bounty Reporting
Bug bounty reports are shorter but follow the same structure:
## Title: SQL Injection in /api/search Allows Database Dump
**Severity:** Critical
**CVSS:** 9.8
**Asset:** api.target.com
## Summary
The `q` parameter in the search API is injectable, allowing full database extraction
without authentication.
## Steps to Reproduce
1. Send the following request:
`GET /api/search?q=' OR 1=1-- HTTP/1.1`
2. Observe all records returned instead of empty results
3. Use the UNION technique to extract tables:
`GET /api/search?q=' UNION SELECT table_name,NULL FROM information_schema.tables--`
## Impact
Complete database read access including user PII and credentials.
## Proof of Concept
[Screenshot showing database contents returned]
## Suggested Fix
Use parameterized queries:
```sql
SELECT * FROM products WHERE name LIKE ? Pass %${userInput}% as the bound parameter.
References
- OWASP SQL Injection Prevention Cheat Sheet
**Bug bounty tips:**
- Clear title with the vulnerability type and affected endpoint
- Steps must be reproducible exactly — triagers follow them verbatim
- Include proof (screenshot, video, response body) — not just "I saw it"
- Impact section should explain real-world consequences, not just technical effect
- Suggest a fix — shows competence and reduces back-and-forth
## Certifications Roadmap
Entry level: CompTIA Security+ → security fundamentals, required for many jobs CompTIA Network+ → networking (do before Security+ if new to networking) eJPT (eLearnSecurity) → hands-on entry pentest, beginner-friendly
Intermediate: OSCP (Offensive Security) → gold standard practical cert, required by most pentest firms CEH (EC-Council) → vendor cert, less respected but widely recognized by HR eWPT (eLearnSecurity) → web application penetration testing
Advanced: OSED (Exploit Developer) → advanced Windows exploitation (by OffSec) OSEP (Experienced Pentester) → evasion, AD attacks CRTP (Certified Red Team Pro) → Active Directory attacks CISSP → management/governance track
Path recommendation:
- Security+ (foundational, opens doors)
- TryHackMe + HackTheBox for hands-on
- OSCP (requires: at least 3 months of HTB/VulnHub practice)
- Specialize: OSED (binary), OSEP (AD), or web-focused certs