Re: Security and direct proxies (Was: Re: Lecture series on SES and capability-based security by Mark Miller)

2011-11-09 Thread Andreas Rossberg
On 9 November 2011 00:16, Mark S. Miller erig...@google.com wrote:
 On Tue, Nov 8, 2011 at 12:50 PM, Andreas Rossberg rossb...@google.com
 wrote:

 On 8 November 2011 20:46, Mark S. Miller erig...@google.com wrote:
  Nevertheless, I see your point. Many defensive ES5 abstractions will be
  less
  defensive than this. If I understand you correctly, your point is
  specifically about the [[Call]] and [[Construct]] traps.

 Yes. Existing code has no reason to bother making functions
 non-extensible if all it does is calling them. Proxy.attach
 fundamentally breaks that (so far correct, AFAICT) assumption.

 I think we're agreeing on the operational point -- that much defensive code
 won't bother to freeze such functions. But for clarity, I must correct your
 no reason. The reason is one of the oldest software engineering best
 practices: Say What You Mean. Perhaps a clearer statement is Mean Only What
 You Say. The it in your above sentence presumes a non-local whole program
 analysis which violates this rule, and is in any case inapplicable to
 libraries.
 To keep what the program means in sync with what it seems to mean, we need
 to avoid introducing unexpressed communication channels. Or, put another
 way, unexpressed shared mutable locations. If Alice provides object C to
 both B and D, the only ways in which this should enable further
 communication between B and D (beyond that which they may have already had)
 should be according to the expressed behavior of C. For example, if the
 expressed behavior of C is completely stateless, then the fact that B and D
 both share a reference to C should not enable any additional
 communications/interaction/influence between B and D.
 These constraints are useful for much beyond security. If you wish to
 program in a mostly functional style, you'd like the deviations from
 functional style to only be where you've made a purposeful choice. When
 debugging, you need to figure out: How did the bad symptom happen? If you
 can bound the possible causes, by reasoning in terms of the program's
 intended behavior, your detective work is much easier.

Agreed with everything you say. But I suppose there are two levels of
concern: protecting your own abstractions, and not providing security
loopholes that others can exploit to harm third parties.  Given how
hostile JS is towards encouraging the latter, I would expect that a
significant amount of code exists that only cares about the former,
which I think is a valid concern on its own.

/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Security and direct proxies (Was: Re: Lecture series on SES and capability-based security by Mark Miller)

2011-11-09 Thread Sam Tobin-Hochstadt
On Tue, Nov 8, 2011 at 4:58 PM, Tom Van Cutsem tomvc...@gmail.com wrote:
  Perhaps we should
  be more conservative here, without necessarily backing away from the
  whole
  Proxy.attach idea?

 Disallowing attaching to functions with your own call/construct traps
 would be the minimal restriction, I think. But maybe there is
 something cleaner.

 I wonder if chaperones, as implemented in Racket, would be of help here. To
 my understanding, a chaperone is a proxy that is very restricted in its
 actions, specifically: when intercepting a function call, a chaperone is
 only allowed to throw an exception, return the original value, or a
 chaperone for the original value (racketeers on this list should correct me
 where needed).

 Chaperones would still be powerful enough to express data binding: firing an
 update event as a side-effect does not require changing the arguments or
 return values of wrapped functions.

 However, at this point I'm not yet sufficiently familiar with chaperones to
 see how they can be adapted into our Proxy framework.

That's a very accurate summary.  I agree with Andreas that this is a
significant risk for Proxy.attach.  ES in the wild has few enough
invariants that we should be very wary of breaking the ones we've got.

However, the direct proxy proposal is already enforcing some
invariants -- the proxy must produce === values to the underlying
object for frozen properties.  Could we just reuse this mechanism for
the [[Call]] and [[Construct]] behavior of functions in the cases
Andreas brings up for Proxy.attach (if we decide that we want it)?

The idea of chaperones would be then relaxing this invariant slightly,
to allow frozen properties to produce proxies for the underlying
property value, instead of just something === to it.  This makes
proxies more expressive in some cases, without reducing the invariants
we can rely on.
-- 
sam th
sa...@ccs.neu.edu
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Security and direct proxies (Was: Re: Lecture series on SES and capability-based security by Mark Miller)

2011-11-08 Thread David Bruant
Le 08/11/2011 14:26, Andreas Rossberg a écrit :
 On 3 November 2011 23:55, Mark S. Miller erig...@google.com wrote:
 If I understood Mark correctly, the features needed for SES are
 already part of ES.5 and are shipping in browsers

 (and hence don't bear upon future features).  Did I misunderstand?
 These do bear on future features in three ways:

 1) Future features could easily destroy all the security gains that ES5
 achieved.
 I'm still trying to grasp the implications of the recent direct proxy
 proposal in this respect -- more precisely, its startTrapping
 functionality.
Just as a reminder, startTrapping really is not necessary to direct
proxies (Proxy.for) and should both should be considered independently
(even though they are on the same strawman)

 It seems to me that the ability to attach to a function, in
 particular, invalidates all current security guarantees, since it
 gives a whole new way of completely redefining any random function _in
 place_ by simply turning it into a function proxy. That is, even if
 that function is given by a non-writable binding or property!
Given that direct proxies are not in a position to violate any of the
*non-configurability or non-extensibility constraints* of their wrapped
target, it should be safe to replace an existing normal object by a
direct proxy wrapping that object.
My understanding is that regarding the issue you mention, you cannot do
more with startTrapping than redefining built-ins by (re)setting a property.
Though, I agree about the non-writable binding. Something should be
added about that.
And it seems so much safer to prevent start trapping the global object
because things could get nasty otherwise.


 To achieve the effect of today's Object.{seal,freeze}, you hence also
 would have to make _every_ of the object's properties non-attachable.
 That is certainly possible, but seems considerably more fragile.And
 it still breaks the security of pre-existing SES code. IOW, I sense a
 security hazard.
I agree that there is a hazard but I am not sure it is that much bigger
than the opportunity for an attacker to redefine built-ins. This
opportunity exists since the origin of JavaScript (so before ES5 and SES).


 I also wonder about the effect that turning an (ordinary) object into
 a proxy would have on the visibility of private names. If one of the
 original methods accesses a private property on `this', then,
 according to the private names proposal, the handler only gets to see
 the .public property of that name. But can't this still leak
 information? The handler cannot use it to _read_ the existing property
 data, but it will still receive all future _writes_ to it.

 Am I missing something?
I don't think you are. I think you are right.
As said, the startTrapping proposal is controversial. Proxies are still
very new. I'm not sure it's wise to add the startTrapping.
If we ever realize that this is really needed, i don't think there is a
problem with adding it in a later ECMAScript version.

David
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Security and direct proxies (Was: Re: Lecture series on SES and capability-based security by Mark Miller)

2011-11-08 Thread Mark S. Miller
On Tue, Nov 8, 2011 at 5:26 AM, Andreas Rossberg rossb...@google.comwrote:

 On 3 November 2011 23:55, Mark S. Miller erig...@google.com wrote:
  If I understood Mark correctly, the features needed for SES are
  already part of ES.5 and are shipping in browsers
 
  (and hence don't bear upon future features).  Did I misunderstand?
 
  These do bear on future features in three ways:
 
  1) Future features could easily destroy all the security gains that ES5
  achieved.

 I'm still trying to grasp the implications of the recent direct proxy
 proposal in this respect -- more precisely, its startTrapping
 functionality.

 It seems to me that the ability to attach to a function, in
 particular, invalidates all current security guarantees, since it
 gives a whole new way of completely redefining any random function _in
 place_ by simply turning it into a function proxy. That is, even if
 that function is given by a non-writable binding or property!

 To achieve the effect of today's Object.{seal,freeze}, you hence also
 would have to make _every_ of the object's properties non-attachable.
 That is certainly possible, but seems considerably more fragile. And
 it still breaks the security of pre-existing SES code. IOW, I sense a
 security hazard.


Hi Andreas, thanks for starting a discussion on this. I agree that there is
a huge danger here. There is another approach to so-called data binding
(treat it like an optimization of polling) that cannot cause any loss of
security (if equivalence to polling really is maintained). Altogether, from
a security pov, we'd certainly be better off without Proxy.attach.

The reason Proxy.attach may not be fatal is that it only allows attachment
to extensible objects. Our hypothesis is that any ES5 object that is
interested in defending itself has already made itself non-extensible. This
is why we must key this off of non-extensibility, rather than introducing a
new orthogonal bit -- to avoid breaching the defenses of those ES5 era
objects that tried to defend themselves. ES3 era objects could not defend
themselves, so attaching to them cannot violate any of their valid
assumptions -- to a first approximation, they could not validly assume
anything.




 I also wonder about the effect that turning an (ordinary) object into
 a proxy would have on the visibility of private names. If one of the
 original methods accesses a private property on `this', then,
 according to the private names proposal, the handler only gets to see
 the .public property of that name. But can't this still leak
 information? The handler cannot use it to _read_ the existing property
 data, but it will still receive all future _writes_ to it.

 Am I missing something?


Only the defensiveness points above. Regarding data binding, we should also
see if the non-dangerous poll-optimization-equivalence can meet our needs
instead, in which case we probably don't need Proxy.attach.




 /Andreas




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Security and direct proxies (Was: Re: Lecture series on SES and capability-based security by Mark Miller)

2011-11-08 Thread Andreas Rossberg
On 8 November 2011 18:47, David Bruant bruan...@gmail.com wrote:
 Given that direct proxies are not in a position to violate any of the
 *non-configurability or non-extensibility constraints* of their wrapped
 target, it should be safe to replace an existing normal object by a
 direct proxy wrapping that object.
 My understanding is that regarding the issue you mention, you cannot do
 more with startTrapping than redefining built-ins by (re)setting a property.

That may be true for plain objects, but I think the situation is quite
different for functions, because there is no equivalent to
non-configurable for the [[Call]] and [[Construct]] properties.


On 8 November 2011 19:13, Mark S. Miller erig...@google.com wrote:
 The reason Proxy.attach may not be fatal is that it only allows attachment
 to extensible objects. Our hypothesis is that any ES5 object that is
 interested in defending itself has already made itself non-extensible. This
 is why we must key this off of non-extensibility, rather than introducing a
 new orthogonal bit -- to avoid breaching the defenses of those ES5 era
 objects that tried to defend themselves.

I don't think that addresses the issue I was describing. The problem
is: the object itself can all be frozen, non-extensible,
non-attachable just fine, but that doesn't achieve much by itself
anymore because an attacker can still attach to each individual
method, since they are entirely separate objects!

So instead of just freezing an object, you _additionally_ would have
to make all its _individual methods_ non-attachable (by whatever
means). AFAICS, that affects assumptions of existing ES5 code quite
severely.

/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Security and direct proxies (Was: Re: Lecture series on SES and capability-based security by Mark Miller)

2011-11-08 Thread Andreas Rossberg
On 8 November 2011 20:29, Andreas Rossberg rossb...@google.com wrote:
 On 8 November 2011 18:47, David Bruant bruan...@gmail.com wrote:
 Given that direct proxies are not in a position to violate any of the
 *non-configurability or non-extensibility constraints* of their wrapped
 target, it should be safe to replace an existing normal object by a
 direct proxy wrapping that object.
 My understanding is that regarding the issue you mention, you cannot do
 more with startTrapping than redefining built-ins by (re)setting a property.

 That may be true for plain objects, but I think the situation is quite
 different for functions, because there is no equivalent to
 non-configurable for the [[Call]] and [[Construct]] properties.

BTW, a similar issue applies to getters and setters: even if a
property is non-configurable, as long as it is defined by accessors an
attacker could attach to the underlying JS functions and thereby
essentially redefine the property without actually modifying it.

/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Security and direct proxies (Was: Re: Lecture series on SES and capability-based security by Mark Miller)

2011-11-08 Thread Mark S. Miller
On Tue, Nov 8, 2011 at 11:29 AM, Andreas Rossberg rossb...@google.comwrote:

 On 8 November 2011 19:13, Mark S. Miller erig...@google.com wrote:
  The reason Proxy.attach may not be fatal is that it only allows
 attachment
  to extensible objects. Our hypothesis is that any ES5 object that is
  interested in defending itself has already made itself non-extensible.
 This
  is why we must key this off of non-extensibility, rather than
 introducing a
  new orthogonal bit -- to avoid breaching the defenses of those ES5 era
  objects that tried to defend themselves.

 I don't think that addresses the issue I was describing. The problem
 is: the object itself can all be frozen, non-extensible,
 non-attachable just fine, but that doesn't achieve much by itself
 anymore because an attacker can still attach to each individual
 method, since they are entirely separate objects!

 So instead of just freezing an object, you _additionally_ would have
 to make all its _individual methods_ non-attachable (by whatever
 means). AFAICS, that affects assumptions of existing ES5 code quite
 severely.


In general, for an object to be defensive, much of the surface reachable
from it by transitive prototype and reflective property traversal should
usually be frozen, and at least non-extensible. This is possible to express
in ES5 
http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/startSES.js#623,
but inconvenient and expensive. That's why I have been advocating better
defensive abstractions for ES6: const functions, const classes,
traitsjs or its syntactic derivatives, etc.

Nevertheless, I see your point. Many defensive ES5 abstractions will be
less defensive than this. If I understand you correctly, your point is
specifically about the [[Call]] and [[Construct]] traps. Perhaps we should
be more conservative here, without necessarily backing away from the whole
Proxy.attach idea?

-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Security and direct proxies (Was: Re: Lecture series on SES and capability-based security by Mark Miller)

2011-11-08 Thread Andreas Rossberg
On 8 November 2011 20:46, Mark S. Miller erig...@google.com wrote:
 In general, for an object to be defensive, much of the surface reachable
 from it by transitive prototype and reflective property traversal should
 usually be frozen, and at least non-extensible. This is possible to express
 in ES5
 http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/startSES.js#623,
 but inconvenient and expensive. That's why I have been advocating better
 defensive abstractions for ES6: const functions, const classes,
 traitsjs or its syntactic derivatives, etc.
 Nevertheless, I see your point. Many defensive ES5 abstractions will be less
 defensive than this. If I understand you correctly, your point is
 specifically about the [[Call]] and [[Construct]] traps.

Yes. Existing code has no reason to bother making functions
non-extensible if all it does is calling them. Proxy.attach
fundamentally breaks that (so far correct, AFAICT) assumption.

 Perhaps we should
 be more conservative here, without necessarily backing away from the whole
 Proxy.attach idea?

Disallowing attaching to functions with your own call/construct traps
would be the minimal restriction, I think. But maybe there is
something cleaner.

/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Security and direct proxies (Was: Re: Lecture series on SES and capability-based security by Mark Miller)

2011-11-08 Thread Mark S. Miller
On Tue, Nov 8, 2011 at 12:50 PM, Andreas Rossberg rossb...@google.comwrote:

 On 8 November 2011 20:46, Mark S. Miller erig...@google.com wrote:
  Nevertheless, I see your point. Many defensive ES5 abstractions will be
 less
  defensive than this. If I understand you correctly, your point is
  specifically about the [[Call]] and [[Construct]] traps.

 Yes. Existing code has no reason to bother making functions
 non-extensible if all it does is calling them. Proxy.attach
 fundamentally breaks that (so far correct, AFAICT) assumption.


I think we're agreeing on the operational point -- that much defensive code
won't bother to freeze such functions. But for clarity, I must correct your
no reason. The reason is one of the oldest software engineering best
practices: Say What You Mean. Perhaps a clearer statement is Mean Only What
You Say. The it in your above sentence presumes a non-local whole program
analysis which violates this rule, and is in any case inapplicable to
libraries.

To keep what the program means in sync with what it seems to mean, we need
to avoid introducing unexpressed communication channels. Or, put another
way, unexpressed shared mutable locations. If Alice provides object C to
both B and D, the only ways in which this should enable further
communication between B and D (beyond that which they may have already had)
should be according to the expressed behavior of C. For example, if the
expressed behavior of C is completely stateless, then the fact that B and D
both share a reference to C should not enable any additional
communications/interaction/influence between B and D.

These constraints are useful for much beyond security. If you wish to
program in a mostly functional style, you'd like the deviations from
functional style to only be where you've made a purposeful choice. When
debugging, you need to figure out: How did the bad symptom happen? If you
can bound the possible causes, by reasoning in terms of the program's
intended behavior, your detective work is much easier.


A program should not only work. It should also appear to work. --Carl
Hewitt.

-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-08 Thread David Herman
 Perhaps __proto__ should not be writeable in use strict?
 
 That's a great idea! This never occurred to me, and I have not heard anyone 
 suggest this. Thanks!

Doesn't work.

obj[(function(__){return __ + proto + __})(__)]

Dave

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-08 Thread Mark S. Miller
On Tue, Nov 8, 2011 at 3:33 PM, David Herman dher...@mozilla.com wrote:

 Perhaps __proto__ should not be writeable in use strict?


 That's a great idea! This never occurred to me, and I have not heard
 anyone suggest this. Thanks!


 Doesn't work.

 obj[(function(__){return __ + proto + __})(__)]


If the [ above is a strict [, it should not be able to address
__proto__, regardless of whether the  __proto__ is computed or not. Or
if we intend only to suppress writing, then

 obj[(function(__){return __ + proto + __})(__)] = {}

should still fail if the [ above is in strict code.




 Dave




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-08 Thread Mark S. Miller
On Tue, Nov 8, 2011 at 3:46 PM, Mark S. Miller erig...@google.com wrote:



 On Tue, Nov 8, 2011 at 3:33 PM, David Herman dher...@mozilla.com wrote:

 Perhaps __proto__ should not be writeable in use strict?


 That's a great idea! This never occurred to me, and I have not heard
 anyone suggest this. Thanks!


 Doesn't work.

 obj[(function(__){return __ + proto + __})(__)]


 If the [ above is a strict [, it should not be able to address
 __proto__, regardless of whether the  __proto__ is computed or not.
 Or if we intend only to suppress writing, then

  obj[(function(__){return __ + proto + __})(__)] = {}

 should still fail if the [ above is in strict code.


Sorry, it should not fail. It should simply create a normal property that
happens to be named __proto__. Likewise, your first example should simply
address such a normal property. Then JSON would again be an almost-subset
of ES5/strict, modulo \u2028 and \u2029.







 Dave




 --
 Cheers,
 --MarkM




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-08 Thread Mark S. Miller
http://www.google.com/support/forum/p/Google+Docs/thread?tid=0cd4a00bd4aef9e4
But yes. Because the difference would be silent, I'm skeptical too.

On Tue, Nov 8, 2011 at 8:23 PM, David Herman dher...@mozilla.com wrote:

 And another silent semantic change? I wouldn't be so quick to do that. And
 that's not the direction we were going for __proto__ in the last f2f.

 I *wish* __proto__ were just treated as another normal property. And I'd
 like for us to work towards a future where that's the case. I'm just
 skeptical we can do it by cramming it into strict mode.

 Dave

 On Nov 8, 2011, at 3:50 PM, Mark S. Miller wrote:



 On Tue, Nov 8, 2011 at 3:46 PM, Mark S. Miller erig...@google.com wrote:



 On Tue, Nov 8, 2011 at 3:33 PM, David Herman dher...@mozilla.com wrote:

 Perhaps __proto__ should not be writeable in use strict?


 That's a great idea! This never occurred to me, and I have not heard
 anyone suggest this. Thanks!


 Doesn't work.

 obj[(function(__){return __ + proto + __})(__)]


 If the [ above is a strict [, it should not be able to address
 __proto__, regardless of whether the  __proto__ is computed or not.
 Or if we intend only to suppress writing, then

  obj[(function(__){return __ + proto + __})(__)] = {}

 should still fail if the [ above is in strict code.


 Sorry, it should not fail. It should simply create a normal property that
 happens to be named __proto__. Likewise, your first example should simply
 address such a normal property. Then JSON would again be an almost-subset
 of ES5/strict, modulo \u2028 and \u2029.







 Dave




 --
 Cheers,
 --MarkM




 --
 Cheers,
 --MarkM





-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-08 Thread Brendan Eich
One more thought: people are already avoiding use strict; because it bites 
back:

* concatenation with non-strict code and under-testing, but let's hope we are 
past this now;
* performance dinged a bit by strict mode, or at least non-strict calling 
strict and vice versa.

We should try to avoid taking away the forbidden fruit prematurely. In 
particular since ES6 is based on ES5 strict.

When | is out and well-deployed, maybe. No predictable schedule for when we 
could actually hope to remove __proto__.

/be

On Nov 8, 2011, at 8:57 PM, Mark S. Miller wrote:

 http://www.google.com/support/forum/p/Google+Docs/thread?tid=0cd4a00bd4aef9e4
 But yes. Because the difference would be silent, I'm skeptical too.
 
 On Tue, Nov 8, 2011 at 8:23 PM, David Herman dher...@mozilla.com wrote:
 And another silent semantic change? I wouldn't be so quick to do that. And 
 that's not the direction we were going for __proto__ in the last f2f.
 
 I *wish* __proto__ were just treated as another normal property. And I'd like 
 for us to work towards a future where that's the case. I'm just skeptical we 
 can do it by cramming it into strict mode.
 
 Dave
 
 On Nov 8, 2011, at 3:50 PM, Mark S. Miller wrote:
 
 
 
 On Tue, Nov 8, 2011 at 3:46 PM, Mark S. Miller erig...@google.com wrote:
 
 
 On Tue, Nov 8, 2011 at 3:33 PM, David Herman dher...@mozilla.com wrote:
 Perhaps __proto__ should not be writeable in use strict?
 
 That's a great idea! This never occurred to me, and I have not heard anyone 
 suggest this. Thanks!
 
 Doesn't work.
 
 obj[(function(__){return __ + proto + __})(__)]
 
 If the [ above is a strict [, it should not be able to address 
 __proto__, regardless of whether the  __proto__ is computed or not. Or 
 if we intend only to suppress writing, then
 
  obj[(function(__){return __ + proto + __})(__)] = {}
 
 should still fail if the [ above is in strict code.
 
 Sorry, it should not fail. It should simply create a normal property that 
 happens to be named __proto__. Likewise, your first example should simply 
 address such a normal property. Then JSON would again be an almost-subset of 
 ES5/strict, modulo \u2028 and \u2029.
 
  
 
  
 
 Dave
 
 
 
 
 -- 
 Cheers,
 --MarkM
 
 
 
 -- 
 Cheers,
 --MarkM
 
 
 
 
 -- 
 Cheers,
 --MarkM
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Claus Reinke

In .. an ES5/strict environment in which all primordial built-in objects
are transitively frozen, ..

   function makeTable() {
 var array = [];
 return Object.freeze({
   add: function(v) { array.push(v); },
   store: function(i, v) { array[i] = v; },
   get: function(i) { return array[i]; }
 });
   }

.. Given just a table instance, can Bob nevertheless obtain direct access
to the underlying array?


Hm. A favorite pattern that I haven't thought about enough, it seems.
My curiosity did cost me some sleep:-| My favorite work around for
your constraints is this little shim:-)

 // dynamic language
 Object.freeze = function(obj){return obj};

You imply that this is not intended, so I can show it without spoiling
the fun. I was surprised that this works.

The first solution that came to mind ought to be defeated by your
transitively frozen constraint, and it is, in current JS implementations,
though not all JS implementations in the wild are there yet - do you
feature-detect old engines and issue warnings if they invalidate
your base assumptions?

The second approach took longer to find but relies on non-standard
features (and again, I suspect a bug/interpretation issue).

Both ideas are weak, in that they could be blocked by type checks.


If you've already seen this puzzle and know the answer, please don't
post. If no one else has posted the correct answer in 24 hours, I will.


Neither of my approaches seems to be the droid you are looking for,
given your no realistic fix remark, so I'm curious what else I've missed.


Note that I don't see any realistic way to fix problem #3 in the ES.next
language. My point is only that defensive programming is tricky even after
you've gotten all the formal properties you need. As ES.next introduces
various new abstraction mechanisms, whether classes, enhanced object
literals, proxies, modules, or private names, the design of these can
either help or hurt those attempting to write defensive abstractions. Any
class abstraction that is only useful for making indefensible instances is
worse than useless -- it is actively harmful, both to security and to
serious software engineering.


You also rely on you security base framework being the first to run,
and on nobody trying to modify source on load, right?

Claus
http://clausreinke.github.com/
http://clausreinke.github.com/js-tools/


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Allen Wirfs-Brock

On Nov 4, 2011, at 8:50 AM, Juan Ignacio Dopazo wrote:

 On Thu, Nov 3, 2011 at 7:55 PM, Mark S. Miller erig...@google.com wrote:
 function makeTable() {
   var array = [];
   return Object.freeze({
 add: function(v) { array.push(v); },
 store: function(i, v) { array[i] = v; },
 get: function(i) { return array[i]; }
   });
 }
 
  Given just a table instance, can Bob nevertheless obtain direct access to 
 the underlying array?
 
 So Bob can cheat by extending Array.prototype, right?

MarkM said all primordial built-in objects are transitively frozen so 
Array.prototype is not extensible and Array.prototype.push is not writable...

Allen

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Mark S. Miller
On Fri, Nov 4, 2011 at 8:14 AM, Claus Reinke claus.rei...@talk21.comwrote:


 Hm. A favorite pattern that I haven't thought about enough, it seems.
 My curiosity did cost me some sleep:-| My favorite work around for
 your constraints is this little shim:-)

  // dynamic language
  Object.freeze = function(obj){return obj};

 You imply that this is not intended, so I can show it without spoiling
 the fun. I was surprised that this works.


Since the primordials are already frozen, this assignment fails.




 The first solution that came to mind ought to be defeated by your
 transitively frozen constraint, and it is, in current JS implementations,
 though not all JS implementations in the wild are there yet - do you
 feature-detect old engines and issue warnings if they invalidate
 your base assumptions?


Yes, as shown by 
http://es-lab.googlecode.com/svn/trunk/src/ses/explicit.html.
For example, Firefox 7.0.1 shows Max Severity: Not isolated(4) is not
SES-safe.
Chrome 16 shows Max Severity: Safe spec violation(1).
Firefox Nightly 10.0a1 shows no Max Severity line because it encountered no
unrepairable problems.

If you do a view source, you'll see the text

// This severity is too high for any use other than development.
ses.maxAcceptableSeverityName = 'NEW_SYMPTOM';

For production use, depending on you're purpose, you'd probably let the max
acceptable severity default, in which case initSES.js will fail quickly as
soon as it detects that this platform cannot be made SES-safe. Once
initSES.js terminates, ses.ok() indicates whether the max acceptable
severity has been exceeded. The severity levels can currently be found at 
http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/repairES5.js#85


We are currently in the process of integrating SES in with the rest of
Caja. If you're only targeting SES-safe browsers you can still use
initSES.js by itself. Otherwise, if you deploy through Caja, the plan is
that Caja will detect whether this is a SES-safe platform, deploy without
translation using SES if so, and otherwise fall back to Caja's ES5-to-ES3
translator.



 The second approach took longer to find but relies on non-standard
 features (and again, I suspect a bug/interpretation issue).


What is your second approach?



 Both ideas are weak, in that they could be blocked by type checks.


How?





  If you've already seen this puzzle and know the answer, please don't
 post. If no one else has posted the correct answer in 24 hours, I will.


 Neither of my approaches seems to be the droid you are looking for,
 given your no realistic fix remark, so I'm curious what else I've missed.


I should take this opportunity to reveal that David Herman found a bug last
night with my challenge. Due to a feature of ES3 which ES5.1 preserves,
and which I keep forgetting about because it has always seemed only to be
annoyance, the attack I had in mind actually fails on an ES5.1 conformant
browser. Another reason I missed it is my attack succeeds on Chrome/v8,
because it does not implement this feature. Dave found it because
FF/SpiderMonkey is ES5.1 conformant in this regard. After he rediscovered
the attack, it failed when he tried it on SpiderMonkey, reminding both of
us of this annoyance. Perhaps this annoyance really is a feature after all?

I asked him to keep quiet about it for the remainder of the 24 hours
because I was curious to see what people came up with.

Congrats to Dave!





  Note that I don't see any realistic way to fix problem #3 in the ES.next
 language. My point is only that defensive programming is tricky even after
 you've gotten all the formal properties you need. As ES.next introduces
 various new abstraction mechanisms, whether classes, enhanced object
 literals, proxies, modules, or private names, the design of these can
 either help or hurt those attempting to write defensive abstractions. Any
 class abstraction that is only useful for making indefensible instances is
 worse than useless -- it is actively harmful, both to security and to
 serious software engineering.


 You also rely on you security base framework being the first to run,


Yes, absolutely.




 and on nobody trying to modify source on load, right?


I think the answer to this is yes as well, but first I should ask for
clarification: source to what?



 Claus
 http://clausreinke.github.com/
 http://clausreinke.github.com/**js-tools/http://clausreinke.github.com/js-tools/





-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Axel Rauschmayer
[edited and sent to es-discuss, just in case]

function makeTable() {
  var array = [];
  return Object.freeze({
add: function(v) { array.push(v); },
store: function(i, v) { array[i] = v; },
get: function(i) { return array[i]; }
  });
}
 
 [...] Given just a table instance, can Bob nevertheless obtain direct access 
 to the underlying array?

How about:

function Bob(t) {
   var stolenArray;
   var hackedPush = function() {
   stolenArray = this;
   };
   t.store(push, hackedPush);
   t.add(0);
   console.log(stolenArray);
}
Bob(makeTable());

-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Axel Rauschmayer
function Bob(t) {
   var stolenArray;
   var hackedPush = function() {
   stolenArray = this;
   };
   t.store(push, hackedPush);
   t.add(0);
   console.log(stolenArray);
}
Bob(makeTable());


As an aside: This problem would go away if we really did distinguish between 
accessing a property and accessing a collection element. Then the former would 
be done via Object.* methods, while the latter would be done via square 
brackets.

-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Jorge
On 03/11/2011, at 23:55, Mark S. Miller wrote:
 3) Although SES is *formally* an object-capability language, i.e., it has all 
 the formal properties required by the object-capability model, it has bad 
 usability properties for writing defensive abstractions, and therefore bad 
 usability properties for use as an object-capability language or for serious 
 software engineering. One example:
 
 In a SES environment, or, for present purposes, an ES5/strict environment in 
 which all primordial built-in objects are transitively frozen, say Alice uses 
 the following abstraction:
 
 function makeTable() {
   var array = [];
   return Object.freeze({
 add: function(v) { array.push(v); },
 store: function(i, v) { array[i] = v; },
 get: function(i) { return array[i]; }
   });
 }
 
 Say she uses it to make a table instance with three methods: add, store, 
 and get. She gives this instance to Bob. Alice and Bob are mutually 
 suspicious. All of us as programmers, looking at this code, can tell that 
 Alice intended the table abstraction to encapsulate the array. Given just a 
 table instance, can Bob nevertheless obtain direct access to the underlying 
 array?

Yes, this:

function makeTable() {
  var array = [];
  return Object.freeze({
add: function(v) { array.push(v); },
store: function(i, v) { array[i] = v; },
get: function(i) { return array[i]; }
  });
}

o= makeTable();
o.add(1);
o.add(2);
o.add(3);
o.add('Yay!');

o.store('__proto__', {push:function () { console.log(this) }});
o.add();

Gives:

[ 1, 2, 3, 'Yay!' ]
-- 
Jorge.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Allen Wirfs-Brock

On Nov 4, 2011, at 10:33 AM, Axel Rauschmayer wrote:

 How about:
 
function Bob(t) {
   var stolenArray;
   var hackedPush = function() {
   stolenArray = this;
   };
   t.store(push, hackedPush);


If Array.prototype has been frozen (as the problem statement implied) then the 
above line should throw.


Allen
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Jorge
On 04/11/2011, at 18:51, Jorge wrote:
 On 03/11/2011, at 23:55, Mark S. Miller wrote:
 3) Although SES is *formally* an object-capability language, i.e., it has 
 all the formal properties required by the object-capability model, it has 
 bad usability properties for writing defensive abstractions, and therefore 
 bad usability properties for use as an object-capability language or for 
 serious software engineering. One example:
 
 In a SES environment, or, for present purposes, an ES5/strict environment in 
 which all primordial built-in objects are transitively frozen, say Alice 
 uses the following abstraction:
 
function makeTable() {
  var array = [];
  return Object.freeze({
add: function(v) { array.push(v); },
store: function(i, v) { array[i] = v; },
get: function(i) { return array[i]; }
  });
}
 
 Say she uses it to make a table instance with three methods: add, store, 
 and get. She gives this instance to Bob. Alice and Bob are mutually 
 suspicious. All of us as programmers, looking at this code, can tell that 
 Alice intended the table abstraction to encapsulate the array. Given just a 
 table instance, can Bob nevertheless obtain direct access to the underlying 
 array?
 
 Yes, this:
 
 function makeTable() {
  var array = [];
  return Object.freeze({
add: function(v) { array.push(v); },
store: function(i, v) { array[i] = v; },
get: function(i) { return array[i]; }
  });
 }
 
 o= makeTable();
 o.add(1);
 o.add(2);
 o.add(3);
 o.add('Yay!');
 
 o.store('__proto__', {push:function () { console.log(this) }});

Or even easier yet, what Axel says:

o.store('push', function () { console.log(this) });

 o.add();
 
 Gives:
 
 [ 1, 2, 3, 'Yay!' ]

[ 1, 2, 3, 'Yay!', push: [Function] ]
-- 
Jorge.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Axel Rauschmayer
But hackedPush is added to the instance, not Array.prototype.

On Nov 4, 2011, at 18:59 , Allen Wirfs-Brock wrote:

 
 On Nov 4, 2011, at 10:33 AM, Axel Rauschmayer wrote:
 
 How about:
 
   function Bob(t) {
  var stolenArray;
  var hackedPush = function() {
  stolenArray = this;
  };
  t.store(push, hackedPush);
 
 
 If Array.prototype has been frozen (as the problem statement implied) then 
 the above line should throw.
 
 
 Allen

-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Allen Wirfs-Brock
You can't over-ride an inherited read-only property by assignment. See ES5.1 
8.12.4

You could do it via Object.defineProperty, but that requires direct access to 
the object.

Allen

On Nov 4, 2011, at 11:01 AM, Axel Rauschmayer wrote:

 But hackedPush is added to the instance, not Array.prototype.
 
 On Nov 4, 2011, at 18:59 , Allen Wirfs-Brock wrote:
 
 
 On Nov 4, 2011, at 10:33 AM, Axel Rauschmayer wrote:
 
 How about:
 
   function Bob(t) {
  var stolenArray;
  var hackedPush = function() {
  stolenArray = this;
  };
  t.store(push, hackedPush);
 
 
 If Array.prototype has been frozen (as the problem statement implied) then 
 the above line should throw.
 
 
 Allen
 
 -- 
 Dr. Axel Rauschmayer
 a...@rauschma.de
 
 home: rauschma.de
 twitter: twitter.com/rauschma
 blog: 2ality.com
 
 
 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread David Herman
This is the only one I've seen that seems like it should work, but it depends 
on whether SES/Caja/etc have some sort of way of neutering __proto__. Just from 
hacking around, I don't see much way of censoring it in SpiderMonkey.

MarkM, do you have any tricks for censoring __proto__?

Dave

On Nov 4, 2011, at 10:51 AM, Jorge wrote:

 On 03/11/2011, at 23:55, Mark S. Miller wrote:
 3) Although SES is *formally* an object-capability language, i.e., it has 
 all the formal properties required by the object-capability model, it has 
 bad usability properties for writing defensive abstractions, and therefore 
 bad usability properties for use as an object-capability language or for 
 serious software engineering. One example:
 
 In a SES environment, or, for present purposes, an ES5/strict environment in 
 which all primordial built-in objects are transitively frozen, say Alice 
 uses the following abstraction:
 
function makeTable() {
  var array = [];
  return Object.freeze({
add: function(v) { array.push(v); },
store: function(i, v) { array[i] = v; },
get: function(i) { return array[i]; }
  });
}
 
 Say she uses it to make a table instance with three methods: add, store, 
 and get. She gives this instance to Bob. Alice and Bob are mutually 
 suspicious. All of us as programmers, looking at this code, can tell that 
 Alice intended the table abstraction to encapsulate the array. Given just a 
 table instance, can Bob nevertheless obtain direct access to the underlying 
 array?
 
 Yes, this:
 
 function makeTable() {
  var array = [];
  return Object.freeze({
add: function(v) { array.push(v); },
store: function(i, v) { array[i] = v; },
get: function(i) { return array[i]; }
  });
 }
 
 o= makeTable();
 o.add(1);
 o.add(2);
 o.add(3);
 o.add('Yay!');
 
 o.store('__proto__', {push:function () { console.log(this) }});
 o.add();
 
 Gives:
 
 [ 1, 2, 3, 'Yay!' ]
 -- 
 Jorge.
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Claus Reinke

 // dynamic language
 Object.freeze = function(obj){return obj};

You imply that this is not intended, so I can show it without spoiling
the fun. I was surprised that this works.


Since the primordials are already frozen, this assignment fails.


Yes. It just re-emphasizes the need to be the first to run.
Needing to freeze freeze seemed a fun way to show the
Muenchhausen aspect of getting a secure environment.

I was surprised that several of my current JS environments
do not yet implement freeze, btw. Need to watch that.


The first solution that came to mind ought to be defeated by your
transitively frozen constraint, and it is, in current JS 
implementations,

though not all JS implementations in the wild are there yet - do you
feature-detect old engines and issue warnings if they invalidate
your base assumptions?


Yes, as shown by 
http://es-lab.googlecode.com/svn/trunk/src/ses/explicit.html.
For example, Firefox 7.0.1 shows Max Severity: Not isolated(4) is not
SES-safe.
Chrome 16 shows Max Severity: Safe spec violation(1).
Firefox Nightly 10.0a1 shows no Max Severity line because it encountered 
no

unrepairable problems.

If you do a view source, you'll see the text

   // This severity is too high for any use other than development.
   ses.maxAcceptableSeverityName = 'NEW_SYMPTOM';

For production use, depending on you're purpose, you'd probably let the 
max

acceptable severity default, in which case initSES.js will fail quickly as
soon as it detects that this platform cannot be made SES-safe. Once
initSES.js terminates, ses.ok() indicates whether the max acceptable
severity has been exceeded. The severity levels can currently be found at 


http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/repairES5.js#85




We are currently in the process of integrating SES in with the rest of
Caja. If you're only targeting SES-safe browsers you can still use
initSES.js by itself. Otherwise, if you deploy through Caja, the plan is
that Caja will detect whether this is a SES-safe platform, deploy without
translation using SES if so, and otherwise fall back to Caja's ES5-to-ES3
translator.


Is this feature-testing something that could be emphasized more
in SES presentations? It might be useful to remind JS coders of
the difficulties of security - it isn't just PHP, and just because there
are efforts like AdSafe or SES, that doesn't mean that the fight is
won, or that solutions are easy. Highlighting the difficulties could
avoid the I-feel-safe-because-there-are-magic-security-black-boxes.


The second approach took longer to find but relies on non-standard
features (and again, I suspect a bug/interpretation issue).


What is your second approach?


Is the time up, already?-)

My first approach was using store to modify array.push, also
suggested by others. That should fail, because Array.prototype
is frozen and freezing prevents shadowing inherited properties.

In FireFox 7, it fails, but the older node-0.4.9 doesn't seem to care..

My second approach was to use store to modify array.__proto__,
adding a rogue push to a new non-frozen prototype. That should
fail if Object.prototype is frozen, for the same shadowing reason.

In FireFox 7, it fails, but the older node-0.4.9 doesn't seem to care..

To guard against, one might prevent __proto__ use in general, as
AdSafe does, I think). Or ensure that array.push is the method
one wants by not getting it from modifiable array.

Perhaps __proto__ should not be writeable in use strict?

Perhaps test262 failures that enable security issues should be
highlighted separately, to encourage upgrading? Or, if test262
cannot test for non-standard features, the SES initialization
checks could be given a similarly prominent (publicity-worthy)
status as test262?


Both ideas are weak, in that they could be blocked by type checks.


How?


Ah, yes. I was thinking that checking the type of store's index
parameter would prevent both of these attempts. But there is
nothing in your spec that rules out string parameters. So, one
would have to resort to blacklisting :-(, starting with..

   (!i in array||array.hasOwnProperty(i))


 If you've already seen this puzzle and know the answer, please don't

post. If no one else has posted the correct answer in 24 hours, I will.


Neither of my approaches seems to be the droid you are looking for,
given your no realistic fix remark, so I'm curious what else I've 
missed.


I should take this opportunity to reveal that David Herman found a bug 
last

night with my challenge. Due to a feature of ES3 which ES5.1 preserves,
and which I keep forgetting about because it has always seemed only to be
annoyance, the attack I had in mind actually fails on an ES5.1 conformant
browser. Another reason I missed it is my attack succeeds on Chrome/v8,
because it does not implement this feature. Dave found it because
FF/SpiderMonkey is ES5.1 conformant in this regard. After he rediscovered
the attack, it failed when he tried it 

Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Brendan Eich
On Nov 4, 2011, at 2:40 PM, Allen Wirfs-Brock wrote:

 On Nov 4, 2011, at 2:33 PM, Brendan Eich wrote:
 ...
 If you could redefine [] as an operator on all objects, perhaps that would 
 help. Or hurt. Both, probably. That isn't what Allen proposes, though. It 
 would have to be universal AFAICT. Thoughts?
 
 
 Actually, that sounds pretty much what I proposed.  My proposal was that [ ] 
 (actually RHS and LHS independently) would invoke a method using a well known 
 property name if it was present on the object to the left of the [ ].  If the 
 property was not present (own or inherited) then it would fall back to 
 current behavior.

So Object.prototype customization would cover all cases? Except Proxies, of 
course -- and host objects.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Allen Wirfs-Brock

On Nov 4, 2011, at 2:49 PM, Brendan Eich wrote:

 On Nov 4, 2011, at 2:40 PM, Allen Wirfs-Brock wrote:
 
 On Nov 4, 2011, at 2:33 PM, Brendan Eich wrote:
 ...
 If you could redefine [] as an operator on all objects, perhaps that would 
 help. Or hurt. Both, probably. That isn't what Allen proposes, though. It 
 would have to be universal AFAICT. Thoughts?
 
 
 Actually, that sounds pretty much what I proposed.  My proposal was that [ ] 
 (actually RHS and LHS independently) would invoke a method using a well 
 known property name if it was present on the object to the left of the [ ].  
 If the property was not present (own or inherited) then it would fall back 
 to current behavior.
 
 So Object.prototype customization would cover all cases? Except Proxies, of 
 course -- and host objects.
 

Yes, except that what you would expect to put into Object.prototype would 
actually (or also) be defined as default behavior in order to ensure that that 
Object.create(null) objects, etc continue to have ES1-5 behavior.  Because 
collection behavior is defined via  method invocation, proxies don't  need to 
do/have anything special (although a Proxy's [[Get]] handler) could look for 
accesses to the special [ ] behavior methods.  Same for host objects, except 
who knows what a host object really is...

Allen 



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Mark S. Miller
On Fri, Nov 4, 2011 at 10:33 AM, Axel Rauschmayer a...@rauschma.de wrote:


 How about:

function Bob(t) {
var stolenArray;
   var hackedPush = function() {
   stolenArray = this;
   };
   t.store(push, hackedPush);
   t.add(0);
   console.log(stolenArray);
}
 Bob(makeTable());


Yes, that is precisely the attack I had in mind. Congrats!

As Dave Herman discovered, it works on v8 but not on SpiderMonkey due to a
known bug in v8 that I had forgotten was a bug. According to the ES5.1
spec, you can't override a non-writable data property with a simple
assignment. I had always considered this an unfortunate annoyance and
irrelevant to security, but in this case it did happen to accidentally
prevent an attack.

-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Axel Rauschmayer
 So Object.prototype customization would cover all cases? Except Proxies, of 
 course -- and host objects.
 
 Yes, except that what you would expect to put into Object.prototype would 
 actually (or also) be defined as default behavior in order to ensure that 
 that Object.create(null) objects, etc continue to have ES1-5 behavior.  
 Because collection behavior is defined via  method invocation, proxies don't  
 need to do/have anything special (although a Proxy's [[Get]] handler) could 
 look for accesses to the special [ ] behavior methods.  Same for host 
 objects, except who knows what a host object really is...

Have you come to a decision with regard to a separate .[] operator for 
collections (including arrays)?

I think it’s better to rededicate []:
- .[] would invalidate all existing array code.
- [] would only invalidate code that uses computed property names. And that can 
be fixed via the default behavior.

It might make sense to have a stricter mode that turns off the default 
behavior of []:
- It would thus force you to use methods such as (the yet to be defined) 
Object.setOwnProperty() and Object.getProperty() when you want to compute the 
name of a property.
- Stricter mode could also restrict [] for arrays to just numbers, including 
negative numbers for accessing elements relative to the end of an array.

-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Mark S. Miller
On Fri, Nov 4, 2011 at 10:37 AM, Axel Rauschmayer a...@rauschma.de wrote:

function Bob(t) {
   var stolenArray;
   var hackedPush = function() {
   stolenArray = this;
   };
   t.store(push, hackedPush);
   t.add(0);
   console.log(stolenArray);
}
Bob(makeTable());


 As an aside: This problem would go away if we really did distinguish
 between accessing a property and accessing a collection element. Then the
 former would be done via Object.* methods, while the latter would be done
 via square brackets.


I admit that I haven't followed the previous thread on .[ and such. Is
there a short summary? I ask because my diagnosis is similar but my
conclusion is reversed. The lesson I take from this is not to use objects
as maps. It you want a map, create a Map() and say map.get(key) and
map.set(key, value) rather than using square brackets.

The remaining case is arrays. My conclusion there is to always say
array[+i] rather than array[i]. If Alice had already been practicing this
as a habit, then her table abstraction would have been naturally robust
against this attack even if Alice never thinks of this specific attack.

Having eliminated both of these uses of unmarked square brackets (lists and
maps), the only remaining justified use of unmarked square bracket indexing
is reflection. If you see an unmarked square bracket that's not doing
reflection, you should probably refactor.


-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Mark S. Miller
On Fri, Nov 4, 2011 at 10:51 AM, Jorge jo...@jorgechamorro.com wrote:


 o= makeTable();
 o.add(1);
 o.add(2);
 o.add(3);
 o.add('Yay!');

 o.store('__proto__', {push:function () { console.log(this) }});
 o.add();

 Gives:

 [ 1, 2, 3, 'Yay!' ]


Very nice! Your use of __proto__ is very clever, and should work on
SpiderMonkey, or any other conforming browser that also supports de-facto
__proto__.

Note that the mitigating practice I just recommended: always saying
array[+i] rather than array[i], would have prevented this attack as well,
even though I had not thought of it before.

-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Axel Rauschmayer
 As an aside: This problem would go away if we really did distinguish between 
 accessing a property and accessing a collection element. Then the former 
 would be done via Object.* methods, while the latter would be done via square 
 brackets.
 
 I admit that I haven't followed the previous thread on .[ and such. Is 
 there a short summary? I ask because my diagnosis is similar but my 
 conclusion is reversed. The lesson I take from this is not to use objects as 
 maps. It you want a map, create a Map() and say map.get(key) and map.set(key, 
 value) rather than using square brackets.
 
 The remaining case is arrays. My conclusion there is to always say array[+i] 
 rather than array[i]. If Alice had already been practicing this as a habit, 
 then her table abstraction would have been naturally robust against this 
 attack even if Alice never thinks of this specific attack.
 
 Having eliminated both of these uses of unmarked square brackets (lists and 
 maps), the only remaining justified use of unmarked square bracket indexing 
 is reflection. If you see an unmarked square bracket that's not doing 
 reflection, you should probably refactor. 

I agree completely (see also my other email):
- Never use objects as maps.
- Introduce collection classes.
- Try to make arrays fit into the collection framework.

-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Mark S. Miller
On Fri, Nov 4, 2011 at 11:46 AM, David Herman dher...@mozilla.com wrote:

 This is the only one I've seen that seems like it should work, but it
 depends on whether SES/Caja/etc have some sort of way of neutering
 __proto__. Just from hacking around, I don't see much way of censoring it
 in SpiderMonkey.

 MarkM, do you have any tricks for censoring __proto__?


Not censoring, no. However, for code that follows the following best
practices, uncensored __proto__ should be harmless.

1) Avoid objects as maps -- use Maps as maps.
2) Always use array[+i] for numeric indexing. Note that this can still
access properties named 'NaN', 'Infinity', and '-Infinity'.
3) Always freeze, or at least seal, objects potentially exposed directly to
untrusted clients.

#3 is crucial, and works because ES5.1 section 8.6.2 says:
if [[Extensible]] is false the value of the [[Class]] and [[Prototype]]
internal properties of the object may not be modified. Once the value of an
[[Extensible]] internal property has been set to false it may not be
subsequently changed to true.

This is tested by test262 at 
http://hg.ecmascript.org/tests/test262/file/c84161250e66/test/suite/ch08/8.6/8.6.2/S8.6.2_A8.js
.

The visible development tip of all major browsers except Opera 12 alpha
build 1116 already implement this restriction. initSES.js considers that
Opera unsafe for this reason.

Nevertheless, if I could cheaply censor __proto__ I would. Since I'm not, I
am *very* curious is this leaves open other attacks against code obeying
the above best practices. If any of you see some other avenue of attack,
*please* let me know. Thanks.

-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Mark S. Miller
On Fri, Nov 4, 2011 at 12:11 PM, Claus Reinke claus.rei...@talk21.comwrote:

  // dynamic language
  Object.freeze = function(obj){return obj};

 You imply that this is not intended, so I can show it without spoiling
 the fun. I was surprised that this works.


 Since the primordials are already frozen, this assignment fails.


 Yes. It just re-emphasizes the need to be the first to run.
 Needing to freeze freeze seemed a fun way to show the
 Muenchhausen aspect of getting a secure environment.


I haven't yet seen the movie. But since it is directed by Terry Gilliam,
it's on my list ;).




 I was surprised that several of my current JS environments
 do not yet implement freeze, btw. Need to watch that.

[...]

 Is this feature-testing something that could be emphasized more
 in SES presentations?


I haven't, but I agree with you that I should. I do emphasize that SES only
works on ES5, and that on a pre-ES5 browser, we still need the Caja
ES5-to-ES3 translator. But I should make clearer how picky initSES.js is
about what it considers and ES5 browser.



 It might be useful to remind JS coders of
 the difficulties of security - it isn't just PHP, and just because there
 are efforts like AdSafe or SES, that doesn't mean that the fight is
 won, or that solutions are easy. Highlighting the difficulties could
 avoid the I-feel-safe-because-there-are-**magic-security-black-boxes.


Although I may be understating the difficulties, I think you are
overstating them here. This problem is transient. The visible development
tip versions of all major browsers are either already SES-safe of fall
short by one bug, tested by test262, that I expect both teams to fix. This
means that shortly, the most recent released version of all major browsers
will be SES-safe. Browser makers have generally been getting more
aggressive about encouraging upgrades, so that the tail of old browsers
fades out quicker.

I'll go ahead and make a prediction that a year from now the straggler
we're all be cursing will be IE8 on Windows-XP, since I do not expect MS to
ever backport IE10 to XP, and I expect there will still be Windows users
holding onto XP for dear life.





  The second approach took longer to find but relies on non-standard
 features (and again, I suspect a bug/interpretation issue).


 What is your second approach?


 Is the time up, already?-)

 My first approach was using store to modify array.push, also
 suggested by others. That should fail, because Array.prototype
 is frozen and freezing prevents shadowing inherited properties.

 In FireFox 7, it fails, but the older node-0.4.9 doesn't seem to care..

 My second approach was to use store to modify array.__proto__,
 adding a rogue push to a new non-frozen prototype. That should
 fail if Object.prototype is frozen, for the same shadowing reason.


That is very interesting. I would have expected __proto__ to be exempt from
this restriction since it isn't really a property. I'm glad to hear that it
is not exempt, at least on SpiderMonkey.




 In FireFox 7, it fails, but the older node-0.4.9 doesn't seem to care..

 To guard against, one might prevent __proto__ use in general, as
 AdSafe does, I think).


ADsafe guards against this at the price of including a full accurate JS
lexer and parser. One of my goals for SES is to see if we could get to full
ocap security without needing an accurate lexer and parser, in order to
avoid download bloat. It seems we can.



 Or ensure that array.push is the method
 one wants by not getting it from modifiable array.


For normal defensive SES programming use, I fear this is a bridge too far.
For programmers coming from JS, I want defensive SES to still be easy to
learn and pleasant to use.

Of course, if Alice notices the danger for this specific example, should
could reasonably use it here but not in general. But the problem is the if
Alice notices part. Secure programming practices only work if they defend
against most attacks without the programmer needing to have thought of
these attacks.



 Perhaps __proto__ should not be writeable in use strict?


That's a great idea! This never occurred to me, and I have not heard anyone
suggest this. Thanks!




 Perhaps test262 failures that enable security issues should be
 highlighted separately, to encourage upgrading? Or, if test262
 cannot test for non-standard features, the SES initialization
 checks could be given a similarly prominent (publicity-worthy)
 status as test262?


SES has no normative status yet in TC39, so doing so at
test262.ecmascript.org is a bit tricky. At some point I intend to bring SES
to TC39, probably on a separate track in the way i18n is separately
tracked. Once SES is on its way towards de jure standardization, then such
prominence should naturally follow. Thanks for the suggestion.

Of course, nothing stops anyone from publicizing SES in other venues, so
please feel free ;).




  Both ideas are weak, in that they could be blocked by type checks.


 How?


 

Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Mark S. Miller
On Fri, Nov 4, 2011 at 6:50 PM, Axel Rauschmayer a...@rauschma.de wrote:


 I agree completely (see also my other email):
 - Never use objects as maps.
 - Introduce collection classes.
 - Try to make arrays fit into the collection framework.


Great! But could you please post a pointer to that other email, or post a
summary? Thanks.


-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Mark S. Miller
On Fri, Nov 4, 2011 at 2:33 PM, Brendan Eich bren...@mozilla.com wrote:


 If you could redefine [] as an operator on all objects, perhaps that would
 help. Or hurt. Both, probably. That isn't what Allen proposes, though. It
 would have to be universal AFAICT. Thoughts?


Is there a previous email or a short summary of what redefine [] as an
operator would entail? I'm sorry that I haven't really followed that
thread, but I haven't. Thanks.

-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Axel Rauschmayer
 I agree completely (see also my other email):
 - Never use objects as maps.
 - Introduce collection classes.
 - Try to make arrays fit into the collection framework.
 
 Great! But could you please post a pointer to that other email, or post a 
 summary? Thanks. 

This is the original thread:
http://www.mail-archive.com/es-discuss@mozilla.org/msg10464.html

My understanding (using Allen’s terminology) is as follows (consult Allen’s 
email that started the thread for further details and a longer rationale).

We have to separate the data domain from the program domain:
- Arrays: [] is used to access both collection/array elements (data domain) and 
properties (program domain).
- Objects: [] is used mainly for properties, but also for collection element 
access when (ab)using objects as maps from strings to values.

Solutions:
1. New operator for the data domain: Introduce a new, separate operator .[] for 
accessing collection elements. Use it for all new collection types, implement 
it for arrays, too.  
2. Rededicate [] to be used for the data domain only: Default behavior remains 
as is, but can be overridden in collection classes (including arrays). Using [] 
for property access is deprecated, you must use methods such as 
Object.setOwnProperty() and Object.getProperty() to do so.

Addendum: edited quote from a recent email of mine:

 I think it’s better to rededicate [] to be a collection element accessor:
 - Introducing .[] would deprecate all existing array code and code that uses 
 objects as maps.
 - Rededicating [] would only deprecate code that uses computed property names.
 
 It might make sense to have a stricter mode that turns off the default 
 behavior of []:
 - It would thus force you to use methods such as (the yet to be defined) 
 Object.setOwnProperty() and Object.getProperty() when you want to compute the 
 name of a property.
 - Stricter mode could also restrict [] for arrays to just numbers, including 
 negative numbers for accessing elements relative to the end of an array.


-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-04 Thread Allen Wirfs-Brock

On Nov 4, 2011, at 6:44 PM, Mark S. Miller wrote:

 
 On Fri, Nov 4, 2011 at 10:37 AM, Axel Rauschmayer a...@rauschma.de wrote:
 
 
 
 As an aside: This problem would go away if we really did distinguish between 
 accessing a property and accessing a collection element. Then the former 
 would be done via Object.* methods, while the latter would be done via square 
 brackets.
 
 I admit that I haven't followed the previous thread on .[ and such. Is 
 there a short summary? I ask because my diagnosis is similar but my 
 conclusion is reversed. The lesson I take from this is not to use objects as 
 maps. It you want a map, create a Map() and say map.get(key) and map.set(key, 
 value) rather than using square brackets.
 

My original proposal is at 
https://mail.mozilla.org/pipermail/es-discuss/2011-October/017468.html 

Here is an abridged version:

We then give MemberExpression [ Expression ] a new semantics.  Here is the 
initial skeleton of this new semantics:

if MemberExpression is a collection return the result of invoking its 
element getter/setter method
else do the algorithm from ES5 11.2.1

What this says is that for any existing ES5 style object continue to work just 
like they always have. But in ES.Harmony there would be a new kind of 
collection object for which .  works differently from [ ].

So to make the above skeleton semantics more meaningful we need to define what 
we really mean by collection and by element getter/setter method.  Let's 
start with the latter.

Let assume that there are two predefined private name object values that are 
required to exist by the ES.Harmony spec. Let's refer to those values as 
@elementGetKey and @elementSetKey  (these are just names we use in the spec. 
language to talk about those private name values, the actual private name 
objects would be dynamically provided by ES implementations).  Then a element 
getter/setter method is simply an object property whose property key is either 
@elementGetKey or @elementSetKey.  The signature of these methods would 
normally be:
function /*element getter */ (elementKey){return anElementValue};  
function /*element setter */ (elementKey, newElementValue){};

Further more we define collection to mean an object that has a property that 
is a  element getter/setter method.  The property may be either own or 
inherited.

How would we define such an collection object.  It could be as simply as 
something like this:

import {collectionGetter, collectionSetter} from @metaCollections;

export function StringKeyedMap() {
   this.__content = Object.create(null);  //note __content object is a normal 
object and  [ ] on it does regular property access
   Object.defineProperty(this, collectionGetter,{value: function(k) {return 
this.__content[k]});
   Object.defineProperty(this, collectionSetter,{value: function(k,v) 
{this.__content[k]=v;});
   this.size = function() {Object.getOwnPropertyNames(this.__content ).length}; 
 //I'm lazy
   this.has = function(k) {return {}.hasOwnProperty.call(this.__content,k};
   this.delete = function(k) {return delete this.__content[k]}
}

This implements a string-keyed map with the same interface as used in the 
simple _map proposal, except that [ ] is used instead of get/set methods for 
element access. Note that there is no conflict between element names and method 
names such as size and has.  It uses as backing store a regularly object 
that acts as an string-keyed hash table.

Using this techniques all sorts of collection classes could be build 
including array-like collections with domain restrictions of their element 
values. They would all be fully subclassable.

Also, the length invariant semantics of built-in array objects can be emulated 
without having to use Proxies.


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-03 Thread John J Barton
On Thu, Nov 3, 2011 at 12:52 PM, Tom Van Cutsem tomvc...@gmail.com wrote:
. Also, I heartily recommend the talks to
 those not entirely convinced of the necessity of private/const/frozen
 features. Mark makes a pretty good case for encapsulation as a necessary
 building block for ocap-based security

If I understood Mark correctly, the features needed for SES are
already part of ES.5 and are shipping in browsers (and hence don't
bear upon future features).  Did I misunderstand?

jjb
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-03 Thread Mark S. Miller
On Thu, Nov 3, 2011 at 2:10 PM, John J Barton
johnjbar...@johnjbarton.comwrote:

 On Thu, Nov 3, 2011 at 12:52 PM, Tom Van Cutsem tomvc...@gmail.com
 wrote:
 . Also, I heartily recommend the talks to
  those not entirely convinced of the necessity of private/const/frozen
  features. Mark makes a pretty good case for encapsulation as a necessary
  building block for ocap-based security

 If I understood Mark correctly, the features needed for SES are
 already part of ES.5 and are shipping in browsers


That is correct. Any browser on which 
http://es-lab.googlecode.com/svn/trunk/src/ses/explicit.html passes, which
includes Chrome 16, FF Nightly 10, and WebKit Nightly r98831. Opera 12
alpha build 1116 and IE 10 preview 2 both fall short by only one bug that
both teams are aware of and that test262 tests for, so I expect/hope the
release of both will also be adequate.



 (and hence don't bear upon future features).  Did I misunderstand?


These do bear on future features in three ways:


1) Future features could easily destroy all the security gains that ES5
achieved. As an example, for a long time it wasn't clear -- to me at least
-- how freeze should affect the ability to mutate hidden own properties,
i.e., own properties named by private names. The two obvious answers are
a) hidden own properties are treated just like normal own properties --
freeze makes them non-configurable and (if data) non-writable
b) hidden own properties are completely exempt from the constraints imposed
by freeze.
However, both of these answers would decrease rather than increase
security. Further, #b introduces a capability leak, and so would be fatal
for SES. The answer we settled on at the last meeting is
c) hidden own properties that already exist are exempt from freeze and
seal constraints. However, once an object is non-extensible (whether by
freeze, seal, or preventExtensions), then new hidden own properties
cannot be added to it.


2) The notorious Ch16 exemptions as stated in ES5.1 
http://es5.github.com/#x16, renders all security reasoning necessarily
unsound. For example, an implementation that introduced a non-configurable
ambient method for deleting all the user's files would still be considered
conformant. Going forward, we should make at least 
http://wiki.ecmascript.org/doku.php?id=conventions:make_non-standard_properties_configurable
normative. Beyond this, we need to understand what is the least additional
Ch16 reform needed to enable security reasoning to be sound.


3) Although SES is *formally* an object-capability language, i.e., it has
all the formal properties required by the object-capability model, it has
bad usability properties for writing defensive abstractions, and therefore
bad usability properties for use as an object-capability language or for
serious software engineering. One example:

In a SES environment, or, for present purposes, an ES5/strict environment
in which all primordial built-in objects are transitively frozen, say Alice
uses the following abstraction:

function makeTable() {
  var array = [];
  return Object.freeze({
add: function(v) { array.push(v); },
store: function(i, v) { array[i] = v; },
get: function(i) { return array[i]; }
  });
}

Say she uses it to make a table instance with three methods: add, store,
and get. She gives this instance to Bob. Alice and Bob are mutually
suspicious. All of us as programmers, looking at this code, can tell that
Alice intended the table abstraction to encapsulate the array. Given just a
table instance, can Bob nevertheless obtain direct access to the underlying
array?

If you've already seen this puzzle and know the answer, please don't post.
If no one else has posted the correct answer in 24 hours, I will.

Note that I don't see any realistic way to fix problem #3 in the ES.next
language. My point is only that defensive programming is tricky even after
you've gotten all the formal properties you need. As ES.next introduces
various new abstraction mechanisms, whether classes, enhanced object
literals, proxies, modules, or private names, the design of these can
either help or hurt those attempting to write defensive abstractions. Any
class abstraction that is only useful for making indefensible instances is
worse than useless -- it is actively harmful, both to security and to
serious software engineering.



-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Lecture series on SES and capability-based security by Mark Miller

2011-11-03 Thread Douglas Crockford

On 11:59 AM, Mark S. Miller wrote:
Note that I don't see any realistic way to fix problem #3 in the 
ES.next language. My point is only that defensive programming is 
tricky even after you've gotten all the formal properties you need. As 
ES.next introduces various new abstraction mechanisms, whether 
classes, enhanced object literals, proxies, modules, or private names, 
the design of these can either help or hurt those attempting to write 
defensive abstractions. Any class abstraction that is only useful for 
making indefensible instances is worse than useless -- it is actively 
harmful, both to security and to serious software engineering.


I share your concern about the unintended consequences of new features. 
The dangers are very real, and the patterns can be extremely subtle.


But while #3 is not fixable, there are features of ES5 that make it 
easier to live with. For example, if you had built makeTable with


var array = Object.create(null),
length = 0;

and adapted the methods accordingly, then in this example, the leakage 
could have been avoided without excessive trickiness. I think this level 
of practice is teachable.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss