在 AWS Lambda 中使用 JavaScript eval()

at.*_*at. 2 child-process amazon-web-services node.js aws-sdk aws-lambda

我想使用 AWS Lambda 运行用户通过 Web 提交的 JavaScript 代码。我的 Lambda 函数将返回返回值 、stderrstdout。这样做我可能会遇到什么问题?

恶意用户是否能够提交导致 Lambda 函数出现问题的代码?用户所做的更改(例如对节点环境或文件系统的更改)是否在调用中持续存在?有什么办法可以防止这种情况发生吗?

eval()可以将文件写入 Lambda 文件系统并调用:

const userCodeProcess = require('child_process').fork('user_code.js')
userCodeProcess.on('message', response.send)
Run Code Online (Sandbox Code Playgroud)

for*_*mid 6

用户将能够向您的 Lambda 函数提交代码,这在某些情况下可能会导致问题:

  • 文件系统- 您的用户可以提交可以对文件系统进行更改的代码,并且这些更改将在重用容器上调用的函数中持续存在。并非所有用户代码请求都将在同一个容器上运行,但如果两个请求靠近,则将可以访问同一个容器和相同的“临时”磁盘空间。潜在防止这种情况的一种方法是,如果您可以将包含的函数(例如 )限制fs到您在函数调用时定义的特定目录,以便您可以为目录中的每个请求创建一个随机目录/tmp。我不确定这是否可能。您必须确保用户不能fs再次自行请求。更好的建议是使用类似的东西safe-eval,我稍后将详细讨论。
  • 环境变量- 在 eval 中运行的代码可以访问 Node 环境变量。如果您需要向数据库、其他 AWS 产品等发出任何请求,那么您需要向 Lambda 函数提供策略,除非您对凭证进行硬编码,并且该信息可以通过用户代码访问。您必须确保您向系统提供的任何凭据都不在环境变量中,如果在环境变量中,那么您可以接受用户访问它们。
  • 限制- 您可能会遇到限制问题。默认情况下,AWS 仅允许 100 个并发调用。如果您不限制用户提交自己的 JS 的请求,那么您可能会遇到由于达到限制而导致请求被拒绝的问题。我最近请求增加限制,我能够将我的并发请求增加到 3000 个并发请求,而他们不必评估他们当前的基础设施是否可以处理它,所以他们也可能会给你这个没有问题的。
  • 费用- 我确信您已经考虑过函数超时,但您希望确保限制函数运行时间,以便您的用户不会增加您的 AWS 账单。此外,它可能看起来很小,但在大规模上,一堆 6MB 请求响应加起来,因此数据传入和传出可能是一件大事,并且您可能希望在代码中进行限制。
  • 限制您的用户自己可能会遇到容器/tmp目录的限制。他们可能会遇到最大有效负载返回大小的问题。其他极限问题可以在这里研究。

据我了解,您无法使用代码破坏 Lambda 函数容器,从而导致未来的请求无法运行。我相信,如果现有容器不存在,或者现有容器遇到一些问题,将会启动一个新容器。

推荐

根据我刚刚所做的一些额外研究,您可能希望在某种类型的上下文中运行 javascript 代码,以便您的用户只能访问您希望他们访问的 Node API 端点,以及您自己的系统定义的变量。使用类似的工具safe-eval可能会起作用。其他人提出了在上下文中执行的问题eval,例如这里,或者您可以use strict;在每次调用时预先考虑并定义函数变量eval,例如这里描述的。

此外,在关闭函数并返回之前stderrstdout您可以清除/tmp目录。我对此的担忧是,AWS 在同时执行两个请求时是否使用同一个容器,并且您删除了同时执行的两个函数的“临时”空间。我在研究中未能找到这个问题的决定性答案。

此时我仍然想说,您的/tmp目录是您最有可能遇到问题的地方。如果您能找到一种方法来限制对单个目录的使用,而无法导航到父目录,或者AWS是否会在另一个函数中使用容器的同时重用容器,那么我认为您可能可以使用Lambda 无需过多关注即可执行用户提供的代码。或者,您可以通过将文件系统从您使用的任何上下文方法中排除来阻止用户访问您的文件系统。

AWS 关于容器重用的其他阅读内容请参见此处