Security: Isolation
Lecture Notes for CS 142
Fall 2010
John Ousterhout
- Readings for this topic: none.
- The isolation problem:
- Web content comes from many sources, not all equally
trusted.
- Trusted and untrusted content are in close proximity
(frames, tabs, sequential visits).
- Must separate various forms of content so that untrusted content
cannot corrupt/misuse trusted content.
- Example: a "good" page displays a sponsored ad:
- Attackers can buy advertisements, use them to attack
good pages.
- Advertiser gets to supply content for ad (e.g. "good"
page links to advertiser site in <iframe>)
- Ad can contain <script> elements that access
DOM, submit forms, etc.
parent.frames[0].forms[0].submit;
- Even images aren't safe: browsers will accept non-image
content.
Same-Origin Policy
- General idea: separate content with different trust levels
into different frames, restrict communication between
frames.
- One frame can access content in another frame only if they
both came from the same origin. Origin =
- Protocol
- Domain name
- Port (in some browsers).
- All modern browsers implement the same-origin policy.
- Same-origin applies to AJAX requests also.
- Where same-origin doesn't apply:
- <script> tags: Javascript executes with full
privileges of the enclosing frame.
- <img> tags: may contain arbitrary HTML content.
- By itself, the same-origin policy is too restrictive: there are
times when it is useful for frames with different origins to
communicate in various ways.
- Domain relaxation:
- Consider www.facebook.com, facebook.com,
and chat.facebook.com.
- If two frames each set document.domain to the same value,
then they can communicate:
- Must be a suffix of the actual domain.
- Must explicitly set document.domain even if the value
doesn't change (e.g., chat.facebook.com vs.
facebook.com).
- New feature: Access-Control-Allow-Origin header in
HTTP responses:
- Specifies one or more domains that may access this object's DOM.
- Can use "*" to allow universal access.
- Not clear how many browsers currently support this.
- HTML5 postMessage mechanism:
- Allows frames to send messages to each other in a controlled
fashion.
- Sender (from domain a.com):
frames[0].postMessage("Hello world", "http://b.com/");
- Receiver (domain b.com) can check origin:
window.addEventListener("message", doEvent);
function doEvent(e) {
if (e.origin == "http://a.com") {
... e.data ... }
}
}
- Language-based isolation:
- Frames are too restrictive for some situations:
- Example: allow users to enter text that includes markup
- An alternative:
- Don't use frames: content from different sources intermixed.
- Analyze content before including in page:
- Don't allow some features (HTML, Javascript)
- Modify code to include additional run-time checks for
problems that can't be detected statically.
- Example: Facebook Javascript (FBJS):
- Subset of Javascript for use in Facebook applications.
- Facebook analyzes/rewrites Javascript before it gets to
your browser.
- For example:
- All identifiers get application-specific prefix to avoid
conflicts:
is changed to
function a123_foo(a123_bar)
- Can't access the DOM directly: instead of
must invoke FBJS method that enforces isolation:
element.getParentNode()...
- See
http://wiki.developers.facebook.com/index.php/FBJS for details
on FBJS.
- Language-based isolation is very tricky and prone to loopholes: beware!
Navigation
- Who is allowed to decide what content appears in a frame?
frame.src = "http://www.attack.com/";
- Original policy was permissive: any frame could navigate
any other frame.
- Guninski attack:
- Password field on Citibank Web site contained within a frame.
- Attacker could navigate this frame to an identical-looking
one owned by the attacker; steals password.
open("http://www.attack.com/citibank", "password");
- Attack can come from any open window or tab.
- Solution:
- Descendent policy: a frame can only navigate its
children, and their children, etc.
- Most current browsers implement this policy, but older
versions such as IE6 and Firefox 2 are more permissive.
Cookie Security
- Cookies can be read and written from Javascript:
alert(document.cookie);
document.cookie = "name=value; expires=1/1/2011"
- Browsers use the same-origin policy to restrict access to
cookies.