简体   繁体   English

如何安全地评估用户输入表达式

[英]How to safely evaluate user input expressions

I want to parse user's expressions that validates to booleans using standard javascript like: 我想使用以下标准JavaScript解析可验证为布尔值的用户表达式:

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

Since this expressions are written by the user, I want to be sure they are clean becase they are going to be evaluated server side with NodeJS. 由于此表达式是由用户编写的,因此我想确保它们是干净的,因为它们将通过NodeJS在服务器端进行评估。

Instead of having to parse the expression as text looking for patterns and reinvent the wheel, is there a way I can use the power of Node to directly evaluate the expression without the risk of code injection? 不必将表达式解析为文本以寻找模式并重新设计轮子,有没有一种方法可以利用Node的功能直接评估表达式而没有代码注入的风险?

You might not like this answer. 您可能不喜欢这个答案。 But you have to do work. 但是你必须要做。 There is no magic bullet. 没有魔术子弹。

Your question contradicts itself by requiring "standard javascript" and "without the risk of code injection". 您的问题与要求“标准javascript”和“没有代码注入的风险”相矛盾。 You cannot have both. 不能同时拥有。 Standard JavaScript allows expressions like 'require("fs").rmdirSync("/")' 标准JavaScript允许类似'require("fs").rmdirSync("/")'表达式

The expression entered by the user has to be constrained to a seriously limited subset of JavaScript. 用户输入的表达式必须限制在JavaScript的严格限制子集内。 The server must validate that the input is limited to this subset before attempting to evaluate it. 在尝试评估输入之前,服务器必须验证输入是否限于该子集。

So first you need to think carefully about what limited subset is allowed. 因此,首先您需要仔细考虑允许使用的有限子集。 It looks like you want to allow constants integers like '5', operators like '>', '&&' and '<='. 看起来您想允许使用常量整数,如“ 5”,运算符如“>”,“ &&”和“ <=”。 You also allow access to variables like 'var1' 'obj1.prop1' 'var2'. 您还允许访问变量,例如'var1''obj1.prop1''var2'。 I'd imagine you need to be very specific about the list of allowed variables. 我想您需要对允许的变量列表非常具体。

The key to preventing script injection is to define a subset that includes only things you know are safe. 防止脚本注入的关键是定义一个子集,该子集仅包含您知道安全的内容。 You should not try to start with the whole of JavaScript and exclude things you think are dangerous - because you will miss some. 您不应该尝试从整个JavaScript入手,也不应该排除您认为危险的内容-因为您会错过其中的一些内容。

Once you have carefully defined what the expressions may contain, you need to implement code to parse and validate expressions. 仔细定义表达式可能包含的内容后,您需要实现代码以解析和验证表达式。 You may find a library or standard code to do this, but you will have to modify or configure it to permit your specific requirements. 您可能会找到执行此操作的库或标准代码,但是必须修改或配置它以允许您的特定要求。

In generally no matter what you will finally use, I would launch an evaluation process where you drop all privilege and only communicated with it using unix domain socket. 通常,无论最终使用什么,我都会启动一个评估过程,在此过程中,您放弃所有特权,仅使用unix域套接字与之进行通信。 And send the code you want to evaluate to it. 并将您要评估的代码发送给它。

Launch it as root and open the unix domain socket and then drop the privilege to nobody . 以root身份启动它,并打开Unix域套接字,然后将特权授予任何人

process.setgid('nobody');
process.setuid('nobody');

One thing that you should avoid is to do something like this: 您应该避免的一件事是执行以下操作:

const root = global = {};
const require = function() {
  console.log('tryed to call require', arguments);
}

eval("require('fs')");

This might work on the first look, but eg with ES6 there was the import keyword introduces, so even if you overwrite require you could still use import to load module. 乍一看这可能会起作用,但是例如在ES6中引入了import关键字,因此即使您覆盖require ,仍然可以使用import加载模块。

Also the methods mentioned in Safely sandbox and execute user submitted JavaScript? 还是安全沙箱中提到的方法并执行用户提交的JavaScript? like vm.runInContext('globalVar *= 2;', sandbox); vm.runInContext('globalVar *= 2;', sandbox); would not help. 不会帮助。 But the referenced sandcastle , might be something you could look at, but even if you use a sandboxing library I would still suggest to run it in an isolated unprivileged process. 但是所引用的sandcastle可能是您可以查看的内容,但是即使您使用沙箱库,我仍然建议您在隔离的非特权进程中运行它。

Like James suggested in the answer you should go the way that whitelist certain features instead of backlisting harmful ones. 就像詹姆斯在答案中建议的那样,您应该采用将某些功能列入白名单的方式,而不是将有害功能列入白名单。

You can use the mathjs library which comes with it's own expression parser. 您可以使用它自己的表达式解析器附带的mathjs库。

Website: http://mathjs.org/ 网站: http//mathjs.org/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM