为什么用变量调用数组索引是不好的做法?
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érable", "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
还没有被篡改过。
这不一定是全貌,但它确实说明了一点。
查看以下资源,其中更详细地阐述了为什么这是一个问题以及一些替代解决方案:
- https://github.com/nodesecurity/eslint-plugin-security/blob/master/docs/the-dangers-of-square-bracket-notation.md
- Securely set unknown property (mitigate square bracket object injection attacks) utility function
这本身并不是一个坏习惯,因为您确实想要开发一个系统并使其安全。很难想象系统的安全风险会比导致该系统不存在的风险更高。
然而,不允许使用变量来动态 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 用户浏览器发送的请求。
我目前正在 Javascript 开发一个小游戏,我正在使用 Codacy 检查我的代码并帮助我清理它。
最常见的错误之一是 Generic Object Injection Sink (security/detect-object-injection)。
当我尝试使用变量访问数组中的值时会发生这种情况。就像这个例子:
function getValString(value)
{
var values = ["Misérable", "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
还没有被篡改过。
这不一定是全貌,但它确实说明了一点。
查看以下资源,其中更详细地阐述了为什么这是一个问题以及一些替代解决方案:
- https://github.com/nodesecurity/eslint-plugin-security/blob/master/docs/the-dangers-of-square-bracket-notation.md
- Securely set unknown property (mitigate square bracket object injection attacks) utility function
这本身并不是一个坏习惯,因为您确实想要开发一个系统并使其安全。很难想象系统的安全风险会比导致该系统不存在的风险更高。
然而,不允许使用变量来动态 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 用户浏览器发送的请求。