Replace builtin Date without being able to recover original constructor

做~自己de王妃 提交于 2021-01-29 08:08:17

问题


I want to replace Date inside a JavaScript VM (V8 but this is not specific to V8), and make it impossible to access the original Date constructor. This is meant to be one part of a defence against timing attacks like Spectre with multi-tenant JavaScript running in the same process (but different JavaScript VM.) The idea is to deny access to high resolution timers. Cloudflare does this in their Workers, for the same reason. Time is advanced only when IO happens, not during computation. I know there are other ways to construct a timer, but I'm just focused on Date for this question.

I think this can be done in pure JavaScript, and this is my attempt. Is there a way to get the original Date constructor back after running this? Is there a way this differs functionally from the builtin Date - something that could break backwards compatibility?

// Current UNIX timestamp in milliseconds, but that we set manually on each call to runTasks.
// not advancing time during computation is one of our defenses against Spectre attacks.
let NOW = Date.now();

export function setDate(unixTimestampMillis) {
    NOW = unixTimestampMillis;
}

Date = function (BuiltinDate) {
    function Date(...args) {
        if (new.target === undefined) {
            // This is the deprecated naked Date() call which returns a string
            return (new BuiltinDate(NOW)).toString();
        }
        // Otherwise it was the constructor called with new
        if (args.length === 0) {
            // Return the "current" time.
            return new BuiltinDate(NOW);
        }
        // Build a Date with the specified datetime
        return new BuiltinDate(...args);
    }

    // Make a copy of the BuiltinDate "class" and replace the constructor,
    // It needs to be impossible for the user to grab an reference to BuiltinDate.
    Date.prototype = BuiltinDate.prototype;
    BuiltinDate.prototype.constructor = Date;

    // Add the static methods now(), UTC(), and parse() - all of which return a numeric timestamp
    function now() {
        return NOW;
    }
    Date.now = now;
    Date.parse = BuiltinDate.parse; // returns a number
    Date.UTC = BuiltinDate.UTC; // returns a number

    return Date;
}(Date);

来源:https://stackoverflow.com/questions/64625568/replace-builtin-date-without-being-able-to-recover-original-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!