Not a course.
A curriculum.
Progressive study from core web fundamentals to specialized bug hunting. Each module builds on the last. No gaps, no shortcuts.
HTTP is a stateless request-response protocol over TCP. Every request has an exact structure: METHOD /path HTTP/1.1\r\n, then headers, then \r\n\r\n (the critical separator), then optional body. HTTP/2 uses binary frames but Burp translates it — your workflow doesn't change.
GET — No body. Idempotent. But many APIs accept params in body anyway.
PUT — Replaces the full resource. Very interesting for IDOR.
PATCH — Partial modification. Even more interesting for IDOR.
DELETE — Always test if it works without auth.
OPTIONS — CORS negotiation. Reveals what methods the server allows.
Hunter thought: Try PUT /api/users/123 instead of GET. Many backends implement the happy path (GET, POST) but forget to protect less common verbs.
401 — Unauthenticated. No token.
403 — Authenticated but no permission. THE difference from 401.
404 — Or is it a 403 disguised? Many backends do this.
500 — Note what input caused it.
Differential error: If /api/documents/456 returns 403 but /api/documents/9999 returns 404, you confirmed ID 456 exists. That's user enumeration via status code oracle.
Most BAC/IDOR bugs live in the gap between authorization middleware and business logic. The middleware checks 'can you access documents?' but the business logic accepts documentId without verifying that document belongs to you.
Browser → CDN/WAF → LB → Auth MW → Authz MW → Routing → Business logic → DB
The gap between Authz MW and Business logic is where most bugs live.
Many backends use X-Forwarded-For for rate limiting, geolocation, or IP whitelist bypass. Test:
X-Forwarded-For: 127.0.0.1X-Real-IP: 127.0.0.1True-Client-IP: 10.0.0.1
If the server uses Host to build password reset links or confirmation emails, change it to your domain:
Host: evil.attacker.com
If the WAF only filters JSON but the backend accepts form data, you can bypass protections. Try switching:
Content-Type: application/x-www-form-urlencodedContent-Type: multipart/form-data