CS253 Lecture Summaries: Part V: Exceptions to Same Origin Policy
Why does google put )]}'
at the beginning of their API responses? Let’s find out.
Hardening the Same Origin Policy
Can we prevent a site from linking to our site?
Why do this? One reason reputation - prevent a sketchy site linking to me.
We can’t really stop them including the link, but could we stop the request when the link is clicked? We could check the Referer.
But a site can configure whether the Referer header is sent, there are options:
Referrer-Policy: unsafe-url
send the full url of the referrer (used to be default)
Referrer-Policy: no-referrer
Never send Referer
header
Referrer-Policy: no-referrer-when-downgrade
(default) send full url but when http downgrade happens send nothing
Referrer-Policy: origin
send origin not full url
Referrer-Policy: origin-when-cross-origin
Same origin: send full url. Cross origin: send origin.
Referrer-Policy: same-origin
Same origin: send full. Cross origin: send nothing
Referrer-Policy: strict-origin
Send origin, when http downgrade, send nothing.
Referrer-Policy: strict-origin-when-cross-origin
Same origin: send full. Cross origin: send origin. http downgrade, send nothing.
So it’s hard to prevent linking if the site is hiding the referrer.
Can we prevent a site from embedding our site?
Why do this? Prevent clickjacking attacks: attacker embeds our site in an iframe, as a transparent overlay on their own site. User clicks on our site, thinking it’s on theirs.
How do we do it? Early approach - JS detection - check if we are framed via JavaScript.
The idea was to use the window.top
property, which should be the top level frame, like this:
if (window.top.location != window.location) {
window.top.location = window.location
}
But don’t do this. It’s really easy to break - a top level site can check if it’s about to be unloaded and intercept. See the Busting Frame Busting paper by Boneh et al.
Now we have a way to do this with the X-Frame-Options
header:
if not specified (default) any page can display in an iframe
X-Frame-Options: deny
page can not be displayed in a frame.X-Frame-Options: sameorigin
page can be displayed in a frame on the same origin.
Note that this relies on the browser processing the header correctly, you’re trusting the browser for your security. But coverage here is good.
Can we prevent a site from submitting a form to our site?
Why do this? Prevent CSRF.
How we do this? Detect Origin header, use an allowlist.
SameSite cookies.
Can we prevent a site from embedding images from our site?
Why do this? Prevent hotlinking, prevent logged-in avatar from showing up on other sites.
We could detect referer, but not foolproof. We could use SameSite cookies to block auth cookies.
Can we prevent a site from embedding scripts?
Why do this? Prevent hotlinking
Scripts do not contain private user data notably, and note the script will run in the context of the embedding site.
How do we do it? Can detect referer, but not reliable.
Relaxing the Same Origin Policy
Can we allow Site A to read data from site B?
Yes with the postMessage
API. What about arbitrary non-HTML resources, eg JSON?
Site A wants to read some data from Site B’s API like this: const res = await fetch('https://site-b.com/api/date')
etc…
By default this would be denied since they are different origins. We need some way for site B to specify that this response can be read.
Ideally HTTP response could specify an HTTP header indicating that reading this data is allowed. Can we do it without an HTTP header?
There is a method, we can use JSON with padding (JSONP) which looks like this:
<!-- define a callback -->
<script>
function handleTime (data) {
//
}
</script>
<!-- now call the api in a script tag, passing it the name of the callback -->
<script src='https://site-b.com/api/date?callback=handleTime'></script>
<!-- response will look like this: handleTime({"date": 12535151}) -->
Downsides of this - from the server side you need to write additional code to support cross origin requests. It needs to be careful - some JSON strings are not valid JS (eg whitespace issues).
Need to sanitize user provided callback argument - see reflected file download attack.
Problem from the other site’s perspective - they just want some data but now they have to embed and run arbitrary JS. Oh dear!