Javascript 在无法恢复原始构造函数的情况下替换内置日期

Javascript 在无法恢复原始构造函数的情况下替换内置日期,javascript,security,Javascript,Security,我想替换JavaScriptVM中的日期(V8,但这不是V8特有的),并使其无法访问原始的日期构造函数。这意味着是防御定时攻击的一部分,比如在同一进程(但不同的JavaScript VM)中运行多租户JavaScript的Spectre。其思想是拒绝访问高分辨率计时器。出于同样的原因,Cloudflare在他们的员工中也这样做。只有在IO发生时,时间才会提前,而不是在计算过程中。我知道还有其他的方法来构造计时器,但我只关注这个问题的日期 我认为这可以用纯JavaScript实现,这是我的尝试。运

我想替换JavaScriptVM中的日期(V8,但这不是V8特有的),并使其无法访问原始的日期构造函数。这意味着是防御定时攻击的一部分,比如在同一进程(但不同的JavaScript VM)中运行多租户JavaScript的Spectre。其思想是拒绝访问高分辨率计时器。出于同样的原因,Cloudflare在他们的员工中也这样做。只有在IO发生时,时间才会提前,而不是在计算过程中。我知道还有其他的方法来构造计时器,但我只关注这个问题的日期

我认为这可以用纯JavaScript实现,这是我的尝试。运行此命令后,有没有办法恢复原始日期构造函数?有没有一种方式在功能上不同于内置日期-某种可能破坏向后兼容性的方式

// 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);

是的,这似乎是一个不错的实现,除了(全局。)
Date
Date.prototype.constructor
之外,没有其他对内置的引用。通过使用ES6功能,如
new.target
和rest/spread语法,可以稍微改进被覆盖的
Date
。不过,这是否真正安全在很大程度上取决于您的环境。它是否提供对其他领域的访问(如浏览器中的iFrame或node.js中的vm模块),您是否也控制这些领域?还有其他内置函数允许通过间接方式构建本机日期对象吗?@Bergi感谢您的关注。也感谢分享-我看到new.target将有多大的改进。我想我看到了如何使用rest/spread语法。我试试看。该环境是嵌入式V8(不是不安全的节点),没有eval/函数构造函数或workers/共享内存。我将采取一些步骤来锁定setTimeout/setInterval,并且没有高精度计时器。我知道没有其他方法可以得到一个日期,但我会更仔细地看。@Bergi我用你的建议更新了代码,它相当干净,没有我认为不需要的未绑定的东西。