Darien Valentine (2018-09-17T01:19:25.000Z)
> What is going on here? Can you explain?

A C++/V8 API is used to obtain references to the target and handler from
only the proxy object, even though those objects aren’t supposed to be
available to this ES scope:

https://github.com/nodejs/node/blob/master/lib/util.js#L642-L647

The pair of objects is passed to another function, which in turn may pass
values to the method "ctx.stylize", but that property may have been
previously overwritten from user code:

https://github.com/nodejs/node/blob/master/lib/util.js#L566-L580

AFAICT, fixing the leak (beyond util.js) would be possible by making
`stylize` unconfigurable/unwritable. However there may be other avenues
here — I’m not sure.

> Does that mean this attack is impossible from code loaded into a new
realm as made by the shim or SES?

The exploit isn’t sensitive to realm-of-origin, since util is using v8
internals to get the references, not e.g. a patched version of Proxy. But
it still depends on the proxy object in question being exposed to a context
where util.inspect exists.

In the [issue comment](
https://github.com/nodejs/node/issues/10731#issuecomment-419008987), I
wrote this:

> This exploit can be fixed pretty easily. But I think it’s symptomatic. My
understanding was that V8’s C++ APIs are intended for making external
functionality available to ECMAScript using ECMAScript values and
ECMAScript semantics. Here though, it is being used to bypass ECMAScript
semantics. The behavior seen in the above script isn’t possible in
ECMAScript — but neither is distinguishing between objects which have been
implemented as ordinary objects and objects implemented as proxy exotic
objects.


On Sun, Sep 16, 2018 at 8:06 PM Mark Miller <erights at gmail.com> wrote:

> This is indeed quite scary. I have never used of explored the Node `util`
> API. What is going on here? Can you explain?
>
> The Realms shim and SES (which build on the Realms shim) create an
> environment in which only those globals defined by EcmaScript, not by the
> host, are present by default.
> https://github.com/Agoric/SES/tree/master/demo
> https://rawgit.com/Agoric/SES/master/demo/
> Does that mean this attack is impossible from code loaded into a new realm
> as made by the shim or SES?
>
>
>
> On Sun, Sep 16, 2018 at 12:10 PM Mike Samuel <mikesamuel at gmail.com> wrote:
>
>> Nicely done!
>>
>> One more reason to prefer WeakMaps to properties when relating objects
>> and secrets.
>>
>>
>>
>> On Sun, Sep 16, 2018 at 2:59 PM Darien Valentine <valentinium at gmail.com>
>> wrote:
>>
>>> A few weeks ago I’d commented on an open Node github issue regarding
>>> Proxies and inspection. While the bulk of the comment concerns an opinion
>>> that proxies should not be treated as special case, I included an example
>>> of a mechanism by which the current implementation allows outside code to
>>> access the target and handler objects of a proxy that it does not own.
>>>
>>> On reflection I realized this specific issue might be worth drawing more
>>> attention to.
>>>
>>> ```js
>>> const util = require('util');
>>>
>>> const victim = new Proxy({}, {
>>>   SECRET: 'Nothing outside can access this'
>>> });
>>>
>>> let secret;
>>>
>>> const invariantViolator = {
>>>   [util.inspect.custom](depth, options) {
>>>     const { stylize } = options;
>>>
>>>     options.showProxy = true;
>>>
>>>     options.stylize = (value, color) => {
>>>       secret = value;
>>>       options.stylize = stylize;
>>>       return stylize(value, color);
>>>     };
>>>
>>>     return victim;
>>>   }
>>> };
>>>
>>> util.inspect(invariantViolator);
>>>
>>> console.log(secret); // 'Nothing outside can access this'
>>> ```
>>>
>>> The implication is that even if running Node with no C++ addons, it is
>>> presently possible for proxies to be violated using just the standard lib,
>>> which may be significant from a security perspective. I’m not sure if
>>> that’s the case in practice, but just in case, I figured I should try to
>>> get eyes on it.
>>>
>>> Note that even if this particular hole is patched, the "analog hole" (so
>>> to speak) of just analyzing the string output remains.
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
> --
>   Cheers,
>   --MarkM
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180916/4c4b6378/attachment.html>
valentinium at gmail.com (2018-09-17T01:27:08.530Z)
> What is going on here? Can you explain?

A C++/V8 API is used to obtain references to the target and handler from
only the proxy object, even though those objects aren’t supposed to be
available to this ES scope, in `formatValue`:

https://github.com/nodejs/node/blob/master/lib/util.js#L642-L647

The pair of objects is passed to another function, which in turn may pass
values to the method `ctx.stylize` (via `formatValue` again), but that property may have been
previously overwritten from user code:

https://github.com/nodejs/node/blob/master/lib/util.js#L566-L580

https://github.com/nodejs/node/blob/master/lib/util.js#L628

AFAICT, fixing the leak (beyond util.js) would be possible by making
`stylize` unconfigurable/unwritable. However there may be other avenues
here — I’m not sure.

> Does that mean this attack is impossible from code loaded into a new realm as made by the shim or SES?

The exploit isn’t sensitive to realm-of-origin, since util is using v8
internals to get the references, not e.g. a patched version of Proxy. But
it still depends on the proxy object in question being exposed to a context
where util.inspect exists.

In the [issue comment](
https://github.com/nodejs/node/issues/10731#issuecomment-419008987), I
wrote this:

> This exploit can be fixed pretty easily. But I think it’s symptomatic. My understanding was that V8’s C++ APIs are intended for making external functionality available to ECMAScript using ECMAScript values and ECMAScript semantics. Here though, it is being used to bypass ECMAScript semantics. The behavior seen in the above script isn’t possible in ECMAScript — but neither is distinguishing between objects which have been implemented as ordinary objects and objects implemented as proxy exotic objects.
valentinium at gmail.com (2018-09-17T01:26:33.680Z)
> What is going on here? Can you explain?

A C++/V8 API is used to obtain references to the target and handler from
only the proxy object, even though those objects aren’t supposed to be
available to this ES scope:

https://github.com/nodejs/node/blob/master/lib/util.js#L642-L647

The pair of objects is passed to another function, which in turn may pass
values to the method `ctx.stylize` (via `formatValue`), but that property may have been
previously overwritten from user code:

https://github.com/nodejs/node/blob/master/lib/util.js#L566-L580

https://github.com/nodejs/node/blob/master/lib/util.js#L628

AFAICT, fixing the leak (beyond util.js) would be possible by making
`stylize` unconfigurable/unwritable. However there may be other avenues
here — I’m not sure.

> Does that mean this attack is impossible from code loaded into a new realm as made by the shim or SES?

The exploit isn’t sensitive to realm-of-origin, since util is using v8
internals to get the references, not e.g. a patched version of Proxy. But
it still depends on the proxy object in question being exposed to a context
where util.inspect exists.

In the [issue comment](
https://github.com/nodejs/node/issues/10731#issuecomment-419008987), I
wrote this:

> This exploit can be fixed pretty easily. But I think it’s symptomatic. My understanding was that V8’s C++ APIs are intended for making external functionality available to ECMAScript using ECMAScript values and ECMAScript semantics. Here though, it is being used to bypass ECMAScript semantics. The behavior seen in the above script isn’t possible in ECMAScript — but neither is distinguishing between objects which have been implemented as ordinary objects and objects implemented as proxy exotic objects.
valentinium at gmail.com (2018-09-17T01:26:24.263Z)
> What is going on here? Can you explain?

A C++/V8 API is used to obtain references to the target and handler from
only the proxy object, even though those objects aren’t supposed to be
available to this ES scope:

https://github.com/nodejs/node/blob/master/lib/util.js#L642-L647

The pair of objects is passed to another function, which in turn may pass
values to the method `ctx.stylize` (via `formatValue`), but that property may have been
previously overwritten from user code:

https://github.com/nodejs/node/blob/master/lib/util.js#L566-L580
https://github.com/nodejs/node/blob/master/lib/util.js#L628

AFAICT, fixing the leak (beyond util.js) would be possible by making
`stylize` unconfigurable/unwritable. However there may be other avenues
here — I’m not sure.

> Does that mean this attack is impossible from code loaded into a new realm as made by the shim or SES?

The exploit isn’t sensitive to realm-of-origin, since util is using v8
internals to get the references, not e.g. a patched version of Proxy. But
it still depends on the proxy object in question being exposed to a context
where util.inspect exists.

In the [issue comment](
https://github.com/nodejs/node/issues/10731#issuecomment-419008987), I
wrote this:

> This exploit can be fixed pretty easily. But I think it’s symptomatic. My understanding was that V8’s C++ APIs are intended for making external functionality available to ECMAScript using ECMAScript values and ECMAScript semantics. Here though, it is being used to bypass ECMAScript semantics. The behavior seen in the above script isn’t possible in ECMAScript — but neither is distinguishing between objects which have been implemented as ordinary objects and objects implemented as proxy exotic objects.
valentinium at gmail.com (2018-09-17T01:25:19.399Z)
> What is going on here? Can you explain?

A C++/V8 API is used to obtain references to the target and handler from
only the proxy object, even though those objects aren’t supposed to be
available to this ES scope:

https://github.com/nodejs/node/blob/master/lib/util.js#L642-L647

The pair of objects is passed to another function, which in turn may pass
values to the method `ctx.stylize` (via `formatValue`), but that property may have been
previously overwritten from user code:

https://github.com/nodejs/node/blob/master/lib/util.js#L566-L580

AFAICT, fixing the leak (beyond util.js) would be possible by making
`stylize` unconfigurable/unwritable. However there may be other avenues
here — I’m not sure.

> Does that mean this attack is impossible from code loaded into a new realm as made by the shim or SES?

The exploit isn’t sensitive to realm-of-origin, since util is using v8
internals to get the references, not e.g. a patched version of Proxy. But
it still depends on the proxy object in question being exposed to a context
where util.inspect exists.

In the [issue comment](
https://github.com/nodejs/node/issues/10731#issuecomment-419008987), I
wrote this:

> This exploit can be fixed pretty easily. But I think it’s symptomatic. My understanding was that V8’s C++ APIs are intended for making external functionality available to ECMAScript using ECMAScript values and ECMAScript semantics. Here though, it is being used to bypass ECMAScript semantics. The behavior seen in the above script isn’t possible in ECMAScript — but neither is distinguishing between objects which have been implemented as ordinary objects and objects implemented as proxy exotic objects.
valentinium at gmail.com (2018-09-17T01:20:49.412Z)
> What is going on here? Can you explain?

A C++/V8 API is used to obtain references to the target and handler from
only the proxy object, even though those objects aren’t supposed to be
available to this ES scope:

https://github.com/nodejs/node/blob/master/lib/util.js#L642-L647

The pair of objects is passed to another function, which in turn may pass
values to the method "ctx.stylize", but that property may have been
previously overwritten from user code:

https://github.com/nodejs/node/blob/master/lib/util.js#L566-L580

AFAICT, fixing the leak (beyond util.js) would be possible by making
`stylize` unconfigurable/unwritable. However there may be other avenues
here — I’m not sure.

> Does that mean this attack is impossible from code loaded into a new realm as made by the shim or SES?

The exploit isn’t sensitive to realm-of-origin, since util is using v8
internals to get the references, not e.g. a patched version of Proxy. But
it still depends on the proxy object in question being exposed to a context
where util.inspect exists.

In the [issue comment](
https://github.com/nodejs/node/issues/10731#issuecomment-419008987), I
wrote this:

> This exploit can be fixed pretty easily. But I think it’s symptomatic. My understanding was that V8’s C++ APIs are intended for making external functionality available to ECMAScript using ECMAScript values and ECMAScript semantics. Here though, it is being used to bypass ECMAScript semantics. The behavior seen in the above script isn’t possible in ECMAScript — but neither is distinguishing between objects which have been implemented as ordinary objects and objects implemented as proxy exotic objects.