检查是不是在 JavaScript 中覆盖了全局属性/函数

Posted

技术标签:

【中文标题】检查是不是在 JavaScript 中覆盖了全局属性/函数【英文标题】:Check if a global property/function has been overwritten in JavaScript检查是否在 JavaScript 中覆盖了全局属性/函数 【发布时间】:2012-05-03 05:03:36 【问题描述】:

javascript 可以很容易地覆盖全局对象的属性和函数。我想找到一种方法来检查全局属性的原始版本是否已被替换。

考虑有人把它放在他们的 html 中:

<script type="text/javascript">
    window.encodeURIComponent = eval;
</script>
<script type="text/javascript" src="myscript.js"></script>

如果 myscript.js 在某处调用 encodeURIComponent 函数,它现在的行为将无法预测。那么有没有一种方法可以检查 myscript.js 中是否有人在我使用之前覆盖了该函数?

【问题讨论】:

【参考方案1】:

我唯一知道的是一种简单的方法,可以分析函数的字符串表示。通常,代码

window.encodeURIComponent.toString()

应该产生这样的东西:

function encodeURIComponent()  [native code] 

可以很容易地解析出关键信息function encodeURIComponent

如果函数被eval 覆盖,如您的示例所示,您将获得:

function eval()  [native code] 

一般来说,为了检查 window 属性,您可以创建一个假 iframe 并将 window.[property].toString()iframe.contentWindow.[property].toString() 进行比较。如果比较给出false,则属性已更改。

【讨论】:

这是一种非常聪明的跨浏览器方式。 谢谢斯坦。你还知道如何确保eval 的toString 属性没有被function () return "function encodeURIComponent() [native code] "; 之类的东西覆盖吗? 而不是解析和调用toString,你可以简单地做到这一点window.encodeURIComponent.name..无论如何,有更精确的方法来实现这个***.com/a/10266791/474290 @ft1:恐怕,我不知道解决方案。 对于希望在安全上下文中使用此功能的任何人,您不能依赖此检查,除非您可以确保没有恶意代码在其之前运行。恶意库可以覆盖属性并使此检查无用。【参考方案2】:

在一个脚本中执行此操作的一种有趣方法是比较函数原型

默认情况下 - typeof window.encodeURIComponent.prototype === "undefined"

但是如果有人通过

重新定义了这个函数

window.encodeURIComponent = function() eval(); 我们会得到

typeof window.encodeURIComponent.prototype === "Object"

PS:这种方法比其他方法更可靠,但它不会给你 100% 的保证。 JavaScript 是所有对象,都在运行时.. 只需与此一起生活..

更新 你可以结合这两种方法.. mine 和 @Stans..

这个例子不起作用,因为我没有使用eval - eval 默认情况下也有原型“未定义”..所以你可以这样做

window.encodeURIComponent.name === "encodeURIComponent" 
//to make shure that user won't use EVAL 
&& typeof window.encodeURIComponent.prototype === "undefined" 
//to make shure that user won't use self defined function

【讨论】:

Ai_boy,我似乎无法重现。 typeof window.encodeURIComponent.prototype 在这两种情况下都是 "undefined"【参考方案3】:

这是特定于浏览器的,绝对不适用于非功能,但是:

调用函数的toString 方法应该会产生类似的结果:

Chrome:

"function encodeURIComponent()  [native code] "

Firefox:

"function encodeURIComponent() 
    [native code]
"

IE 7/8/9:
"
function encodeURIComponent() 
    [native code]

" 

观察函数名称是否与属性名称匹配,并且其主体被“[native code]”替换。我们的想法是从该字符串中删除所有空格并将其与预期结果进行比较,"functionxxx()[nativecode]"

我不知道它是否适用于所有浏览器/功能,这是反复试验:

var pattern = 'function' + propertyName + '()[nativecode]';
var func = window[propertyName].toString();
if(func.replace(/\s+/g, '') !== pattern) 
    throw new Error("Property window." + propertyName + " has been modified!");

【讨论】:

【参考方案4】:

这个怎么样?

function isNativeWindowProperty(propertyName) 
    var result = false;
    var iframe = document.createElement('iframe');
    iframe.src = 'javascript:;';
    document.getElementsByTagName('body')[0].appendChild(iframe);
    if (window[propertyName].toString() === iframe.contentWindow[propertyName].toString()) 
        // check window[propertyName].toString override
        if (window[propertyName].toString.toString() === iframe.contentWindow[propertyName].toString.toString()) 
            result = true;
        
    
    iframe.parentNode.removeChild(iframe);
    return result;
;

console.log(isNativeWindowProperty('alert'));  // true

window.alert = function() ;
console.log(isNativeWindowProperty('alert'));  // false

window.alert.toString = function() 
    return 'function alert()  [native code] ';
;
console.log(isNativeWindowProperty('alert'));  // false

【讨论】:

也许您可以添加一些文字来解释您的代码如何回答问题? 有趣的方法 - 虽然 document.createElement 本身可能已经被猴子修补,并且可能会修改创建的 iframe 的内容...... 我将这个想法和其他一些想法开发成一个脚本,该脚本扫描window 对象以查找修改的构造函数和类方法 - 我将结果发布在类似的线程here。【参考方案5】:

在 JavaScript 中有一种简单的方法 :) 但是你必须能够访问 HTML,所以你不能在一个脚本中使用这个方法..

function 是一个 OBJECT.. 所以我们可以保存一个指向对象的链接,然后比较这些链接。把一个函数想象成一个简单的对象。如何比较对象?

<script type="text/javascript">
    var a = window.encodeURIComponent;  // a === window.encodeURIComponent -> true
</script>
<script type="text/javascript">
    window.encodeURIComponent = eval; // a === window.encodeURIComponent -> false
</script>
<script type="text/javascript" src="myscript.js">
    if (a !== window.encodeURIComponent) 
    
        throw new Error('Someone redefined function');
    
</script>

【讨论】:

以上是关于检查是不是在 JavaScript 中覆盖了全局属性/函数的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们在 Javascript 中使用术语阴影而不是覆盖?

使用 inotify 检查监视文件夹中的文件是不是被覆盖

提交中单个文件更改时的全局与单个文件覆盖阈值

如何检查在 C# 的全局类中找到的数组中是不是存在对象

自学JavaScript 变量-作用域

JavaScript - 如何检查是不是在数字输入字段中输入了字母字符或符号[重复]