← Vigil ContinuumDiscuss your scope
SAMPLE REPORT
Public illustrative sample

Penetration Test Report

Example Client — FinTech Platform
Engagement ID
EXAMPLE-001
Assessment Type
Full Penetration Test
Period
Illustrative assessment period
Classification
Public sample
Methodology
OWASP ASVS / PTES
Total Findings
23 (3C / 7H / 9M / 4L)
PUBLIC SAMPLE — Illustrates report structure and example findings. It is not evidence of a named client engagement; figures are excluded from our published client totals.

•Table of Contents

1. Executive SummaryAssessment overview, risk posture, key metrics
2. Scope & MethodologyTargets, approach, tools, limitations
3. Findings SummaryAll 23 findings by severity
4. Detailed Findings3 representative findings with PoC
5. Risk AssessmentBusiness impact analysis
6. Remediation RoadmapPrioritized fix timeline

1Executive Summary

Vigil Continuum Group was engaged to perform a comprehensive penetration test of [Client]'s FinTech platform, including the web application, REST API, payment processing workflows, and authentication mechanisms. The assessment was conducted over a 14-day period using a combination of manual expert testing and automated scanning.

The assessment identified 23 security findings, including 3 Critical and 7 High severity vulnerabilities that pose immediate risk to user data, financial transactions, and platform integrity.

23
Total Findings
3
Critical
7
High
13
Medium / Low
Critical (3) High (7) Medium (9) Low (4)

Key Findings

  • Insecure Direct Object Reference (IDOR) in user profile and transaction endpoints allows any authenticated user to access other users' personal data and financial records (Critical, CVSS 9.1)
  • Authentication Bypass Chain combining JWT algorithm confusion with session fixation enables full account takeover without credentials (High, CVSS 8.6)
  • Payment Callback Forgery via unsigned webhook allows creation of fraudulent balance credits (Critical, CVSS 9.8)
  • Race Condition in withdrawal endpoint permits double-spend under concurrent requests (Critical, CVSS 9.4)
Overall Risk Rating: HIGH — Multiple critical findings enable unauthorized access to financial data and manipulation of transaction flows. Immediate remediation is strongly recommended before the next production release.

2Scope & Methodology

In-Scope Targets

TargetTypeAuth Level
app.example.comWeb Application3 roles (User, Manager, Admin)
api.example.com/v1/*REST APIBearer JWT
api.example.com/v1/payments/*Payment APIHMAC + Bearer
ws.example.comWebSocketToken-based

Methodology

01
Reconnaissance
Surface mapping, technology fingerprinting, endpoint discovery
02
Analysis
Authentication flows, business logic, data flow mapping
03
Exploitation
Manual testing, chain building, PoC development
04
Verification
Negative controls, false positive elimination
05
Impact Proof
Real-world exploit chains, business impact demonstration
06
Reporting
Findings documentation, remediation guidance, executive brief

Standards & Frameworks

  • OWASP Application Security Verification Standard (ASVS) v4.0
  • Penetration Testing Execution Standard (PTES)
  • CVSS v3.1 for severity scoring
  • PCI DSS v4.0 requirements (where applicable)

3Findings Summary

The table below provides an overview of all identified findings, sorted by severity. Detailed write-ups for representative findings follow in Section 4.

ID Finding Severity CVSS Status
F-001 Payment Callback Forgery — Unsigned Webhook Allows Free Balance CRITICAL 9.8 Verified
F-002 Race Condition in Withdrawal Flow — Double-Spend CRITICAL 9.4 Verified
F-003 IDOR in User Profile & Transaction History Endpoints CRITICAL 9.1 Verified
F-004 JWT Algorithm Confusion + Session Fixation → Account Takeover HIGH 8.6 Verified
F-005 CORS Origin Reflection with Credentials on API Domain HIGH 8.2 Verified
F-006 Missing Rate Limiting on OTP Verification Endpoint HIGH 7.5 Verified
F-007 Privilege Escalation via Role Parameter Tampering HIGH 8.1 Verified
F-008 WebSocket Authentication Bypass After Token Expiry HIGH 7.4 Verified
F-009 Server-Side Request Forgery via PDF Export Functionality HIGH 7.6 Verified
F-010 Stored XSS in Transaction Notes via Markdown Renderer HIGH 7.1 Verified
F-011 Verbose API Error Messages Expose Internal Architecture MEDIUM 5.3 Verified
F-012 Missing Security Headers (CSP, X-Frame-Options, HSTS) MEDIUM 5.0 Verified
F-013 GraphQL Introspection Enabled in Production MEDIUM 5.3 Verified
F-014 Unrestricted File Upload Type — SVG Injection MEDIUM 6.1 Verified
F-015 Session Token in URL Query Parameter MEDIUM 4.3 Verified
F-016 Insufficient Password Complexity Requirements MEDIUM 4.8 Verified
F-017 User Enumeration via Registration Error Messages MEDIUM 5.3 Verified
F-018 Insecure Direct Object Reference in Document Download MEDIUM 6.5 Verified
F-019 Missing Certificate Pinning in Mobile API Calls MEDIUM 4.8 Verified
F-020 Deprecated TLS 1.0/1.1 Supported on API Endpoint LOW 3.7 Verified
F-021 Server Version Disclosure in HTTP Response Headers LOW 3.1 Verified
F-022 Cookie Without Secure and HttpOnly Flags LOW 3.5 Verified
F-023 Clickjacking — Missing X-Frame-Options on Login LOW 3.1 Verified

4Detailed Findings

Three representative findings are presented below to demonstrate the depth of analysis, proof-of-concept methodology, and remediation guidance provided in the full report.

F-003 Insecure Direct Object Reference — User Profile & Transaction History
Severity
Critical
CVSS 3.1
9.1 (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N)
CWE
CWE-639
Endpoint
GET /api/v1/example/users/{id}
Access Required
Any authenticated user
State
VERIFIED

Description

The user profile endpoint accepts a numeric user_id parameter without verifying that the authenticated user is authorized to access the requested profile. By incrementing or decrementing the ID, any authenticated user can retrieve the full profile (including PII, KYC documents, and transaction history) of any other user on the platform.

Sequential user IDs make enumeration trivial. The same authorization flaw extends to /api/v1/example/users/{id}/transactions, exposing complete financial records.

Proof of Concept

# Step 1: Request own profile (user_id=14523) — baseline curl -s https://api.example.com/v1/example/users/14523 \ -H "Authorization: Bearer eyJhbG....example" \ -H "Content-Type: application/json" → 200 OK { "id": 14523, "email": "tester@example.com", "full_name": "[Own Account Name]", "phone": "+1***...7890", "kyc_status": "verified", "balance": "1,250.00" } # Step 2: Request ANOTHER user's profile (user_id=14524) — IDOR curl -s https://api.example.com/v1/example/users/14524 \ -H "Authorization: Bearer eyJhbG....example" \ -H "Content-Type: application/json" → 200 OK { "id": 14524, "email": "victim@example.com", "full_name": "[Another User's Full Name]", "phone": "+1***...4567", "kyc_status": "verified", "balance": "48,720.50", "created_at": "2025-03-14T09:22:11Z" } # Step 3: Access victim's transaction history curl -s https://api.example.com/v1/example/users/14524/transactions?limit=50 \ -H "Authorization: Bearer eyJhbG....example" → 200 OK { "total": 847, "transactions": [ {"id": 98201, "type": "deposit", "amount": "5,000.00", "status": "completed", ...}, {"id": 98195, "type": "withdrawal", "amount": "2,100.00", "status": "completed", ...}, ... ] } # Negative control: Unauthenticated request curl -s https://api.example.com/v1/example/users/14524 → 401 Unauthorized {"error": "Authentication required"}

Impact

  • Full PII exposure for all platform users (name, email, phone, KYC documents)
  • Complete transaction history disclosure (amounts, counterparties, timestamps)
  • Balance information enables targeted social engineering attacks
  • Sequential IDs allow automated mass enumeration of the entire user base
  • Potential regulatory violations (GDPR, PCI DSS Requirement 7)

Pass 2 — False Positive Elimination

Verified that no object-level authorization check exists in the middleware chain. The endpoint validates the JWT token (authentication) but does not compare the token's sub claim against the requested user_id. No WAF rule or rate limiter blocks enumeration. The response contains real user data, not cached/default values.

Remediation

  • Implement object-level authorization: compare the authenticated user's ID (from JWT sub claim) against the requested resource's owner ID before returning data
  • Replace sequential integer IDs with UUIDs in all public-facing API paths
  • Apply the same authorization check to /transactions, /documents, and all user-scoped endpoints
  • Implement rate limiting on user-scoped endpoints to limit enumeration velocity
  • Log and alert on sequential access patterns across different user IDs

F-004 Authentication Bypass Chain — JWT Algorithm Confusion + Session Fixation
Severity
High
CVSS 3.1
8.6 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N)
CWE
CWE-287, CWE-384
Endpoint
POST /api/v1/example/auth/*
Access Required
Unauthenticated
State
VERIFIED

Description

The authentication system is vulnerable to a multi-step attack chain that combines two distinct weaknesses to achieve full account takeover without knowing the victim's credentials.

Attack Chain

  1. JWT Public Key Extraction. The /.well-known/jwks.json endpoint exposes the RSA public key used for token verification. The server accepts tokens signed with both RS256 and HS256 algorithms without restriction.
  2. Algorithm Confusion. The attacker forges a JWT by signing it with the HS256 algorithm using the public RSA key as the HMAC secret. The server's JWT library treats the public key as a valid HMAC secret and accepts the forged token.
  3. Session Fixation. The password reset flow generates a pre-authenticated session token in the response body before the user completes the reset. This token is valid for 15 minutes and grants full session access to the target account.
  4. Account Takeover. Using the forged admin JWT from Step 2, the attacker triggers a password reset for any user via the admin panel's /api/v1/example/admin/users/{id}/reset endpoint, capturing the pre-authenticated session token from the response.

Proof of Concept

# Step 1: Retrieve public key curl -s https://api.example.com/.well-known/jwks.json | jq '.keys[0]' → {"kty":"RSA","n":"0vx7agoebGcQ...","e":"AQAB","use":"sig","alg":"RS256"} # Step 2: Forge JWT with algorithm confusion (HS256 + public key as secret) # [Tool output redacted — jwt_tool used for demonstration] → Forged token: eyJhbGciOiJIUzI1NiIs...example # Step 3: Verify forged token grants admin access curl -s https://api.example.com/v1/example/admin/dashboard \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs...example" → 200 OK {"role": "admin", "permissions": ["users.read", "users.write", "finance.read", ...]} # Step 4: Trigger password reset (captures pre-auth session) curl -s -X POST https://api.example.com/v1/example/admin/users/14524/reset \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs...example" → 200 OK {"session_token": "a8f3e2d1...example", "expires_in": 900}

Impact

  • Full account takeover for any user on the platform without credentials
  • Administrative access enables mass data exfiltration
  • Financial transactions can be initiated from compromised accounts
  • The chain requires no user interaction — fully server-side exploitation

Pass 2 — False Positive Elimination

Confirmed that the JWT library (jsonwebtoken v8.x) does not enforce algorithm restriction. Verified the forged token actually grants admin-level API access (not just a 200 response). The pre-authenticated session token from the reset flow was used to access the victim's dashboard, confirming full ATO.

Remediation

  • Enforce a strict algorithm allowlist in JWT verification: reject any token with an algorithm not matching the server's signing configuration
  • Update the JWT library to the latest version with algorithm confusion protections
  • Remove pre-authenticated session tokens from password reset responses — require the user to complete the full reset flow before granting access
  • Implement separate key stores for different signing algorithms

F-011 Verbose API Error Messages Expose Internal Architecture
Severity
Medium
CVSS 3.1
5.3 (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)
CWE
CWE-209
Endpoint
Multiple API endpoints
Access Required
Unauthenticated
State
VERIFIED

Description

Multiple API endpoints return verbose error messages in production that disclose internal implementation details, including database table names, ORM query structures, internal service URLs, and stack traces with file paths. This information significantly reduces the effort required for an attacker to identify and exploit deeper vulnerabilities.

Proof of Concept

# Malformed request triggers verbose error curl -s -X POST https://api.example.com/v1/example/users/search \ -H "Content-Type: application/json" \ -d '{"query": {"$gt": ""}}' → 500 Internal Server Error { "error": "SequelizeDatabaseError", "message": "column \"$gt\" does not exist", "sql": "SELECT \"id\", \"email\", \"full_name\", \"phone\", \"balance\" FROM \"users\" WHERE ...", "stack": "Error: column \"$gt\" does not exist\n at Query.run (/app/node_modules/sequelize/...)\n at /app/src/controllers/userController.js:142:28", "env": "production", "service": "user-service", "version": "3.2.1", "internal_url": "http://service.example:3001" }

Disclosed Information

Data TypeExampleRisk
Database schemaTable users with columnsAssists IDOR / SQLi construction
ORM & versionSequelize (Node.js)Known CVE targeting
File paths/app/src/controllers/Directory structure mapping
Internal URLsservice.example:3001SSRF target identification
Service version3.2.1Version-specific exploit research

Impact

While information disclosure alone does not directly compromise user data, the leaked details were actively used during this assessment to develop the IDOR (F-003) and SSRF (F-009) exploits faster. Internal service URLs discovered through error messages directly enabled the SSRF attack chain.

Remediation

  • Implement a global error handler that returns generic error messages to clients in production: {"error": "Internal server error", "request_id": "uuid"}
  • Log detailed error information server-side only (structured logging to a centralized system)
  • Remove the stack, sql, internal_url, and env fields from all API error responses
  • Ensure NODE_ENV=production disables debug output across all microservices

5Risk Assessment

The following matrix summarizes the overall risk posture based on findings categorized by impact area.

4
Data Breach Risk
3
Financial Fraud Risk
5
Account Takeover Risk
3
Privilege Escalation
5
Information Leakage
3
Configuration Issues

Business Impact Summary

Impact AreaScenarioEstimated Exposure
CRITICAL Mass PII exfiltration via IDOR enumeration Regulatory fines, class action risk
CRITICAL Fraudulent balance creation via callback forgery Direct financial loss, unlimited scale
CRITICAL Double-spend via race condition $50K–$500K+ depending on withdrawal limits
HIGH Account takeover via authentication bypass chain Reputational damage, user trust erosion

6Remediation Roadmap

Findings are prioritized into three remediation phases based on severity, exploitability, and business impact.

Phase Timeline Findings Action
P0 Immediate
(0–72 hours)
F-001, F-002, F-003 Payment callback signature validation, withdrawal locking, IDOR authorization checks
P1 Short-term
(1–2 weeks)
F-004 through F-010 JWT algorithm enforcement, CORS policy, rate limiting, XSS sanitization, SSRF controls
P2 Medium-term
(2–4 weeks)
F-011 through F-023 Error handling, security headers, GraphQL hardening, TLS configuration, cookie flags
Retest Available. VCG offers a complimentary retest of all Critical and High findings within 30 days of remediation to verify the fixes are effective. Contact us to schedule.