This document covers the raw mechanics of HTTP — request/response anatomy, methods, headers, status codes, cookies, and TLS basics — that everything else in web application testing is built on top of, mapping to eJPT’s “Introduction to the Web & HTTP Protocol” module. It’s the prerequisite layer beneath web-enumeration-common-vulns-cheatsheet-professional.md (which assumes you already read a request/response) and burp-suite-cheatsheet-professional.md (which is the tool that lets you intercept and edit what’s described here).
Every HTTP exchange follows the same four-part structure — a start line, headers, a blank line, and an optional body — and being able to read this by eye is the single most fundamental skill for web testing.
POST /login HTTP/1.1
Host: target.example.com
User-Agent: Mozilla/5.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
Cookie: session=abc123
username=admin&password=test
POST /login HTTP/1.1), or for a response, version + status code + reason phrase (HTTP/1.1 200 OK)\r\n that separates headers from the body; its absence/presence is what tells a parser where headers endPOST/PUT, normally absent on GETHTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1256
Set-Cookie: session=xyz789; HttpOnly; Secure
<html>...</html>
Note: the response mirrors the same structure — status line, headers, blank line, body — which is why learning to read one half makes the other half trivial.
Each HTTP method signals a different intended action on the target resource, and knowing what each is supposed to do is what lets a tester spot when the server does something it shouldn’t.
| Method | Purpose | Testing relevance |
|---|---|---|
| GET | Retrieve a resource, no body expected | Most common attack surface — parameters live in the URL, easy to fuzz/log |
| POST | Submit data to be processed (forms, API calls) | Body-based injection points; not logged in browser history/URLs |
| PUT | Create/replace a resource at a given URI | If enabled and unauthenticated, can allow arbitrary file upload/overwrite |
| DELETE | Remove a resource | If enabled without auth checks, can allow unauthorized data destruction |
| HEAD | Same as GET but returns headers only, no body | Useful for quickly checking status/headers without downloading content |
| OPTIONS | Ask the server which methods are allowed on a resource | First check for verb tampering — reveals the attack surface for that endpoint |
# Ask the server what it will accept on this endpoint
curl -i -X OPTIONS http://target/api/users
Verb tampering / method override: an endpoint that only checks auth on
GETbut not onPOST/PUT/DELETEfor the same path is a classic authorization bypass — always re-test a blocked action with a different method (orX-HTTP-Method-Overrideheader) before ruling it out.
Headers carry most of the metadata an attacker can read, spoof, or abuse, so a handful of them are worth checking on every single request.
| Header | Direction | Security relevance |
|---|---|---|
Host |
Request | Determines routing/vhost selection — spoofable for host header injection, password-reset poisoning, vhost/cache-based attacks |
Cookie |
Request | Carries session tokens — theft/prediction leads directly to session hijacking |
Authorization |
Request | Carries credentials (Basic/Bearer/JWT) — check for weak encoding, missing expiry, algorithm confusion |
Content-Type |
Both | Declares body format — mismatched/spoofed values can bypass upload filters or trigger different parsers server-side |
User-Agent |
Request | Client fingerprint string — attacker-controlled, sometimes reflected/logged unsanitized (XSS/log injection) |
X-Forwarded-For |
Request | Client IP as seen by a proxy — often trusted blindly, making it a common IP allowlist/rate-limit bypass vector |
Referer |
Request | Prior page URL — can leak sensitive tokens in URLs, sometimes checked (weakly) for CSRF protection |
GET /admin HTTP/1.1
Host: internal-panel.target.local
X-Forwarded-For: 127.0.0.1
User-Agent: <script>alert(1)</script>
Note:
X-Forwarded-For: 127.0.0.1is a standard first move against IP-based access controls — many applications trust this header without verifying it came from an actual upstream proxy.
Status codes are grouped into five classes by their first digit, and testers develop a reflex for which specific codes are worth a second look.
| Code | Meaning | Why it matters for testing |
|---|---|---|
| 200 OK | Request succeeded | Baseline for comparison — confirm this is what a legitimate response looks like |
| 301/302 | Redirect (permanent/temporary) | Follow to see final destination — open redirects and post-login redirect logic live here |
| 401 Unauthorized | Authentication required/failed | No valid credentials presented at all — different from 403, matters for distinguishing “who are you” vs “you can’t” |
| 403 Forbidden | Authenticated but not permitted | Server recognizes the request but denies it — a prime target for authorization-bypass testing (IDOR, forced browsing, method tampering) |
| 404 Not Found | Resource doesn’t exist | Baseline for “nothing here” — useful for diffing against 403 to enumerate hidden paths |
| 500 Internal Server Error | Unhandled server-side error | Often leaks stack traces, file paths, or SQL syntax — a strong signal that malformed input reached vulnerable code |
401 vs 403: 401 means “I don’t know who you are” (no/invalid credentials); 403 means “I know who you are, and you’re still not allowed.” A 403 on a resource you can’t reach as an authenticated low-privilege user is exactly the kind of finding IDOR/auth-bypass testing targets (see
web-enumeration-common-vulns-cheatsheet-professional.md).
Cookies are how a stateless protocol fakes a persistent login session, and the Set-Cookie attributes attached to them determine how much an attacker can do if they get near that cookie.
Set-Cookie: session=xyz789; Secure; HttpOnly; SameSite=Strict
| Attribute | What it does | Risk if missing |
|---|---|---|
| Secure | Cookie only sent over HTTPS | Cookie can be sniffed in plaintext over HTTP (e.g. on shared/untrusted networks) |
| HttpOnly | Cookie inaccessible to JavaScript (document.cookie) |
An XSS finding becomes full session-token theft instead of just DOM manipulation |
| SameSite | Controls whether the cookie is sent on cross-site requests (Strict/Lax/None) |
Missing/None makes the application more exposed to CSRF |
# Quickly check a target's cookie attributes
curl -i https://target/login | grep -i set-cookie
Note: finding all three attributes present doesn’t mean session management is fully secure — also check session token entropy/predictability and whether the token rotates on privilege change (e.g. after login).
Everything above — request lines, headers, status codes, Set-Cookie — is exactly what an intercepting proxy shows and lets you edit, which is why this file is the conceptual groundwork for proxy-based testing.
Browser → Proxy (127.0.0.1:8080) → Target server
← ←
burp-suite-cheatsheet-professional.md — this section is only the “why” behind that toolNote: understanding the raw request/response format first makes Burp’s Proxy/Repeater tabs far less confusing — they’re just a GUI over the exact text shown in Section 1.
HTTPS wraps HTTP inside an encrypted TLS tunnel, and a tester mainly needs to know how that encryption gets in the way of — and gets deliberately bypassed for — inspection.
# Quick command-line look at a target's certificate details
curl -vI https://target 2>&1 | grep -i -A2 "subject\|issuer\|SSL certificate"
Note: self-signed/expired/mismatched-hostname certs on a target itself (not the proxy) are also worth flagging as findings — they indicate weak TLS hygiene even outside interception setup.
curl gives quick, scriptable HTTP access without spinning up a browser or proxy — ideal for one-off header checks, method tests, and redirect tracing.
curl -i https://target/ # -i: include response headers in output
curl -s https://target/ -o /dev/null -w "%{http_code}\n" # print only the status code
curl -L https://target/old-page # -L: follow redirects (301/302) to final destination
curl -X PUT https://target/api/file -d @payload # -X: set a custom/non-default HTTP method
curl -X OPTIONS -i https://target/api/users # enumerate allowed methods on an endpoint
curl -H "X-Forwarded-For: 127.0.0.1" https://target/admin # inject a custom header
curl -b "session=abc123" https://target/profile # -b: send a cookie with the request
curl -A "custom-agent-string" https://target/ # -A: set a custom User-Agent
curl -k https://target/ # -k: ignore TLS cert validation (self-signed lab targets only)
Note:
curlis not a replacement for a proxy — it doesn’t save history or let you replay/diff requests — but it’s faster for a single sanity check like “does this endpoint accept PUT” or “does this redirect chain end where I expect.”
A single-page lookup for every command/header covered above.
| Need | Command/Header |
|---|---|
| Show response headers | curl -i https://target/ |
| Print only the HTTP status code | curl -s -o /dev/null -w "%{http_code}\n" https://target/ |
| Follow redirects to final destination | curl -L https://target/old-page |
| Send a custom/non-default method | curl -X PUT https://target/api/file -d @payload |
| Enumerate allowed methods (verb tampering recon) | curl -X OPTIONS -i https://target/api/users |
| Spoof source IP for access-control bypass attempts | curl -H "X-Forwarded-For: 127.0.0.1" https://target/admin |
| Send a cookie manually | curl -b "session=abc123" https://target/profile |
| Set a custom User-Agent | curl -A "custom-agent-string" https://target/ |
| Skip TLS cert validation (lab targets only) | curl -k https://target/ |
| Inspect a target’s TLS certificate | curl -vI https://target 2>&1 \| grep -i -A2 "subject\|issuer" |
| Check cookie security attributes | curl -i https://target/login \| grep -i set-cookie |
Prepared as a reference for the eJPT web application pentest module. All techniques should only be used within written authorization (scope/RoE).