【问题标题】: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 中是否有人在我使用之前覆盖了该函数?

【问题讨论】:

    标签: javascript overwrite global-object


    【解决方案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..无论如何,有更精确的方法来实现这个stackoverflow.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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-16
        • 2015-04-26
        • 1970-01-01
        • 1970-01-01
        • 2010-09-27
        相关资源
        最近更新 更多