为什么用变量调用数组索引是不好的做法?

Why is it bad pratice calling an array index with a variable?

我目前正在 Javascript 开发一个小游戏,我正在使用 Codacy 检查我的代码并帮助我清理它。

最常见的错误之一是 Generic Object Injection Sink (security/detect-object-injection)。

当我尝试使用变量访问数组中的值时会发生这种情况。就像这个例子:

function getValString(value)
{
    var values = ["Mis&eacuterable", "Acceptable", "Excellente", "Divine"];
    return values[value];
}

function 用于在屏幕上显示项目的值字符串。它接收一个“值”,可以是 0、1、2 或 3 和 returns 值的字符串。

现在这是我的问题:

Codacy 告诉我应该禁止使用 var[var],因为它会导致安全问题,而且我对 Javascript 还很陌生,我想知道为什么以及在那种情况。

这里存在的安全问题是 value 的字符串化值可能正在访问从对象的 __proto__ 分层原型继承的 属性,而不是实际的 属性 对象本身。

例如,考虑 value"constructor" 的字符串文字的情况。

const property = "constructor";
const object = [];
const value = object[property];

在此上下文中 value 的结果将解析为 Array() 函数 - 它作为对象原型的一部分继承,而不是 [=18] 的实际 属性 =] 变量。此外,被访问的对象可能已经覆盖了默认继承的 Object.prototype 属性的 any,这可能是出于恶意目的。


可以通过执行 object.hasOwnProperty(property) 条件检查以确保对象 实际上 具有此 属性 来部分防止此行为。例如:

const property = "constructor";
const object = [];
if (object.hasOwnProperty(property)) {
    const value = object[property];
}

注意,如果我们怀疑被访问的对象可能是恶意的或重写了hasOwnProperty方法,可能需要直接使用从原型继承的Object hasOwnProperty:Object.prototype.hasOwnProperty.call(object, property)
当然,这是假设我们的 Object.prototype 还没有被篡改过。

这不一定是全貌,但它确实说明了一点。


查看以下资源,其中更详细地阐述了为什么这是一个问题以及一些替代解决方案:

这本身并不是一个坏习惯,因为您确实想要开发一个系统并使其安全。很难想象系统的安全风险会比导致该系统不存在的风险更高。

然而,不允许使用变量来动态 create/use/update 索引实际上减少了您对 hard-coding 任何可用于引用数组项或对象成员的索引的选择.

不允许索引大大减少了您的选择,以至于它威胁到您可能想要在 Javascript 中创建的任何系统都不存在。让我们看看一些 use-cases:

循环次数:

for (let index = 0; index < arr.length; index++) {
    //do whatever with arr[index]
}

当然,while 循环也是如此。

在循环中

for (let index in variable) {
    //do whatever with arr[index]
}

循环次数

for (let item of variable) {
    // do whatever with item
}

动态查找值

这实际上有无限多种用途,上面的例子都是它的具体案例。示例:

function getItem(arr, index) {
    return arr[index];
}

总结

动态索引对漏洞利用的恐惧,相当于一颗流星命中准确地点和准确时间的恐惧。当然,我们不能排除它,但人不能生活在恒定的环境中。害怕 low-chanced 灾难。同样,如果有不合理的、偏执的恐惧,编程也是不可能的。因此,与其因为漏洞利用的可能性而完全拒绝动态索引,我们还必须参考可能发生的实际漏洞利用。如果不允许我们使用动态实例,那么无论我们要开发什么系统,如果它不是简单的饼,就不会存在。所以,无论我们害怕什么威胁,都应该以其他方式加以保护。

示例:您从 data-source 中检索值并且有一个信用卡 IBAN 字段。是的,如果将其显示给非所有者的用户,则风险很高。但是您应该通过仅使用外部来源的索引来使 IBAN 不可用来防止这种情况发生,例如 POST 用户浏览器发送的请求。