如何保护全局变量(窗口)不被覆盖

时间:2019-05-29 08:37:48

标签: javascript typescript security

我目前正在从事安全非常重要的项目。默认情况下,所有全局变量/属性(例如Promise甚至crypto都可以被覆盖。

有没有一种方法可以防止它们被覆盖?

示例:

window.crypto.getRandomValues = () => { return [1] }

window.crypto.getRandomValues(new Uint32Array(1))[0] // 1

我的第一个想法是使用Object.freeze()来锁定对象,但是可以简单地覆盖Object.freeze方法,使其无所事事。

我们已经非常选择了我们使用的依赖项,但是我仍然要确保这些变量不会被覆盖。或者至少检测它们是否被覆盖。

1 个答案:

答案 0 :(得分:0)

免责声明:这只是一个粗略的轮廓,未经彻底测试。我确定还有更多问题要解决。


freezing窗口对象不是选项,这只会引起问题,但是可能像window.crypto这样的对象?

但是您可以重新定义属性,使其即使在窗口对象上也无法更改

function freezeProp(target, propertyName) {
  const { value, get = () => value, set = () => void 0, ...desc } = Object.getOwnPropertyDescriptor(target, propertyName);
  Object.defineProperty(target, propertyName, { ...desc, get, set, configurable: false });
}

freezeProp(window, "crypto");

但是,只有在可以确保您是第一个运行的脚本的情况下,这些方法才可行。

如果您引用了某些方法,也可以确定它们是否已更改;而我们又回到了第一个运行的脚本。


但是,如果您不确定全局范围是否已被破坏,为什么不获取一个新的窗口对象?

window.crypto.getRandomValues = () => {
  return [1]
};

const secure = (() => {
  let iframe = document.createElement("iframe");
  document.body.appendChild(iframe);
  const contentWindow = iframe.contentWindow;
  document.body.removeChild(iframe);
  return contentWindow;
})();

var a = window.crypto.getRandomValues(new Uint8Array(1));
console.log(a);

var b = secure.crypto.getRandomValues(new Uint8Array(1));
console.log(b);