Durable Objects
May 24, 2008 at 3:13 pm by Douglas Crockford | In Development |Cooperating applications, such as mashups, must be able to exchange objects
with robust interfaces. An object must be able to encapsulate its state such
that the state can be modified only as permitted by its own methods.
JavaScript’s objects are soft and currently the language does not include any
means to harden them, so an attacker can easily access the fields directly and
replace the methods with his own.
Fortunately, JavaScript provides the means to construct durable objects
that can perfectly guard their state by using a variation of the Module Pattern.
You’ll recall that the Module Pattern makes it possible to make an object
with privileged methods. Privileged methods are able to access the private
state of the constructor’s closure. By adding one simple rule, we can easily
generate secure objects:
A durable object contains no visible data members, and its methods use neither
thisnorthat.
This is a template for a durable constructor:
function durable(parameters) {
var that = {} or the product of another durable constructor;
var private variables;
function method() {
…
}
that.method = method;
return that;
}
Define all of your methods as private methods. The methods you choose to
expose to the public get copied into that. None of the functions defined or
inherited make use of that or this.
We can give the object created by the durable constructor to untrusted code.
That code will be unable to get direct access to the private state. It can
replace the methods with its own methods, but that only reduces the usefulness
of the object to the attacker. It does not weaken or confuse the object. Each method is a capability. The object is just a collection of capabilities.
Durable objects allow code from multiple (possibly untrusted) parties to
cooperate. Durable objects can be expressed in a safe subset of JavaScript,
such as ADsafe or Cajita.
Share and extend: Bookmark with Yahoo! My Web | Bookmark with del.icio.us | digg it! | reddit!
11 Comments »
RSS feed for comments on this post. TrackBack URI
Leave a comment

Copyright © 2007 Yahoo! Inc. All rights reserved. Privacy Policy - Terms of Service
Powered by WordPress on Yahoo! Web Hosting.
I don’t think this pattern alone is enough to ensure privacy. I don’t think privacy can every be complete.
Here is an idea for one hack off the top of my head that worked in Firefox.
<script type=”text/javascript”>
function durable() {
var that = {};
var a = 25;
return that;
}
</script>
<script type=”text/javascript”>
var foo = durable();
console.log(foo.a); // undefined
</script>
<script type=”text/javascript”>
var scripts = document.getElementsByTagName(’script’);
for (var i=0, ilen=scripts.length; i<ilen; i++) {
var script = scripts[i];
var code = script.innerHTML;
if (code.match(/return that/)) {
setTimeout(code.replace(/return that/, “that.a = a;return that”), 10);
}
}
</script>
<script type=”text/javascript”>
window.onload = function() {
var foo = durable();
console.log(foo.a); // 25
};
</script>
Another example is if the script that a hacker wants to exploit is available through XHR (i.e. same origin) then the hacker could obtain the script content through XHR instead of innerHTML like in the above example.
Comment by Peter Michaux — May 24, 2008 #
Nifty idea! Thanks Douglas.
In addition to the no “this or that” rule, it’s also important to use global variables carefully, especially methods in the standard library. A silly example:
function durable(params) {
var that = {};
var secret = {"a":"b"};
function method() {var x=[]; x.push(secret);}
that.method = method;
return that;
}
A consumer of the durable object could gain access to the private “secret” variable by overriding Array/push:
var y = new durable(),
evil;
Array.prototype.push = function(x) {evil=x;}
y.method(); // evil now points to secret!
In addition, one has to be careful with return values. If you return a reference to a private variable the consumer code can then trivially manipulate that variable. Using the previous example, if durable/method simply returned secret an attacker could then do something like this:
var y = new durable();
var evil = y.method(); // evil now points to secret
The avoid this problem, always return values or references to method variables (as opposed to private class variables). If you do need to return private class variables, duplicate them first and return the copy.
Comment by Joey Hurst — May 24, 2008 #
The Kerckhoffs’s Principle tells us that we should not be putting secrets in the source of the programs, and we should not be inconvenienced by the enemy reading the source of our programs.
Comment by Douglas Crockford — May 25, 2008 #
Peter,
Your security cannot depend on your global variables if the attacker has access to your global variables, including your global functions and constructors. An attacker can trivially replace your functions with his.
Try your attack under ADsafe. The attacker does not get access to your global durable function. The attacker does not get access to the DOM so he cannot examine the script tags. The attacker does get access to the ADSAFE object which could contain functions that facilitate interwidget communication, including the exchange of durable objects.
Comment by Douglas Crockford — May 25, 2008 #
Douglas: Thanks for the reply.
Re Kerckhoffs’ Principle: definitely agree.
I should have chosen the variable name “secret” more carefully, perhaps calling it “private,” or simply “state.” The point was that one has to be careful not to expose references to private variables by one means or another, as this will allow a third party to manipulate the durable object’s state directly. As you mentioned, projects like Caja and ADSafe can address (pun intended) these additional concerns.
Comment by Joey Hurst — May 25, 2008 #
Is there any mechanism for protecting private methods defined on the prototype of an object?
Comment by Simon — May 25, 2008 #
There are no private methods in the prototype. All members, including all methods, are public.
Comment by Douglas Crockford — May 25, 2008 #
Douglas,
What exactly is the difference between what you outlined in the original article, specifically returning “that”, and doing this?
var Durable = function() {
var a = 2;
var b = 4;
this.getA = function() {
return a;
}
this.getB = function() {
return b;
}
}
TIA,
Billy
Comment by Billy Reisinger — May 28, 2008 #
But what about inheritance? How would you inherit properties/methods from another “durable” object?
Comment by Rytis Daugirdas — May 28, 2008 #
I agree with Billy, what is the difference between what you propose and instantiating an instance of a constructor with private members?
Comment by James Norton — May 29, 2008 #
Billy,
Suppose you have a method C that calls this.A and this.B. If an attacker replaces your methods with his, then C will be compromised. Function C would be vulnerable if it used this.
Rytis,
Inheritance is obtained by calling another durable constructor.
var that = another_constructor();
Comment by Douglas Crockford — June 2, 2008 #