如何检测setTimeout等原生函数是否被猴子补丁/Polyfill?求可靠方案
检测原生函数是否被猴子补丁的更优方法
针对setTimeout这类原生函数被猴子补丁或Polyfill的检测,单纯通过函数自身的toString()判断是否包含[native code]的方法很容易被绕过——攻击者只需重写目标函数的toString方法,就能伪造返回结果。以下是几种更可靠的检测方案:
1. 调用原生Function.prototype.toString检测
即使目标函数的toString被篡改,我们可以直接调用未被污染的Function.prototype.toString来获取函数的真实字符串表示:
const isNativeFunction = (fn) => { return Function.prototype.toString.call(fn).includes('[native code]'); }; // 检测示例 console.log(isNativeFunction(setTimeout)); // 原生函数返回true,被篡改则返回false
注意:该方法的前提是Function.prototype.toString本身未被攻击者篡改,不过这种极端污染场景在多数情况下很少见。
2. 通过独立iframe获取干净原生函数对比
浏览器中,iframe会创建一个独立的执行环境,其中的原生函数未被当前页面脚本修改。我们可以借助这个特性获取纯净的原生函数,再与当前环境的函数做引用对比:
function getCleanNativeTimeout() { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.body.appendChild(iframe); const nativeTimeout = iframe.contentWindow.setTimeout; document.body.removeChild(iframe); return nativeTimeout; } // 检测示例 const cleanNative = getCleanNativeTimeout(); console.log(setTimeout === cleanNative); // 原生函数返回true,被篡改则返回false
这种方法的可靠性极高,除非攻击者能实现跨iframe的环境污染,否则很难绕过。
3. 辅助判断:检查函数的固有属性
原生函数会带有一些固定的属性特征,比如setTimeout的length属性为2(对应它的两个必填形参:回调函数、延迟时间),可以作为辅助验证项:
console.log(setTimeout.length === 2); // 原生函数返回true
不过该方法仅作辅助,因为部分合规的Polyfill也会模拟这些属性,不能单独作为判断依据。
内容的提问来源于stack exchange,提问作者Adassko
相关产品推荐
相关产品推荐

