如何安全评估用户inputexpression式

我想parsing用户的expression式,使用标准的JavaScriptvalidation布尔值,如:

var1 > obj1.prop1 && var2 + 1 <= 5 

由于这个expression式是由用户编写的,我想确定它们是干净的,因为它们将被NodeJS评估为服务器端。

而不是必须parsingexpression式作为文本寻找模式和重新发明车轮,是否有一种方法,我可以使用节点的能力来直接评估expression式没有代码注入的风险?

你可能不喜欢这个答案。 但你必须做工作。 没有魔法弹。

你的问题通过要求“标准的JavaScript”和“没有代码注入的风险”自相矛盾。 你不能有两个。 标准JavaScript允许expression式如'require("fs").rmdirSync("/")'

用户input的expression式必须被限制在严重有限的JavaScript子集中。 在尝试评估input之前,服务器必须validationinput是否限于这个子集。

所以首先你需要仔细考虑有限的子集是允许的。 它看起来像你想允许常量整数像'5',运算符像'>','&&'和'<='。 您还允许访问像'var1''obj1.prop1''var2'这样的variables。 我想你需要非常具体的允许variables的列表。

防止脚本注入的关键是定义一个只包含你知道的安全的子集。 你不应该试图从整个JavaScript开始,排除你认为是危险的东西 – 因为你会错过一些。

一旦仔细定义了expression式可能包含的内容,就需要实现代码来parsing和validationexpression式。 您可能会find一个库或标准代码来执行此操作,但是您必须修改或configuration它才能满足您的特定要求。

一般情况下,无论您最终将使用什么,我都会启动一个评估过程,您可以放弃所有权限,只使用unix域套接字与其通信。 并将您想要评估的代码发送给它。

以root用户身份启动它,然后打开unix域套接字,然后将该特权放到任何人 。

 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沙盒中提到的方法和执行用户提交的JavaScript? 像vm.runInContext('globalVar *= 2;', sandbox); 没有帮助。 但是引用的sandcastle可能是你可以看到的东西,但是即使你使用了一个沙箱库,我仍然会build议在一个孤立的非特权进程中运行它。

就像詹姆斯在回答中所build议的那样,你应该采取将某些特征列入白名单的方式,而不是列入有害的特征。

你可以使用自带的expression式parsing器附带的mathjs库。

网站: http : //mathjs.org/