Web Application Vulnerabilities
Almost every web vulnerability reduces to one idea — untrusted data crosses a boundary and becomes code or a command. User input flows into a SQL query, an HTML page, a shell string, a file path, or the body of a serialized object — and wherever the parser cannot tell your data apart from your instructions, the attacker takes control. The defensive job is always the same — keep data as data at every crossing.
This section dissects the main classes of web attack not as a payload collection but as a set of trust boundaries and ways to hold them. For each class you get the mechanism (how input turns into execution), a concrete example, and the root-cause defense, not cosmetics. Mixing the classes up (mistaking SQL injection for a race, XSS for CSRF, path traversal for XSS) is the single most common interview trap. The full map is in the layers below.
Topic map
- XSS — cross-site scripting — how attacker JavaScript lands on the page and why the primary defense is context-aware output encoding and CSP.
- DOM-based XSS — XSS entirely in the browser, the "source → dangerous sink" flow, and safe sinks instead of
innerHTML. - CSRF — cross-site request forgery — how another site makes the victim's browser send a state-changing request, and how
SameSiteand tokens close it. - Clickjacking and tabnabbing — deception via an invisible iframe and tab hijacking via
window.opener, defended with headers andrel=noopener. - SQL injection — how input alters a query's structure and why parameterization closes it at the root.
- Blind SQL injection — extracting data with no visible output via a boolean and timing oracle, and the same parameterization defense.
- NoSQL injection — operators like
$ne/$regexin a JSON body and the defense by type coercion and schema. - SQL injection through an ORM — raw escape hatches (
literal,raw,text) the ORM does not parameterize. - OS command injection — shell metacharacters and the defense via an argument vector with no interpreter.
- SSTI — server-side template injection — input as template source versus input as data, the path to server-side RCE.
- Insecure deserialization — gadget chains from untrusted bytes and the defense by a safe format and a class allowlist.
- Path traversal —
../in a filename and the defense by path canonicalization and a prefix check. - Local file read (LFR) —
php://wrappers and mime-check bypass, defended by a source allowlist and re-encoding. - Path traversal via nginx alias — a trailing-slash mismatch between
location/aliasas a security bug. - SSRF — server-side request forgery — the server fetching internal addresses, blocklist bypasses, and the defense by validating the resolved IP.
- Business-logic races — TOCTOU on read-modify-write and the defense by making the operation atomic.
- Office-document attacks — xlsx/docx as ZIP+XML (Zip Slip, XXE, CSV injection) and the defense by sandboxed parsing.
Common traps
| Mistake | Consequence |
|---|---|
| Escaping input instead of context-aware output encoding | XSS gets through — the render context is what matters, not the moment of intake |
Treating httpOnly/TLS/POST as enough against CSRF or XSS | False sense of security; the attack class itself is not closed |
Filtering with a blocklist (characters, ../, localhost) | A bypass always exists via encoding or an alternate representation |
| Hand-escaping quotes instead of parameterizing SQL | One forgotten edge or exotic encoding and the injection returns |
Trusting the ORM's "safety" and putting input next to literal/raw | Raw ORM escape hatches are not parameterized — direct SQL injection |
| Validating the raw URL/path string, not the resolved result | Normalization after the check (TOCTOU, DNS rebinding) bypasses the filter |
| Assuming image rendering or a "non-SQL" DB is immune | Zip Slip, XXE, CSV injection, $ne/$regex — the attack is just in another syntax |
| Confusing attack classes with one another | A wrong diagnosis leads to a fix that does not close the hole |
Interview relevance
Web vulnerabilities are asked to check whether you see the trust boundary and can name a defense that closes the attack class at its root rather than treating a symptom. A strong candidate on a code question quickly names the class ("this is OS command injection because input flows into a shell string"), states the mechanism in one sentence, and gives a fix that removes the possibility itself ("an argument vector with no shell"), not a blocklist.
Typical checks:
- Correct classification: injection versus race, XSS versus CSRF, SSRF versus CSRF, path traversal versus XSS.
- Root-cause defense: parameterization, context-aware encoding + CSP, an argument vector, allowlists, atomicity, path canonicalization.
- Why popular half-measures fail — blocklists,
httpOnly,try/catch, validation before normalization. - Understanding that "data becomes code" is the shared root of most of these bugs.
Common wrong answer: naming a symptomatic fix as the root fix — "add rate limiting against the race", "escape output against SQL injection", "enable HTTPS against CSRF". Each leaves the original attack class open.