Le 19/01/2012 06:44, Brendan Eich a écrit :
Use __proto__ in object literals to do a put (assuming that a
__proto__ getter/setter was created in Object.prototype) instead of a
defineProperty? All modes or only nonstrict mode?
Allen: Make such use of __proto__ to be a synonym for <|. If a <| is
already present, it's an error.
DaveH: __proto__ is ugly. Don't want it in the language forever.
Waldemar: What about indirect [] expressions that evaluate to
"__proto__"? In Firefox they evaluate to accesses that climb the
prototype chain and usually reach a magic
getter/setter-that-isn't-a-getter-setter named __proto__ that sits on
Object.prototype.
MarkM: Likes the ability to delete __proto__ setter and thereby
prevent anything in the frame from mutating prototypes.
Waldemar: How do you guard against cross-frame prototype mutations?
DaveH: __proto__ is in the "omg, what were we thinking" category.
Waldemar: Opposed to making __proto__ mutate prototypes other than at
object construction. This is getting insanely complex.
Unresolved.
One point not recorded here: given MarkM's argument for
Object.prototype.__proto__ as the one property to delete to remove
this old beast, what kind of property does that appear to be to ES5's
Object.getOwnPropertyDescriptor? Arguments pro and con for data
property (as it appears to be in SpiderMonkey) vs. accessor (JSC
intended to move to that from its hardcoded magic id handling in Get
and Put code).
Argument for data property facade: an accessor allows extracting the
setter from the property descriptor, call it stolen__proto__setter.
Then if one makes an object with a bespoke proto-object but not
delegating to Object.prototype:
var o = { __proto__: Object.create(null) };
an attacker could mutate o's [[Prototype]] via
stolen__proto__setter.call(o, evil_proto). This is not possible if
Object.prototype.__proto__ reflects as a data property, because o's
two-level proto chain is cut off from Object.prototype, so no further
means of updating [[Prototype]] is available.
Every time I've been thinking of an issue like this, the solution I've
found was "whoever runs first wins".
Assuming __proto__ is an accessor of Object.prototype:
If trusted code runs first, it can protect itself by removing the setter
and making the property non-configurable.
If an attacker runs first... you're screwed as you made the demonstration.
Even in the data property case, if an attacker runs first, she can
probably change quite a lot of built-in prototypes, change built-in
properties (of any object it has access to) to non-configurable
accessors, add loggers, all over the place, return evil values to
function calls.
I have a script [1] which replaces every function with a function that
is semantically equivalent, but logs "this", the arguments and the
return value. If an attacker runs this before any other script (before
initSES.js, for instance :-° ), but adds more harmful than loggers, she
can really do nasty stuffs.
It seems that the threat may be a bit smaller if __proto__ is a data
property, but I'm not sure it's significantly smaller than all the
things you can already do if an attacker runs first.
If you run first, __proto__ being an accessor or a data property does
not make a difference, you can protect yourself in any case.
The accessor has the advantage that you can have fine-grained control
over who can change and what cannot. Specifically, you can bind
__proto__setter, and share this with someone so that this party can
change the prototype of a given object (or set of objects) you've
chosen. A data property is more "all (everyone can change the prototype
of every object inheriting from Object.prototype) or nothing (or no one
can change the prototype of any object)".
The question that remains is "how can you make sure your trusted run
first?" which, I think goes beyond ECMAScript scope and should be
considered in each context (browser, node.js, etc.)
For the browser, I can't think of a good solution that would be backward
compatible and efficient. Suggestions welcome.
David
[1] https://github.com/DavidBruant/JSTraversers (not really production
ready and makes some browser crash or hang, because they don't seem to
appreciate their DOM builtins being traversed)
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss