保护用户定义的 javascript 函数以保护 node.js 服务器

Securing user defined javascript function to protect node.js server

我正在制作一个数学教学网页(NodeJS 后端和 Angular 前端)。我想要一种特殊的用户(创建者)来创建数学练习。这些练习之一可能如下所示:

Marie has ${nums[0]} oranges and ${nums[1]} apples. How many fruits does she have?

现在我想让创作者写一个这样的数字生成函数:

const generate = () => {
  const nums = new Array(2).fill(0).map(e => Math.floor(Math.random() * 10)
  return { nums: nums, answer: nums.reduce((p, c) => p + c, 0) }
}

这个函数应该发送到服务器并存储。当用户想试题时,题目应该在服务器上执行。 我应该怎么做才能保护服务器免受恶意代码的侵害,例如:

const generate = () => {
  process.exit()
}

很简短的回答,这对服务器来说从来都不是真正安全的。不可能证明一个程序是安全的。有一些缓解措施(例如沙盒)可以提供帮助,但它最终始终是一种风险。对于此应用程序,可能是一个不必要的应用程序。

考虑一些不需要 exec 来传达公式的方法。一种方法可能是发送某种抽象语法树,或者解析数学表达式。

这个 npm 包看起来很有前途。以与填写书面问题模板相同的方式填写数学表达式字符串模板。可能需要提供另一个对象来定义需要的随机数并将它们映射到模板中使用的名称。 math-expression-evaluator

这对 server/client 来说是不安全的。

不确定这是不是正确的方法。但您可以限制全局变量访问

const generate1 = () => {
    process.exit();
}

const generate2 = () => {
    const nums = new Array(2).fill(0).map(e => Math.floor(Math.random() * 10));
    return {
        nums: nums,
        answer: nums.reduce((p, c) => p + c, 0)
    }
}

const funcStr1 = generate1.toString();
const funcStr2 = generate2.toString();

//get all global variables key from 'global' and check it exist or not
// const globals = Object.keys(global); // will return same result as below remove keys which you want to allow
const globals = ['DTRACE_NET_SERVER_CONNECTION',
    'DTRACE_NET_STREAM_END',
    'DTRACE_HTTP_SERVER_REQUEST',
    'DTRACE_HTTP_SERVER_RESPONSE',
    'DTRACE_HTTP_CLIENT_REQUEST',
    'DTRACE_HTTP_CLIENT_RESPONSE',
    'COUNTER_NET_SERVER_CONNECTION',
    'COUNTER_NET_SERVER_CONNECTION_CLOSE',
    'COUNTER_HTTP_SERVER_REQUEST',
    'COUNTER_HTTP_SERVER_RESPONSE',
    'COUNTER_HTTP_CLIENT_REQUEST',
    'COUNTER_HTTP_CLIENT_RESPONSE',
    'global',
    'process',
    'Buffer',
    'clearImmediate',
    'setImmediate',
    // 'clearInterval',
    // 'clearTimeout',
    // 'setInterval',
    // 'setTimeout'
];

const hasGlobal1 = globals.some((g) => funcStr1.includes(`${g}.`));
const hasGlobal2 = globals.some((g) => funcStr2.includes(`${g}.`));

console.log('generate1 has global', hasGlobal1);
console.log('generate2 has global', hasGlobal2);