测试导航器属性是否被getter函数覆盖的可靠方法



使用脚本可以用覆盖Chrome和Firefox中的navigator.plugins属性

Object.defineProperty(navigator, 'plugins', {
get: function() {
return [1, 2, 3, 4, 5];
},
});

因此,基本上该属性是只读的,但使用getter函数可以覆盖它。(不是在控制台中,而是在脚本中(那么我如何测试属性是否被覆盖?

我读到了关于接收函数的toString属性的消息,该属性应该返回[本地代码]

function isNative(fn) {
return (/{s*[native code]s*}/).test('' + fn);
}

现在我的问题是:如何测试getter是否被get:function()覆盖。。在上面

有一些技术可以让您更接近确定函数是否被覆盖:

  • 至少在Chrome中,plugins存在于Navigator.prototype上,而不是window.navigator上。如果代码在Chrome中运行,并且属性直接在navigator上,则它已被覆盖
const definitelyPatched = navigator.hasOwnProperty('plugins');
  • 如果属性已经放在原型上,请检查属性描述符是否与默认值匹配:它应该是可枚举和可配置的。如果不是,则被覆盖
const descriptor = Object.getOwnPropertyDescriptor(Navigator.prototype, 'plugins');
const definitelyPatched = descriptor.set || !descriptor.enumerable || descriptor.configurable;
  • 结合以上内容,一个几乎万无一失的方法是使用Function.prototype.toString.call绕过修补函数的自定义toString

const fn = function() {
return [1, 2, 3, 4, 5];
};
fn.toString = function() {
return '[native code]';
};
Object.defineProperty(Navigator.prototype, 'plugins',
{
get: fn,
});
const descriptor = Object.getOwnPropertyDescriptor(Navigator.prototype, 'plugins');
console.log(Function.prototype.toString.call(descriptor.get));

只有在Function.prototype.toString也被覆盖的情况下,这才会失败,并且这种修补可以在多领域环境中检测到。

最新更新