Traditional way to include third-party "rich" content:
Escape it (and thus disable active content)
Example: Webmail
Introduce a new syntax
Example: Wiki
Whitelist some active tags
Example: Blog comments
Host it on a different domain and display it in an IFrame
Example: Social networking sites
* The traditional way to do sandboxing was using iframes hosted on a different domain
- these have a lot of shortcomings
- iframes are rectangular
- there's limited ability to co-operate between gadgets
- they don't actually work either
* Defensive code problem
- shared global namespace
* HTTP-Only cookies are not needed
Mashups
Traditional way to include third-party "rich" content:
Escape it (and thus disable active content)
Example: Webmail
Introduce a new syntax
Example: Wiki
Whitelist some active tags
Example: Blog comments
Host it on a different domain and display it in an IFrame
Example: Social networking sites
Ignore the problem and hope
Mashups
Traditional way to include third-party "rich" content:
Escape it (and thus disable active content)
Example: Webmail
Introduce a new syntax
Example: Wiki
Whitelist some active tags
Example: Blog comments
Host it on a different domain and display it in an IFrame
Example: Social networking sites
* The traditional way to do sandboxing was using iframes hosted on a different domain
- these have a lot of shortcomings
- iframes are rectangular
- there's limited ability to co-operate between gadgets
- they don't actually work either
* Defensive code problem
- shared global namespace
LOLcat Search
Two cooperating gadgets:
Searchbox
Displays a search form and uses a search engine provided by the
container to fetch and display results.
Kittens
When a search result is clicked on, displays pictures of cute
kittens using the search engine supplied by the container.
LOLcat Search
Example Attack: Redirection
top.location = "http://www.thinkfu.com/evil.gif";
Any third party code you load can redirect the container page to a malicious site
You want to allow gadgets in your page but browsers allow any gadget
(including one that is in an iframe) to access and navigate the
browser window. For example, a gadget can redirect the container
to a phishing site to steal your password.
Caja does not enforce a policy of its own. Instead it gives
containers stricter control over a gadget can do. For example, it
allows the container to decide whether a gadget can read or set
variables such as top.location. A careful choice of
policy allows a container to protect its users from being unwittingly
redirected to phishing and malware sites.
Example Attack: History Sniffing
.co
var computedStyle = document.defaultView.getComputedStyle(link, null);
var computedColor = computedStyle.getPropertyValue('color');
var visited = computedColor == 'rgb(0, 0, 0)' ? "Yes!" : "Unknown";
Browsers style visited links differently from unvisited links
Gadgets can create links and see what style is applied on it
They can phone this information home
When you visit a website, your browser helpfully colors links to that
site with a different color. Unfortunately a malicious gadget can use
this computed style to detect if you have visited particular sites.
In this way, a malicious gadget try to determine your gender, your
news tastes, your political leaning, the name of your bank and other
sensitive information by analyzing the sites you visit.
By default Caja protects users against such leakage of information by
not granting access to computed styles.
Gadgets can read and set cookies of the container or other gadgets hosted on the same domain
You want to inline gadgets in your page but you don't want it to steal
your viewer's cookies. In this example, you can see if a gadget you
use sets cookies and if a malicious gadget can access it.
Caja disallows access to any variable which the container does not
explicitly grant a gadget access to. Unless a container explicitly
grants a gadget access to your cookies, a gadget is unable to access
it.
Example Attack: Script Injection
var blogComment = document.createElement('div');
blogComment.innerHTML = document.getElementById('submittedComment').value;
document.getElementById("comments").appendChild(blogComment);
Manipulating the DOM with poorly sanitized content can result in XSS
You want to allow a user to enter comments in your blog using HTML but
you don't want them to be able to enter scripts which steal cookies of
other readers of your blog. In this example, user input is being
assigned directly to innerHTML. On some browsers this has no effect
but on IE, this will result in the embedded script being executed.
Caja prevents such attacks by sanitizing strings before inserting them into the DOM.
There are regularly circumstances where you want to embed third
party code in your application. The most obvious cases are in
social networks like Orkut, Facebook, iGoogle, YAP.
But many of you as developers of other applications, as authors of
blogs, of wikis, of applications where you want javascript
plugins, and of applications that display ads, you regularly need
to allow third party gadgets to be embedded in your application.
Caja — Securing WebApps
A principled secure framework for mashups that runs
in existing browsers and is usable by non security-experts.
Allows the container to enforce a how gadgets interact with each other and with the container
Goals
Offensive Code Problem
A gadget can't interfere with the container
Gadgets can't interfere with other gadgets
Legacy Tools Problem
Existing tools can be easily adapted to support the language
Legacy Code Problem
Existing code can be easily adapted to work with the language
Defensive Code Problem
Mutually suspicious gadgets can cooperate
* More general than gadgets
- any third party code should not interfere
-
Co-operating Gadgets
Caja allows the container to introduce two gadgets to each other directly.
var searchEngine = new SearchEngine();
// Provide both modules an interface to AJAX Search APIs.
searchBoxImports.searchEngine = kittensImports.searchEngine = searchEngine;
// Allow searchBoxImports to talk to kittens.
searchBoxImports.resultConsumer = kittensImports.showKitten;
What problems could arise from doing so in javascript?
Source Code Rewriting
location = 'http://evil.com/';
↓
IMPORTS___.location = 'http://evil.com/';
Globals rewritten to point to a per-gadget object. Authority not "ambiently" available.
document.createElement('script');
↓
IMPORTS___.document.createElement('script');
"Tamed" document object looks, smells, and tastes like the real DOM, but can whitelist elements and rewrite attributes.
Source Code Rewriting
Unfortunately closed functions are not enough
eval allows a third-party gadget to magically create a reference to an object it has not been passed
var global = eval("window");
global.location = "http://www.google.com";
The semantics of this has unusual semantics allowing a function to magically create a reference to the window object
var that = (function() { return this; })();
that.location = "http://www.google.com";
Assortment of javascript and DOM features which have a global effect
Object-Capabilities Build on Good Software Development Practices
Separation of Duties
→
Separation of Authority
Information hiding
→
Encapsulation
Message Passing
→
Authorization
Dependency Injection
→
Authority Injection
↓ POLA (Principle of Least Authority)
Cajita: Remove the knives from javascript
Removes from javascript
eval
with
this
variable deletion
Complicated coercing rules surrounding == and !=
Adds to javascript
cajita.freeze
immutable objects
Interoperates well with existing browser api
A decent language to program in!
Offensive Code Problem ✓
Legacy Tools Problem ✓
Defensive Code Problem ✓
Legacy Code Problem
Valija: Add toy knives right back in again
Solving All Four Goals In One Step Is Hard
Instead solve in steps
Make the target language cajita
Take advantage of the security guarantees
Implement the lost functionality of javascript in cajita
Time of check vs time of use
Eich: not sure if rewriting systems make sense - probably don't want rewriting rules so much
SES: Secure ecmascript
Venkat delivery via dom api
URI Rewriting
Content is brought into a browser via URI names
Caja rewrites URIs according to a policy
If you can't trust the browser, rewrite URIs use a proxy that gives you that trust