为啥用变量调用数组索引是不好的做法?
Posted
技术标签:
【中文标题】为啥用变量调用数组索引是不好的做法?【英文标题】:Why is it bad pratice calling an array index with a variable?为什么用变量调用数组索引是不好的做法? 【发布时间】:2017-12-06 13:02:52 【问题描述】:我目前正在用 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,并返回值的字符串。
现在这是我的问题:
Codacy 告诉我应该禁止使用 var[var]
,因为它会导致安全问题,而且由于我对 Javascript 还比较陌生,所以我想知道为什么以及在这种情况下有哪些好的做法。
【问题讨论】:
代码看起来不错。但是,在这里使用开关或查找表会更合适... 不,只是一张价值图:koefficient。还有一个班轮...... 两者都没有回答 OP 的问题 - 为什么将数组索引查找报告为不良安全做法,这是否有效? 对我来说似乎是因为查找依赖于外部函数参数,理论上可以由客户端操作,而客户端本身可能会导致任何不好的东西,如缓冲区溢出或任何被利用的东西。是否没有 codacity 的文档部分来解释这个问题? 我认为 Codacy 应该改进检查,因为只有当用作索引的变量是从外部接收的(例如用户输入或参数)而不是当它是局部变量(例如 for/while 循环计数器)。 【参考方案1】:这里存在的安全问题是value
的字符串化值可能正在访问从对象的__proto__
分层原型继承的属性,而不是对象本身的实际属性。
例如,考虑value
是"constructor"
的字符串文字的场景。
const property = "constructor";
const object = [];
const value = object[property];
value
在此上下文中的结果将解析为 Array()
函数 - 它作为对象原型的一部分被继承,而不是 object
变量的实际属性。此外,被访问的对象可能已经覆盖了任何默认继承的Object.prototype
属性,这可能是出于恶意目的。
通过执行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【讨论】:
【参考方案2】:这本身并不是一个坏习惯,因为您确实想开发一个系统并使其安全。很难想象一个系统的安全风险比导致该系统不存在的风险更高。
然而,不允许使用变量来动态创建/使用/更新索引实际上减少了硬编码任何索引的选项,这些索引可用于引用数组项或对象成员。
不允许索引极大地减少了您的选择,以至于它威胁到您可能想要在 Javascript 中创建的任何系统都不存在。让我们看看一些用例:
编号循环:
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];
总结
由于动态索引而对漏洞利用的恐惧,就相当于对流星击中确切位置和确切时间的恐惧。当然,我们不能排除它,但不能生活在不断的恐惧中低概率的灾难。同样,编程也是不可能的,有不合理的、偏执的恐惧。因此,与其因为存在漏洞利用的可能性而完全拒绝动态索引,我们必须参考可能的实际漏洞利用。如果不允许我们使用动态实例,那么我们要开发的任何系统,如果它不是那么简单,就不会存在。所以,无论我们害怕什么威胁,都应该受到保护。
示例:您从数据源检索值并有一个用于信用卡 IBAN 的字段。是的,如果向不是所有者的用户显示,那风险很高。但是您应该通过仅通过外部资源使用索引(例如用户浏览器发送的 POST 请求)使 IBAN 不可用来防止这种情况发生。
【讨论】:
以上是关于为啥用变量调用数组索引是不好的做法?的主要内容,如果未能解决你的问题,请参考以下文章
为啥直接从 Servlet 访问 DAO 是一种不好的做法?