如何避免在用户定义的函数中使用JavaScript eval()

时间:2021-12-31 13:00:08

I'm trying to make a generic table-top RPG helper web app. It has to be generic because Wizards of the Coast is very protective of their copyrights. So, in order to avoid cease-and-desists, the system has to be capable of loading arbitrary rules. That said, my buddies and I (along with most any other user) will be using it for D&D.

我正在尝试制作一个通用的桌面RPG帮助Web应用程序。它必须是通用的,因为Wizards of the Coast非常保护他们的版权。因此,为了避免停止和停止,系统必须能够加载任意规则。也就是说,我和我的朋友(以及大多数其他用户)将使用它进行D&D。

In D&D, modifiers are based on a character's stats. To get a modifier, you take the stat, subtract 10, divide by 2, and round down.

在D&D中,修饰符基于角色的统计数据。要获得一个修饰符,你可以取stat,减去10,除以2,然后向下舍入。

function getModifier(statValue) {
    return Math.floor((statValue - 10) / 2);
}

My app will be capable to loading a game's rules from a .json file. I want to be able to make this modifier function user-definable. The easiest way would be to just eval() whatever they provide in the .json file, but obviously that's a terrible idea due to security issues.

我的应用程序将能够从.json文件加载游戏规则。我希望能够使这个修饰符功能用户可定义。最简单的方法是只在eval()中提供它们在.json文件中提供的任何内容,但很明显,由于安全问题,这是一个糟糕的主意。

Unfortunately, I can't think of a simple way to get around this in a secure manner. Obviously I could write my own parser, but that's more complicated than I'd like/am currently capable of.

不幸的是,我想不出以一种安全的方式解决这个问题的简单方法。显然我可以编写自己的解析器,但这比我目前能够使用的更复杂。

Ideas?

4 个解决方案

#1


I did a quick google search and found two options - http://mathjs.org and http://jsep.from.so

我做了一个快速的谷歌搜索,发现了两个选项 - http://mathjs.org和http://jsep.from.so

btw. writing your own parser is not that difficult. You may be able to write one that's sufficient for your purpose in less than 100 lines of code

顺便说一句。编写自己的解析器并不困难。您可以在少于100行代码中编写一个足以满足您目的的编程

#2


First, bear in mind that this is all on the client-side. So long as you trust the JSON (it came from your server or it is controlled alongside the application itself), then you can use it. That doesn't completely rule out some * inserting malicious rules, but I don't think botnets have learned to play D&D yet.

首先,请记住这一切都在客户端。只要您信任JSON(它来自您的服务器或它与应用程序本身一起控制),那么您就可以使用它。这并没有完全排除某些木马插入恶意规则,但我认为僵尸网络还没有学会玩D&D。

To literally avoid eval and provide some modicum of security, you can use new Function. It takes a list of argument names followed by the function body, allowing you a large amount of control over how the function is defined and where it can be referenced from. You only need to store the body in the JSON file, allowing you to largely control the parameters and make it difficult to assign to the global scope, minimizing your attack surface (such as it is) quite a lot.

要从字面上避免eval并提供一些安全性,您可以使用新的Function。它采用参数名称列表,后跟函数体,允许您对函数的定义方式以及函数的引用进行大量控制。您只需要将主体存储在JSON文件中,从而允许您在很大程度上控制参数并使其难以分配到全局范围,从而最大限度地减少攻击面(例如它)。

If you want to have fun with this and now your rules will largely be mathematical, you may consider using a tool like pegjs to generate a parser for your rules. Calculators are one of the classic introductions to parsers and compilers, so this could be an opportunity to play with some fun tech. The rules and parsers built by pegjs are very easy to use in a JS project (I have an example using PegJS and ES6 via Babel).

如果你想玩得开心,现在你的规则很大程度上是数学的,你可以考虑使用像pegjs这样的工具为你的规则生成一个解析器。计算器是解析器和编译器的经典介绍之一,因此这可能是一个玩一些有趣技术的机会。由pegjs构建的规则和解析器在JS项目中非常容易使用(我有一个使用PegJS和ES6通过Babel的示例)。

#3


There are two options as I see it. One, if you 100% want to define the function in .json, you will need to parse. JSON does not allow functions, so you need to store the function as a string and eval it.

我看到它有两个选项。一,如果你100%想要在.json中定义函数,你需要解析。 JSON不允许函数,因此您需要将函数存储为字符串并对其进行评估。

The better way would be to also provide a config.js ability. Perhaps the .json would have a "configUrl": property, and then expose well known apis, eg RPGHelper.setModifer(someFunction) that you can call from inside the config.js file. The user is then free to define whatever arbitrary logic there.

更好的方法是提供config.js能力。也许.json会有一个“configUrl”:属性,然后暴露众所周知的apis,例如RPGHelper.setModifer(someFunction),你可以从config.js文件中调用它。然后,用户可以*地定义那里的任意逻辑。

#4


One solution to your problem is to use sandboxed iframes (current supported by all major browsers

您的问题的一个解决方案是使用沙盒iframe(当前所有主流浏览器都支持

You run user code on a separate page, with limited priviliges, in such a way that the code does not interfere with the rest of the application. You can communicate with the sandboxed page using postMessage() and window.onmessage.

您在具有有限特权的单独页面上运行用户代码,使代码不会干扰应用程序的其余部分。您可以使用postMessage()和window.onmessage与沙盒页面进行通信。

#1


I did a quick google search and found two options - http://mathjs.org and http://jsep.from.so

我做了一个快速的谷歌搜索,发现了两个选项 - http://mathjs.org和http://jsep.from.so

btw. writing your own parser is not that difficult. You may be able to write one that's sufficient for your purpose in less than 100 lines of code

顺便说一句。编写自己的解析器并不困难。您可以在少于100行代码中编写一个足以满足您目的的编程

#2


First, bear in mind that this is all on the client-side. So long as you trust the JSON (it came from your server or it is controlled alongside the application itself), then you can use it. That doesn't completely rule out some * inserting malicious rules, but I don't think botnets have learned to play D&D yet.

首先,请记住这一切都在客户端。只要您信任JSON(它来自您的服务器或它与应用程序本身一起控制),那么您就可以使用它。这并没有完全排除某些木马插入恶意规则,但我认为僵尸网络还没有学会玩D&D。

To literally avoid eval and provide some modicum of security, you can use new Function. It takes a list of argument names followed by the function body, allowing you a large amount of control over how the function is defined and where it can be referenced from. You only need to store the body in the JSON file, allowing you to largely control the parameters and make it difficult to assign to the global scope, minimizing your attack surface (such as it is) quite a lot.

要从字面上避免eval并提供一些安全性,您可以使用新的Function。它采用参数名称列表,后跟函数体,允许您对函数的定义方式以及函数的引用进行大量控制。您只需要将主体存储在JSON文件中,从而允许您在很大程度上控制参数并使其难以分配到全局范围,从而最大限度地减少攻击面(例如它)。

If you want to have fun with this and now your rules will largely be mathematical, you may consider using a tool like pegjs to generate a parser for your rules. Calculators are one of the classic introductions to parsers and compilers, so this could be an opportunity to play with some fun tech. The rules and parsers built by pegjs are very easy to use in a JS project (I have an example using PegJS and ES6 via Babel).

如果你想玩得开心,现在你的规则很大程度上是数学的,你可以考虑使用像pegjs这样的工具为你的规则生成一个解析器。计算器是解析器和编译器的经典介绍之一,因此这可能是一个玩一些有趣技术的机会。由pegjs构建的规则和解析器在JS项目中非常容易使用(我有一个使用PegJS和ES6通过Babel的示例)。

#3


There are two options as I see it. One, if you 100% want to define the function in .json, you will need to parse. JSON does not allow functions, so you need to store the function as a string and eval it.

我看到它有两个选项。一,如果你100%想要在.json中定义函数,你需要解析。 JSON不允许函数,因此您需要将函数存储为字符串并对其进行评估。

The better way would be to also provide a config.js ability. Perhaps the .json would have a "configUrl": property, and then expose well known apis, eg RPGHelper.setModifer(someFunction) that you can call from inside the config.js file. The user is then free to define whatever arbitrary logic there.

更好的方法是提供config.js能力。也许.json会有一个“configUrl”:属性,然后暴露众所周知的apis,例如RPGHelper.setModifer(someFunction),你可以从config.js文件中调用它。然后,用户可以*地定义那里的任意逻辑。

#4


One solution to your problem is to use sandboxed iframes (current supported by all major browsers

您的问题的一个解决方案是使用沙盒iframe(当前所有主流浏览器都支持

You run user code on a separate page, with limited priviliges, in such a way that the code does not interfere with the rest of the application. You can communicate with the sandboxed page using postMessage() and window.onmessage.

您在具有有限特权的单独页面上运行用户代码,使代码不会干扰应用程序的其余部分。您可以使用postMessage()和window.onmessage与沙盒页面进行通信。