我想分析用户的表达式中使用标准的JavaScript这样的验证,以布尔:如何安全评估用户输入表达式
var1 > obj1.prop1 && var2 + 1 <= 5
因为这个表达式是由用户编写的,我想,以确保它们是干净becase的他们将被用NodeJS评估服务器端。
而不是必须解析表达式作为文本寻找模式和重新发明轮子,有没有一种方法可以使用节点的能力直接评估表达式没有代码注入的风险?
我想分析用户的表达式中使用标准的JavaScript这样的验证,以布尔:如何安全评估用户输入表达式
var1 > obj1.prop1 && var2 + 1 <= 5
因为这个表达式是由用户编写的,我想,以确保它们是干净becase的他们将被用NodeJS评估服务器端。
而不是必须解析表达式作为文本寻找模式和重新发明轮子,有没有一种方法可以使用节点的能力直接评估表达式没有代码注入的风险?
你可能不喜欢这个答案。但你必须做工作。没有魔法弹。
你的问题,要求“标准的javascript”和“无代码注入的风险”自相矛盾。你不能拥有两个。标准JavaScript允许表达式如'require("fs").rmdirSync("/")'
用户输入的表达式必须被限制为严重受限的JavaScript子集。在尝试评估输入之前,服务器必须验证输入是否仅限于该子集。
所以首先你需要仔细考虑一下有限的子集是允许的。它看起来像你想允许常量整数像“5”,运营商如“>”,“& &”和“< =”。您还允许访问像'var1''obj1.prop1''var2'这样的变量。我想你需要对允许变量的列表非常具体。
防止脚本注入,关键是要定义一个子集,其中包括只有你知道是安全的事情。你不应该试图从整个JavaScript开始,排除你认为是危险的东西 - 因为你会错过一些。
一旦您仔细定义了表达式可能包含的内容,您需要实现代码来解析和验证表达式。您可能会找到一个库或标准代码来执行此操作,但您必须修改或配置它才能满足您的特定要求。
在一般情况下,不管您最终会使用什么,我都会启动一个评估过程,您可以放弃所有权限并仅使用unix域套接字与其进行通信。并将你想评估的代码发送给它。
以root用户身份启动它,并打开unix域套接字,然后删除权限nobody。
process.setgid('nobody');
process.setuid('nobody');
一件事,你应该避免是做这样的事情:
const root = global = {};
const require = function() {
console.log('tryed to call require', arguments);
}
eval("require('fs')");
这可能会在第一次看工作,但如与ES6存在的import
关键字引入,所以即使你覆盖require
你仍然可以使用import
加载模块。
另外Safely sandbox and execute user submitted JavaScript?中提到的方法,如vm.runInContext('globalVar *= 2;', sandbox);
也没有帮助。但是引用的sandcastle,可能是你可以看到的东西,但即使你使用沙箱库,我仍然会建议在一个孤立的非特权进程中运行它。
像James在答案中建议您应该采取白名单的方式,而不是列入有害的名单。
您可以使用自带的表达式解析器附带的mathjs
库。
这个的帮助? http://jsep.from.so/ –
@IlayaRajaS很酷的库!,但它不评估表达式,至少我能算出它 – DomingoSL
你是否在linux服务器上运行node.js? –