Luyện Phỏng Vấn IT — 2000+ Câu Hỏi Phỏng Vấn IT Có Đáp Án 2026

Danh mục

Bảo Mật iconBảo Mật

XSS inject malicious scripts vào browser victim — React JSX tự động escape (dangerouslySetInnerHTML vẫn nguy hiểm); dùng DOMPurify cho user HTML, HttpOnly cookies, và Content Security Policy.

  • XSS (Cross-Site Scripting) cho phép attacker inject và execute malicious scripts trong browser của victim, đánh cắp sessions, redirect users, modify page content.
  • Ba loại: Stored XSS — script được lưu trong DB (comment, profile), mỗi user xem page bị attack; Reflected XSS — script trong URL parameter, server reflect lại trong response (phishing links); DOM-based XSS — client-side code đọc từ URL/storage và inject vào DOM mà không qua server (document.location, window.location.hash → innerHTML).
  • Phòng chống: Context-appropriate encoding — HTML encode khi insert vào HTML, JS encode khi insert vào JavaScript, URL encode khi insert vào URL; React JSX tự động escape — dangerouslySetInnerHTML vẫn nguy hiểm.
  • Không dùng innerHTML với user content — dùng textContent hoặc createElement.
  • DOMPurify: sanitize HTML khi cần render user-provided HTML (rich text editor output) — DOMPurify.sanitize(userHtml).
  • Content Security Policy: block inline scripts và unauthorized external scripts — defense in depth.
  • HttpOnly cookies: JavaScript không thể đọc session cookie dù có XSS.
  • Subresource Integrity (SRI): verify CDN scripts không bị tamper — integrity attribute trên <script>.
  • Template literals và DOM APIs: const div = document.createElement('div'); div.textContent = userInput — safe; div.innerHTML = userInput — unsafe.

CSRF (Cross-Site Request Forgery) exploit việc browser tự động gửi cookies khi request đến domain — attacker tạo form/image trên evil.com gửi request đến bank.com, browser tự động attach session cookie của user.

Ví dụ: <img src='https://bank.com/transfer?to=attacker&amount=1000'> — nếu user đang logged in và bank không có CSRF protection, transfer xảy ra.

OAuth 2.0 là authorization framework — delegated authorization (không phải authentication).

Phân biệt: OAuth cho authorization (app có quyền gì), OpenID Connect (OIDC) là layer trên OAuth cho authentication (ai đang login, trả về ID token).

Authorization Code flow chi tiết:

  1. App redirect user đến Authorization Server với client_id, redirect_uri, scope, state (CSRF protection), code_challenge (PKCE);
  2. User authenticate và consent;
  3. Auth Server redirect về app với authorization code;
  4. App exchange code cho access token qua back-channel request (POST, client_secret không expose trong URL);
  5. App dùng access token để call protected APIs;
  6. Refresh token để get new access token khi expire

PKCE (Proof Key for Code Exchange): app tạo code_verifier (random string), gửi code_challenge = hash(code_verifier) trong step 1, gửi code_verifier trong step 4 — server verify hash match — ngăn authorization code interception attack, bắt buộc cho public clients (SPA, mobile).

Implicit flow: deprecated — trả access token trực tiếp trong URL, exposure risk.

Client credentials flow: machine-to-machine, không có user — backend service gọi API.

Scopes: granular permissions (read:email, write:calendar) — request chỉ scopes cần thiết.

Token storage: access token trong memory (SPA), refresh token trong HttpOnly cookie — không dùng localStorage cho sensitive tokens.

OAuth 2.1 (đang chuẩn hóa) gộp các best practices: PKCE bắt buộc cho mọi client, xóa Implicit và Resource Owner Password Credentials flows.

HTTPS là HTTP over TLS (Transport Layer Security) — encrypt toàn bộ communication, verify server identity, đảm bảo data integrity.

  • TLS handshake: Client Hello (supported cipher suites, TLS version) → Server Hello (chosen cipher, certificate) → Client verify certificate với CA (Certificate Authority) → Key exchange (ECDH — không share private key) → Session keys derived → Encrypted communication.
  • Certificate chain: leaf certificate → intermediate CA → root CA (trusted bởi browser/OS); Let's Encrypt cung cấp free certificates tự động renew.
  • HSTS (HTTP Strict Transport Security): Strict-Transport-Security: max-age=31536000; includeSubDomains — browser chỉ kết nối HTTPS trong 1 năm, ngăn SSL stripping attack; HSTS Preload list (chromium preload) — hardcoded trong browsers.
  • TLS 1.3 improvements: 1-RTT handshake (vs TLS 1.2 2-RTT), 0-RTT resumption cho subsequent connections, removed insecure cipher suites.
  • Certificate Transparency: public log của mọi issued certificate — detect unauthorized certificate issuance cho domain của bạn.
  • Mixed content: HTTPS page load HTTP resources — browsers block active mixed content (scripts, XHR), warn về passive (images).
  • Bắt buộc vì: MITM attack prevention, required cho HTTP/2 (browsers only support HTTP/2 over TLS), Service Workers, PWA, getUserMedia, required cho modern browser features; SEO ranking factor; browser 'Not Secure' warning tăng bounce rate.

Same-origin policy ngăn JavaScript từ một origin (scheme+host+port) đọc response từ origin khác — bảo vệ khỏi CSRF và data theft.

  • CORS cho phép server opt-in cho cross-origin requests qua response headers.
  • Simple requests (GET/POST với basic Content-Type) không cần preflight — browser gửi request và check response headers.
  • Preflight (OPTIONS request): cho non-simple requests (custom headers, PUT/DELETE, Content-Type: application/json) — browser gửi OPTIONS trước, server phải respond với allowed methods/headers trước khi browser gửi actual request.
  • Response headers: Access-Control-Allow-Origin: https://trusted.com (hoặc cho public APIs nhưng không thể dùng với credentials); Access-Control-Allow-Methods: GET, POST, PUT, DELETE; Access-Control-Allow-Headers: Content-Type, Authorization; Access-Control-Max-Age: 86400 (cache preflight 24h, giảm OPTIONS requests); Access-Control-Allow-Credentials: true (để gửi cookies/auth headers — phải specify exact origin, không dùng ).
  • Common mistakes: add CORS headers ở nginx nhưng app cũng trả CORS headers → duplicate headers → browser reject; thêm * nhưng cần credentials → không work; không handle OPTIONS method trong route → 405 error.
  • CORS chỉ restrict browser requests — Postman, curl, server-to-server không bị ảnh hưởng.
  • Credentials mode: fetch(url, { credentials: 'include' }) gửi cookies; cần server set Access-Control-Allow-Credentials: true và exact origin.

Security headers là server response headers kiểm soát browser behavior để prevent attacks.

  • Quan trọng nhất: Strict-Transport-Security: max-age=31536000; includeSubDomains (HSTS — force HTTPS, prevent SSL stripping, 1 năm duration); X-Content-Type-Options: nosniff (prevent MIME type sniffing — browser không tự đoán content type khác Content-Type header, ngăn polyglot file attacks); X-Frame-Options: DENY hoặc SAMEORIGIN (prevent clickjacking — page không thể được embed trong iframe của domain khác); CSP frame-ancestors thay thế X-Frame-Options và flexible hơn.
  • Referrer-Policy: no-referrer-when-downgrade (default) hoặc strict-origin-when-cross-origin — control bao nhiêu URL info gửi trong Referer header; no-referrer cho sensitive pages.
  • Permissions-Policy (thay thế Feature-Policy): kiểm soát browser APIs — Permissions-Policy: geolocation=(), camera=(), microphone=() — disable features không dùng đến.
  • X-XSS-Protection: deprecated, browsers modern tự handle — không cần set.
  • Cross-Origin-Opener-Policy: same-origin — isolate browsing context, enable SharedArrayBuffer, required cho high-resolution timers.
  • Cross-Origin-Embedder-Policy: require-corp — cùng với COOP enable process isolation.
  • Helmet.js trong Express: app.use(helmet()) tự động set tất cả headers với sensible defaults, có thể customize per-header. securityheaders.com để test và grade headers của site.

JWT stateless auth dùng signed token thay vì server-side session — không cần DB lookup mỗi request.

  • Login: verify credentials → tạo JWT (sign với secret) → gửi token cho client.
  • Request: client gửi token trong Authorization header (Bearer token).
  • Server: middleware verify token, extract user info, attach vào req.user.
  • Lưu trữ: access token → memory (JS variable), refresh token → httpOnly cookie. KHÔNG lưu localStorage (XSS risk).

Refresh token cho long-lived sessions.

OWASP Top 10 2021 (phiên bản mới nhất được áp dụng rộng rãi, 2025 edition đang ra) — A01: Broken Access Control, A03: Injection, A07: Auth Failures là ba rủi ro quan trọng nhất cho Node.js dev.

  • OWASP Top 10 là danh sách 10 rủi ro bảo mật web phổ biến nhất, cập nhật định kỳ bởi Open Web Application Security Project. A01: Broken Access Control (lên #1 từ #5) — user truy cập resources không được phép: thiếu authorization checks, IDOR (Insecure Direct Object Reference). A02: Cryptographic Failures — dữ liệu nhạy cảm không được mã hóa, dùng thuật toán yếu (MD5, SHA1 cho password). A03: Injection — SQL, NoSQL, command injection. A04: Insecure Design — thiếu threat modeling, security requirements. A05: Security Misconfiguration — default credentials, verbose errors, unnecessary features enabled. A06: Vulnerable Components — outdated dependencies với known CVEs. A07: Auth Failures — weak passwords, session fixation, no rate limiting trên login. A08: Software Integrity Failures — CI/CD pipeline không secure, unsigned packages. A09: Security Logging Failures — không log security events, không alert. A10: SSRF (Server-Side Request Forgery) — attacker khiến server fetch internal URLs.
  • Trong Node.js context: A03 (SQL injection → parameterized queries), A02 (bcrypt/argon2 thay MD5), A01 (middleware authorization), A06 (npm audit + Dependabot), A07 (rate limiting + account lockout).

Session-based dễ revoke, cần Redis cho multi-server; JWT stateless dễ scale nhưng không thể revoke trước expiry — hybrid (short-lived JWT + server-side refresh token) là best practice 2025. Session-based: server lưu session data trong memory/Redis, client chỉ lưu session ID trong cookie.

  • Server stateful — phải lookup session mỗi request.
  • Ưu điểm: dễ revoke (xóa session), không expose user data, server kiểm soát hoàn toàn.
  • Nhược điểm: cần shared session store (Redis) cho multi-server, horizontal scaling phức tạp. JWT: server stateless, client lưu toàn bộ claims trong token.
  • Không cần DB lookup để verify (chỉ verify signature).
  • Ưu điểm: stateless → dễ scale, microservices có thể verify token mà không cần centralized auth.
  • Nhược điểm: không thể revoke trước khi expire (phải dùng blacklist = stateful), token size lớn hơn session ID.
  • Decision matrix: DÙNG Session khi: cần instant revocation (admin ban user, password change → invalidate tất cả sessions), single-server hoặc đã có Redis, traditional web app với form-based auth.
  • DÙNG JWT khi: microservices (service-to-service auth), public API cho mobile apps, SSO across multiple domains, cần stateless architecture.
  • Hybrid approach: JWT cho access (short-lived, 15min) + server-side session cho refresh tokens — best of both worlds.

Pitfall: JWT không phải encryption — payload là base64, bất kỳ ai có token đều đọc được claims — không đặt sensitive data vào payload.

OWASP 2025 khuyến nghị argon2id (memory-cost=64MB, time-cost=3) là best practice; bcrypt vẫn secure với cost=12 nhưng bị truncate ở 72 bytes.

  • Cả hai đều là password hashing functions thiết kế đặc biệt để chậm — khác với SHA-256/MD5 được tối ưu để NHANH. bcrypt: battle-tested từ 1999, cost factor (saltRounds) tăng exponentially; Node.js: bcrypt.hash(password, 12). Argon2: winner Password Hashing Competition 2015, ba variants: argon2d (GPU resistant), argon2i (side-channel resistant), argon2id (cả hai — recommended).
  • Tham số: memory-cost (RAM, default 64MB), time-cost (iterations), parallelism.
  • Node.js: argon2.hash(password) với argon2.argon2id variant.
  • So sánh: Argon2id resistant với GPU attacks và side-channel attacks tốt hơn bcrypt; OWASP khuyến nghị argon2id (memory-cost=64MB, time-cost=3, parallelism=4). bcrypt giới hạn 72 bytes input (passwords dài hơn bị truncate — security issue); argon2 không có giới hạn.
  • Thực tế 2025: argon2id là best practice mới, bcrypt vẫn secure nếu cost đủ cao và không có passwords >72 bytes.
  • Migration: hash mới bằng argon2id khi user login (verify với bcrypt, rehash với argon2id, save mới) — zero downtime migration.

Pitfall: await bcrypt.hash(password, 10) trong test CI sẽ slow down tests đáng kể — dùng bcrypt.hash(password, 1) hoặc mock trong unit tests.

Token bucket cho phép bursts; sliding window không có burst issue của fixed window; dùng Redis-based implementation (Upstash) cho distributed deployment — in-memory rate limiter chỉ work trên single instance.

  • Rate limiting ngăn abuse, brute-force, DoS. Fixed window: đếm requests trong window cố định (ví dụ 0:00-0:59, 1:00-1:59).
  • Dễ implement, dễ bypass: gửi 100 req cuối window cũ + 100 req đầu window mới = 200 req trong 2 giây. Sliding window: track timestamps của requests trong rolling time window — không có burst issue của fixed window; cần store per-user timestamps trong Redis (sorted set). ZADD key timestamp timestamp; ZREMRANGEBYSCORE key 0 (now-window); ZCARD key để đếm requests. Token bucket: user có bucket tokens, mỗi request tiêu 1 token, tokens được refill theo rate (1 token/giây).
  • Cho phép short bursts (bucket full = burst capacity) nhưng sustainable rate bị limit. Leaky bucket: requests vào queue, xử lý ở fixed rate — smooth output không có bursts; tốt cho APIs cần predictable throughput.
  • Implementation: @upstash/ratelimit (Redis-based, serverless-friendly); express-rate-limit (in-memory mặc định, rate-limit-redis cho distributed); ioredis + custom script.
  • Differentiated limits: /api/auth/login (5 req/15min per IP), /api/* (100 req/min per user), public endpoints (1000 req/min).

Pitfall: in-memory rate limiter không work trong multi-instance deployment — mỗi instance có counter riêng, limit thực tế là n×limit.

Clickjacking embed site trong invisible iframe để đánh lừa user click — fix bằng Content-Security-Policy: frame-ancestors 'none' (CSP, recommended) và X-Frame-Options: DENY (legacy, set cả hai để backward compatibility).

Clickjacking là attack embed target site trong invisible iframe, user nghĩ đang click button trên trang của attacker nhưng thực ra đang click element trong iframe — thực hiện actions trên target site mà user không biết. Ví dụ: evil.com embed bank.com trong iframe với opacity: 0, vị trí button 'Transfer Money' trùng với button 'Click to win!' của evil.com. X-Frame-Options header (legacy): X-Frame-Options: DENY — không cho phép embed trong bất kỳ iframe nào; X-Frame-Options: SAMEORIGIN — chỉ cho phép same origin iframe. CSP frame-ancestors directive (modern, recommended): Content-Security-Policy: frame-ancestors 'none' (tương đương DENY); frame-ancestors 'self' (tương đương SAMEORIGIN); frame-ancestors https://trusted.com — flexible hơn X-Frame-Options (cho phép specific origins). Nên set cả hai để backward compatibility. Helmet.js: helmet.frameguard({ action: 'deny' }) set X-Frame-Options; config CSP riêng với frame-ancestors. Khi nào cho phép iframe: legitimate embedding (payment widgets, video player, maps) — whitelist specific origins với frame-ancestors. Pitfall: nếu cần embed legitimate content từ site của bạn vào third-party (widget, badge), phải loại trừ endpoint đó khỏi frame-ancestors restrictions hoặc dùng SAMEORIGIN.