Practical Security & Networking
OWASP Top 10, auth & crypto, and the URL-to-render journey — with a hands-on JWT decoder, an HTTP header linter you can point at any site, and 25 exam-grade MCQs.
OWASP Top 10 — the attacks every campus test asks
Injection, XSS, CSRF and CORS explained with the exact prevention interviewers want to hear.
| Attack | Runs where | Core prevention |
|---|---|---|
| SQL injection | Database | Prepared statements / parameterized queries |
| XSS | Victim's browser | Escape output, CSP, auto-escaping frameworks |
| CSRF | Victim's browser → your API | SameSite cookies + CSRF tokens |
| CORS misconfig | Browser policy | Tight Allow-Origin, never `*` with credentials |
| Broken access control | Server logic | Check ownership/role on every object (IDOR) |
SQL Injection & prepared statements
Injection happens when user input is concatenated into a query string: `"SELECT * FROM users WHERE name = '" + input + "'"` lets `x' OR '1'='1` change the query's meaning. Prevention: parameterized queries (prepared statements) so the driver sends SQL and data separately — the database can never reinterpret data as code. ORMs do this by default; string-formatted queries are the red flag in code reviews.
// VULNERABLE
const q = `SELECT * FROM users WHERE email = '${email}'`;
// SAFE — parameterized
const q = db.prepare("SELECT * FROM users WHERE email = ?");
q.execute([email]);XSS: stored, reflected, DOM
Cross-Site Scripting injects JavaScript that runs in other users' browsers. Reflected: the payload arrives in the request (e.g. `?q=<script>…`) and is echoed back. Stored: the payload is saved (a comment, a profile field) and served to every viewer — the most damaging. DOM-based: client-side JS writes untrusted data into the DOM (`innerHTML`). Prevention: escape output by context (HTML, attribute, JS, URL), use frameworks' auto-escaping (React escapes by default; `dangerouslySetInnerHTML` is the smell), sanitize rich input with DOMPurify, and add a Content-Security-Policy as defense in depth.
CSRF: forged requests riding on cookies
Cross-Site Request Forgery makes the victim's browser send an authenticated request to your site from a malicious page — the session cookie is attached automatically, so a hidden form can transfer money or change email. Prevention: SameSite=Lax/Strict cookies (default in modern browsers, blocks most cross-site sends), per-session anti-CSRF tokens embedded in forms and verified server-side, and verifying Origin/Referer headers. CSRF matters only for cookie-based auth — bearer tokens in headers are immune (nothing attaches them automatically).
CORS: the browser's gate, not the server's wall
CORS governs which origins' JavaScript may READ responses from your API. The browser sends `Origin`; the server answers with `Access-Control-Allow-Origin`. No header → the browser blocks the response (the request may still have executed — which is why CORS is not a security boundary). Preflight: for non-simple requests (custom headers, PUT/DELETE, JSON content type) the browser first sends OPTIONS; the server must allow the method/headers. Interview trap: 'CORS protects the server' is false — it protects the users of other websites from your API's responses.
Auth & Cryptography essentials
Hashing vs encryption, symmetric vs asymmetric, JWT structure, and the OAuth2/OIDC flow.
Hashing vs encryption
Hashing is one-way (password → digest, irreversible) and must be salted and deliberately slow: bcrypt or Argon2, never MD5/SHA-1/SHA-256 alone for passwords — fast hashes are brute-forceable, and unsalted hashes fall to rainbow tables. Encryption is two-way and reversible with a key: use it for data you must read back (tokens, PII at rest). If an interview asks 'how do you store passwords', the answer is bcrypt/Argon2 + salt — 'encrypt them' is the wrong answer.
Symmetric vs asymmetric
Symmetric (AES): one shared key, fast, used for bulk data; key distribution is the problem. Asymmetric (RSA, ECC): key pair — public key encrypts/verifies, private key decrypts/signs; slower but solves key exchange. Real systems combine them: TLS uses asymmetric crypto to agree on a session key, then symmetric AES for the actual data (TLS 1.3 drops the old RSA key exchange for (EC)DHE + signatures — forward secrecy).
JWT: three base64 parts, real security decisions
A JWT is `header.payload.signature` — base64url encoded, NOT encrypted; anyone can read the payload. The HMAC/RSA signature makes tampering detectable. Danger zones the linter below checks: `alg: none` (a historical bypass — some old libraries accepted unsigned tokens), a weak HMAC secret (offline brute force), and tokens that never expire. Store access tokens in memory, keep refresh tokens httpOnly+Secure+SameSite, and include `iss`, `exp`, `aud` validation server-side.
header: {"alg":"HS256","typ":"JWT"}
payload: {"sub":"u_123","role":"student","iat":1735000000,"exp":1735003600}
signature: HMAC-SHA256(header + "." + payload, secret)OAuth2 vs OpenID Connect
OAuth2 is authorization delegation: 'let this app act on my behalf' — access tokens, scopes. OpenID Connect is the identity layer on top: an `id_token` (a JWT) that says who the user is. The flow to know is Authorization Code + PKCE: your app sends the user to the provider, the provider authenticates them and returns a one-time code, your backend exchanges the code (with its secret) for tokens. Never use the deprecated implicit flow; never put client secrets in SPAs — PKCE exists for them.
Computer Networks in practice
The URL-to-render journey, TLS 1.3, and the port numbers every test memorizes.
| Port | Protocol | Use |
|---|---|---|
| 20/21 | FTP | File transfer (plaintext — use SFTP) |
| 22 | SSH / SFTP | Secure shell & file transfer |
| 25 / 587 | SMTP | Mail sending / submission |
| 53 | DNS | Name resolution (TCP for zone transfer) |
| 80 | HTTP | Web (redirects to 443) |
| 443 | HTTPS | Web over TLS |
| 3306 / 5432 / 1433 | MySQL / Postgres / SQL Server | Databases — never expose publicly |
| 6379 | Redis | Cache — never expose publicly |
What happens when you type https://google.com
1) Browser cache → OS resolver → recursive DNS finds the A/AAAA record (UDP 53). 2) TCP three-way handshake (SYN, SYN-ACK, ACK) to 443. 3) TLS 1.3 handshake: client sends supported ciphers + key share; server responds with certificate and its key share; both derive the same session key — 1 round trip, encrypted from then on (0-RTT for repeat visits). 4) HTTP request (GET, headers, cookies). 5) Server responds (status, headers, HTML). 6) Browser parses HTML, fetches subresources, renders. Each step has a failure mode interviewers probe: DNS failure, connection refused, TLS cert errors, 4xx/5xx semantics.
TCP vs UDP, and where each wins
TCP: connection-oriented, ordered, reliable, congestion-controlled — web, email, file transfer. UDP: connectionless datagrams, no ordering or retry — DNS lookups, video calls, gaming, QUIC (HTTP/3) is UDP-based with its own reliability and 0-RTT handshake. The interview one-liner: TCP pays latency for reliability; UDP pays reliability for latency.
HTTP status codes you must know cold
200 OK; 201 Created (Location header); 204 No Content; 301 vs 302 (permanent vs temporary redirect — SEO differs); 304 Not Modified (cache); 400 Bad Request; 401 Unauthorized (unauthenticated — bad name); 403 Forbidden (authenticated but not allowed); 404 Not Found; 409 Conflict; 429 Too Many Requests (rate limit + Retry-After); 500 server bug; 502/503/504 gateway/upstream problems.
Security headers quick reference
Content-Security-Policy restricts which sources may load scripts/styles — the strongest XSS backstop. Strict-Transport-Security (HSTS) forces HTTPS for future visits. X-Frame-Options: DENY / frame-ancestors blocks clickjacking iframes. X-Content-Type-Options: nosniff stops MIME confusion. Referrer-Policy limits URL leakage. The linter below scores a header set against these.