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

Claus Reinke claus.reinke at talk21.com
Fri Nov 4 12:11:47 PDT 2011

>>  // 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 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!

pity.. still, it was an interesting exercise.

>> 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?

The source being run/being "attacked". Re-directing the loader
to rewrite the source could strip away "security" features even
easier than overwriting non-frozen standard objects.


More information about the es-discuss mailing list