使用脚本可以用覆盖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
也被覆盖的情况下,这才会失败,并且这种修补可以在多领域环境中检测到。