Goal: A fundamentally secure foundation for Web Apps that runs in existing browsers and is usable by non security-experts.
Rewrites JavaScript/HTML/CSS
Enforces Object-Capabilities
Gadget writers use familiar tools
Other approaches: ADSafe, FBJS, Jacaranda, SES
Visual Basic for Apps — documents can do anything the viewer can do.
The web — pages from the same-origin can interact.
Social Networks — use proxies and x-site <script>s to duck the same-origin policy.
Caja — Replaces same-origin policy with an object-capabilities model.
Gadget can't interfere with the container
Nor with other gadgets
But mutually suspicious gadgets can cooperate
And can be safely given user data
With restrictions
Not security experts
Familiar with web technologies
Comfortable with acronyms: JS, HTML, CSS, PHP
Have specific domain knowledge that C.S. generalists lack
location = '//evil.com/';
→IMPORTS___.location = '//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.
Two cooperating gadgets:
Displays a search form and uses a search engine provided by the container to fetch and display results.
When a search result is clicked on, displays pictures of cute kittens using the search engine supplied by the container.
<script src="searchbox.js"></script> <link rel=stylesheet href="searchbox.css" /> <form> <input type=text size=60 name=q> <input type=button value=Search onclick="doSearch(this)"> </form>
Javascript from script and onclick extracted and sanitized. HTML → javascript:
IMPORTS___.htmlEmitter___.p('form') .a('onsubmit', 'return false') .ih(' <input type="text" size="60" name="q">\n' + ' <input type="button" value="Search"' + ' onclick="return plugin_dispatchEvent___(…)">\n') .e('form');
Similarly for CSS from link, and style.
To prevent CSS styles interfering, classes, ids, and CSS rules are rewritten, and styles are rewritten:
/* searchbox.css */
.results li { list-style-type: none; margin-top: .5em;
border-bottom: 1px dotted #888 }
↓
/* searchbox-cajoled.css */
.searchbox___ .results li {
list-style-type: none;
margin-top: .5em;
border-bottom: 1px dotted #888
}
Now the rule only affect DOM sub-trees with class
.searchbox___
. The real class-name is generated at
runtime so that a compiled gadget can be cached.
Global references rewritten, and libraries are "tamed".
// Gadget Javascript document.getElementById('foo')↓
// Cajoled Javascript
___.loadModule(function (IMPORTS___) {
IMPORTS___.document…
})
When the gadget asks for the node with id foo
we
substitute a "tamed" version of the DOM element with id
foo-searchbox___.
<!-- Cajoled HTML from the searchbox gadget will end up here --> <div id="base-searchbox___" class="searchbox___"/> … <script type="text/javascript"> // Create a fake "Global" object for the gadget var searchBoxImports = ___.copy(___.sharedImports); // Create the fake document object. attachDocumentStubs( '-searchbox___', urlRewriter, searchBoxImports); searchBoxImports.htmlEmitter___ = new HtmlEmitter( document.getElementById('base-searchBox___')); </script> <!-- Load the gadget JS --> <script type="text/javascript" src="searchbox.co.js"/>
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;
The searchBoxImports
is the fake "global" scope
created for that gadget, so
searchBoxImports.searchEngine
is available to the
gadget as searchEngine
.
Now the Gadgets can search the web.
Old: untrusted code from a different origin. Collaboration is hard.
New: different pieces of code from same origin. Don't trust each other. Collaborate via normal object passing and method calls.
An O.C. Language is an OO language that ensures:
Separation of Duties | → | Separation of Authority |
Information hiding | → | Encapsulation |
Message Passing | → | Authorization |
Dependency Injection | → | Authority Injection |
POLA (Principle of Least Authority) |
Static policies require blanket rules. O.C. allows exemption by granting references.
A policy, safe HTML, can be enforced by a sanitizer function that returns an HTML capability. But an exemption can be made for HTML from a trusted source by passing in a reference to an HTML capability.
Independent of authentication and identity issues.
(http://tinyurl.com/2xr5t8)
Make sure that bugs come to you before they become exploits
Provide a sandbox for attackers to play in, and watch it.
If someone thinks of an attack they should be able to quickly try it where noone is hurt
Understand attackers' incentives; Publishing Rights, Recognition, Swag, Money; and play to them.
Testing is an Adversarial Process
Developing in the open makes it easy to consult security academics.
Involve standards bodies and well known developers — Brendan Eich, John Resign, etc.
Invite attack from as many as possible.
Start off using existing methods so you're no worse off than before.
As people gain confidence, they will knock out unnecessary crutches.
Language Specification Mostly Stable
Cajoler Implemented
Prototype Tamed DOM
Integrated w/ Shindig (soon w/ iGoogle & Orkut) and successfully Cajoled and run third-party gadgets
Prototype Debugging (Firebug) and IDE (Eclipse) support
Started Penetration Testing
Started Runtime Optimizations — removing unnecessary runtime checks
1 Team Member on the EcmaScript committee, 2 on Secure EcmaScript