Key Takeaways: Web Application Security
A one-page reference. Reread before an exam or before Chapter 21. Dense by design.
The one idea behind every web attack
Almost every web vulnerability is attacker-controlled data being interpreted as code by some interpreter (database, browser, shell, the server's own outbound request). Every durable fix re-establishes the data/code boundary structurally. Defend in three layers: code (the only true fix) → browser (CSP, SameSite — limits damage) → edge (WAF — blocks noise, buys time, telemetry).
Attack → Fix → Detect (memorize this table)
| Attack | What goes wrong | The secure FIX (structural) | How to DETECT attempts |
|---|---|---|---|
| SQL injection | Input becomes part of a DB command | Parameterized queries (prepared statements); allowlist identifiers you can't parameterize | SQL metacharacters in params (union select, or 1=1, --, ;, /*); HTTP 500 spikes from one source |
| Command injection | Input becomes part of a shell command | Pass args as a list to an API with no shell; never concatenate a shell string | Shell metacharacters (;, |, backticks, $()) in params; unexpected process spawns |
| Stored XSS | Saved input runs as script in every viewer's browser | Output encoding by default (auto-escaping templates); scan stored fields | Script-like content in stored fields; CSP violation reports |
| Reflected XSS | Input echoed from a request runs once in a victim's browser | Same: context-aware output encoding | <script, onerror=, javascript:, <svg, <img src (and encoded variants) in inputs |
| DOM-based XSS | Client JS writes untrusted input to a dangerous sink | Safe sinks (textContent, not innerHTML); treat URL/fragment as untrusted |
Often invisible in access logs (payload in URL fragment) → CSP report-uri/report-to |
| CSRF | Browser auto-sends an authenticated, unintended request | Anti-CSRF tokens (synchronizer pattern) + SameSite cookies |
Rejected/missing-token spikes; cross-site Origin/Referer on state-changing routes |
| SSRF | Server tricked into an outbound request to attacker's target | Allowlist destinations; block private/loopback/link-local (re-check after DNS + redirects); egress filtering | User-influenced fetches resolving to internal IPs; app server reaching 169.254.169.254 |
| Session fixation | Same session ID kept across login | Regenerate session ID at login (discard old) | Session ID seen before auth still valid after; unusual session reuse |
| Session theft / replay | Stolen/replayed session token | HttpOnly+Secure+SameSite; high-entropy IDs; server-side logout/invalidation; step-up auth |
One session ID from two distant IPs/user-agents; session use after logout |
CSP — the directives that matter (XSS defense in depth)
Content-Security-Policy:
default-src 'self'; # fallback: only our own origin
script-src 'self'; # *** the key line: no 'unsafe-inline' -> injected inline <script> blocked
object-src 'none'; # no plugins
base-uri 'self'; # attacker can't repoint relative URLs
frame-ancestors 'self'; # clickjacking defense (modern X-Frame-Options)
report-uri /csp-report # browser POSTs violations -> SOC telemetry (esp. for DOM XSS)
script-src 'self'with NO'unsafe-inline'is the single most valuable line for XSS. A CSP with'unsafe-inline'inscript-srcis nearly worthless against XSS. Use nonces/hashes for the few inline scripts you truly cannot move to files.- CSP does not fix XSS (vulnerable code is still vulnerable); it turns a successful injection into a blocked, reported non-event.
Session cookie flags (set all three)
| Flag | Defends against |
|---|---|
HttpOnly |
XSS reading the session cookie (denies the common XSS payload its prize) |
Secure |
Cookie sent over plaintext HTTP (pairs with HSTS from Ch.9) |
SameSite=Lax/Strict |
CSRF (browser won't attach cookie cross-site) |
WAF — the defender's stance (say this precisely)
- IS: defense in depth; blocks the noisy/automated majority; virtual patching (rule blocks a specific bug while code is fixed); attack telemetry for the SOC.
- IS NOT: a fix. The vulnerability still exists; skilled attackers bypass WAFs with encoding/obfuscation.
- Run it: high-confidence rules block, the rest alert to the SIEM — and read the alerts (owner + SLA). "We don't need to fix it, the WAF blocks it" = the dangerous fallacy.
Detection log sources (each catches what the others miss)
| Source | Best for |
|---|---|
| Web access logs | Injection + reflected/stored-XSS probing in the URI/query; error spikes |
| WAF logs | Pre-correlated attack rule matches (broad coverage; needs tuning) |
| Application logs | CSRF (rejected tokens), SSRF (resolved internal destinations), session anomalies — look like valid HTTP |
| CSP violation reports | DOM-based XSS and blocked injections invisible to server logs |
"When to use what" decision aids
- Building a query with user data? → parameterize (never concatenate). Need a user-chosen column? → allowlist (can't parameterize identifiers).
- Rendering untrusted data into a page? → encode for the context; prefer an auto-escaping template.
- State-changing endpoint with cookie auth? → anti-CSRF token +
SameSite. - Server fetches a user-supplied URL? → allowlist + block internal ranges + egress filter (re-check after redirects/DNS).
- Public-facing web app? → WAF in front + the detections above feeding the SIEM.
Common pitfalls
- "We sanitize inputs" as the SQLi fix (it's partial; parameterize). • "We use an ORM" (raw-SQL escape hatches reintroduce the bug — verify binding on every query).
- HTML-encoding data that lands in a
<script>/attribute/URL context (wrong escaping → still breaks out). - A CSP with
'unsafe-inline'(no real XSS protection). • Assuming a JSON API is CSRF-immune (depends on auth method, not body type). - Blocklisting internal IPs for SSRF (DNS rebinding/redirects defeat it — allowlist + re-check + egress).
- Logout that only deletes the cookie (invalidate server-side). • Trusting a WAF to excuse unfixed code, or running it unmonitored.
Certification crosswalk
| Concept | CompTIA Security+ | (ISC)² CISSP domain |
|---|---|---|
| Injection (SQL/command) + parameterization | Application attacks; Secure coding | Software Development Security |
| XSS (stored/reflected/DOM) + output encoding + CSP | Application attacks; Secure coding | Software Development Security |
| CSRF / SSRF | Application attacks | Software Development Security; Security Architecture |
| Session management (fixation, cookie flags) | Secure coding; Identity & access | Software Development Security; IAM |
| WAF as a control | Security architecture / network appliances | Security Architecture & Engineering |
| Same-origin policy | (concept) | Software Development Security |
Project additions this chapter
- Meridian program — web-application security controls: parameterized queries everywhere; output
encoding by default; strict CSP (
script-src 'self'); CSRF tokens +SameSite/Secure/HttpOnly - session rotation + server-side logout; WAF (block + alert→SIEM) and SSRF guards. (Second half of the "Secure-SDLC + web-app controls" increment; sets up Ch.31's pipeline gates and Ch.21's SIEM use cases.)
bluekittoolkit —appsec.pygainstaint_demo(src, sink)— an illustrative taint-tracking demonstrator (untrusted source → dangerous sink without a sanitizer = VULNERABLE), modeling how SAST (Ch.12) reasons about injection. Never executed; hand-traced.