CVE Reversing (Web Vulnerabilities)¶
This page is a practical, repeatable workflow for turning “there’s a CVE” into:
- a verified understanding of what actually changed
- a minimal, safe proof
- a scan/detection artifact (when appropriate)
It’s written for web-app / web-service style issues (auth bypass, SSRF, file upload, traversal, deserialization, template injection, etc.).
Source inspiration: ProjectDiscovery’s methodology writeup: https://projectdiscovery.io/blog/how-to-research-web-vulnerabilities
This page summarizes and adapts the workflow; do not treat it as vendor-specific guidance.
0) Triage: is this CVE worth reversing?¶
Prioritize when you have strong signals of reachability and impact:
- Pre-auth remote attack surface (edge-facing components)
- Low complexity / few steps
- Defaults likely (common deployments)
- Mentioned primitives: path normalization, serialization, template rendering, header trust, proxy auth, SSO
- Clean patch/hotfix available (diff will be small)
Deprioritize (unless you have special context):
- Requires niche configuration
- User interaction only
- Pure info-disclosure that doesn’t unlock tokens/secrets or privilege escalation
1) Build a controlled lab¶
Goal: reproduce safely, with tight observability.
Checklist:
- Pin exact versions: one vulnerable + one fixed (ideally adjacent releases)
- Record deployment assumptions (OS, container, reverse proxy, default config)
- Capture logs and requests from day 1 (Burp export / raw HTTP)
Practical environment notes¶
- Prefer local containers/VMs so you can breakpoint / instrument.
- If closed-source: collect installers, release notes, docs, forum hints, third-party writeups.
2) Find the change (your roadmap)¶
There are two common starting points:
A) Vendor hotfix/patch bundle exists¶
Start here. It often points directly at the vulnerable code path.
B) Only releases exist (no patch file)¶
Use diffing:
- Obtain vulnerable build + patched build
- Unpack/decompile into two trees
- Put vulnerable tree in git, overlay patched tree, then
git diff
Focus on:
- input validation changes
- new/removed allowlists/denylists
- normalization/canonicalization steps (URL/path)
- authn/authz checks moved earlier/later
- new helper functions / “barrier” checks
3) Map inputs → code paths¶
Once you know what changed, your job is to answer:
- What request reaches the changed function?
- What fields are attacker-controlled? (path, headers, query params, body)
- What trust boundary is being crossed? (proxy → app, app → internal network, user → template engine)
Common “bug shapes” worth explicitly testing:
- TOCTOU: check uses decoded/normalized value; handler uses raw value
- Header trust:
X-Forwarded-*,X-Real-IP,Host, internal-only shortcuts - Path canonicalization:
%2f,;path params,..segments, double-decode - Deserialization: unexpected object graphs, type confusion, gadget triggers
4) Write a safe proof¶
A good PoC is:
- minimal (fewest moving parts)
- deterministic (reliable)
- version-pinned
- low-impact (read-only if possible)
Prefer “proof markers” like:
- a distinctive response header/body marker
- a privileged read-only endpoint access
- a controlled time delay (timing-only classes)
Avoid:
- destructive writes
- broad fuzz payloads that may destabilize targets
Always validate against:
- at least one vulnerable version
- at least one fixed version (negative control)
5) Turn proof into detection (optional)¶
If you plan to ship a scanner template:
- keep request minimal
- use multiple matchers (status + unique marker)
- fail fast; avoid following redirects blindly
- document assumptions (auth required? proxy required? platform differences?)
6) Keep your research reproducible¶
Suggested case folder per CVE:
lab-notes.md(what you tried, what worked, what didn’t)requests/(raw HTTP, Burp exports)diffs/(patch notes, git diff snippets)detections/(templates, validation logs)lab/(docker-compose, configs)
The “tiny quirks” you record often become the key later.