在AWS-LAMBDA中使用Exec或Eval运行不受信任的Python代码

6

最近进行了大量研究。虽然我只是一个学徒,但我有一个项目,必须从网站上运行用户不可信的Python3代码。

如果这个问题存在一些变动的部分,我也提前道歉。

  • 我正在寻找尽可能安全的方法。这不需要100%完美,除非存在泄漏极度敏感数据的风险。

主要问题

  • 我的AWS-lambda计划是否存在极高泄漏敏感数据的风险?
  • 是否有其他简单的预防措施可以使这项工作在AWS-lambda中更加安全?
  • 如果我仅连接了单个AWS-api-gateway以进行REST调用,exec()是否有办法突破AWS-lambda容器并进行其他网络连接?
  • 我是否需要限制__builtins__和本地变量,或者AWS-lambda容器已足够安全?

背景

似乎大多数公司使用KubernetesDocker容器来执行不受信任的Python代码(例如LeetcodeProgramizhackerRank)。

请参见以下有用的链接:

我的计划

我考虑可以将任意的Python代码作为微服务POST到AWS Lambda函数中,使用他们容器化/扩展性而不是构建自己的。在Lambda容器中,我只需通过简单的execeval函数运行代码,或许可以进行如下的一些限制:

"

safe_list = ['math','acos', 'asin', 'atan', 'print','atan2', 'ceil', 'cos', 'cosh', 'de grees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'] 
    safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ]) 
    safe_dict['abs'] = abs
    exec(userCode,{"**__builtins__"**:None},safe_dict )

特别注意:

  • 我不太担心出现无限循环或崩溃的情况,因为我会超时并告诉用户重新尝试。
  • 我只需要运行相当简单的Python代码(通常少于几行),并返回异常、标准输出、打印结果,并对结果运行检查。需要运行以下内容:
    • 数学运算符、列表、循环、lambda函数、maps、filters、声明方法、声明具有属性的类、打印。
  • 这不需要成为数十万用户的完美项目。我只想要一个在线网站,用作简历加分项,也许能通过广告赚点钱来帮助支付成本。
  • 如果有严重的限制,我最终可以在Kubernetes中实现它(如上链接所述),但希望此解决方案足够好用。
  • 我只想让这个东西相对良好地运行,并且不要花费太长时间建造或太多金钱成本。
  • 我不想泄露任何敏感信息。

我已经计划采取的安全措施:

  • AWS Lambda:将超时限制在1-2秒左右
  • AWS Lambda:将内存使用情况限制为128mb
  • 我的代码:使用正则表达式确保没有人传递双下划线坏东西
  • 尽可能使这个微服务尽可能简化(仅连接单个AWS-API-Gateway)。

其他注意事项:

  • 我认为我无法在AWS Lambda中使用restrictedPythonPyPy的沙箱功能,因为我没有直接使用这些依赖关系的权限。我希望在此用例中它们不是必需的。
  • 如果使用 exec() 不可能实现此目标,是否有可以从GitHub或其他地方复制粘贴到AWS-lambda文件中并调用的安全Python解释器
  • 我计划允许用户通过类似以下方式从exec中打印:

"

@contextlib.contextmanager
def stdoutIO(stdout=None):
    old = sys.stdout
    if stdout is None:
        stdout = StringIO()
    sys.stdout = stdout
    yield stdout
    sys.stdout = old

    
with stdoutIO() as s:
    try:
        exec(userCode)
    except:
        print("Something wrong with the code")
print( s.getvalue())
print(i)

如果您有任何问题或建议,请告诉我。

___ 编辑 ** 添加架构图 ___

目前为止,这就是架构的大致情况


你最终选择了那条路线,@hippomano 吗? - Joachim Breitner
1
暂时不行。由于我找到了新工作,所以这个项目被搁置了,但是我认为LAMBDA函数的容器化现在相当不错。需要进行大量实验。 - hippomano
2个回答

2

我也在研究这个问题,并且对于AWS Lambda是否可以用于运行不受信任的代码很感兴趣。大多数逻辑看起来合理,但有几个问题需要解决。

使用正则表达式确保没有人传入双下划线badstuff

不要这样做! 这是不可能(或者几乎不可能)检查包含Python代码的字符串是否恶意的。想象一下有人要求您调用以下内容:

eval(base64.b64decode(b'cHJpbnQoInRoaXMgaXNuJ3QgYmFkLCBidXQgeW91IGRvbid0IGtub3cgdGhhdCEiKQ=='))

这安全吗?它会被正则表达式捕获吗?好吧,你可以模拟 eval(),但接下来呢?我绝对没有怀疑过半个能干的 Python 开发人员能够找到一条路线绕过它。
半安全比完全不安全更糟糕
你会开始信任它,构建另一个依赖于半安全层的功能,并最终被黑客攻击。
解决方案
1. 使用许多人和大公司都依赖的语言或特性,这样违规风险就很小(如果有人发现了零日漏洞,那么有更赚钱的人可供黑客攻击)。如果可以使用 JavaScript,则此处可能是一个不错的选择,您还可以尝试编译为 WebAssembly 的 pypy 或 RustPython。
2. 接受您的代码根本不安全,并依靠操作系统/PAAS来保护您。换句话说,让用户在 AWS Lambda 中运行他们喜欢的任何内容,并让 Amazon 进行隔离。
我的问题
我想使用第二个选项,但我担心敌对开发人员会污染 lambda 容器,然后由另一个无辜的开发人员成为受害者。
假设我们有一个 AWS Lambda,它有效地调用 eval(user_written_code) 并返回结果,它还可以设置一堆环境变量,这些变量可以在 user_written_code 中引用。
当调用代码时,lambda 防止它们执行任何恶意操作 - 例如,lambda 用户凭据没有访问任何可怕的内容。他们可以发出请求、使用内存、使用 CPU、挂起 - 所有这些都由 AWS 处理。
但我如何阻止以下向量:
1. 恶意用户执行模拟内置方法的代码,当调用该方法时,当前代码上下文和环境变量被发送到某个服务器。 2. 无辜用户在同一个 lambda 容器上执行其代码,AWS Lambda 聪明地重用进程以提高性能。 3. 无辜用户的代码和凭据(环境变量)被发送到恶意用户的服务器。
我很想知道是否有其他人已经确认了是否有一种有效的方法来防止 lambda 容器像这样被污染?

我一直在遵循类似的逻辑链,并遇到了同样的担忧。我不确定你是否已经排除了这个问题,或者找到了缓解这个担忧的方法? - undefined
如果我现在要做这个的话,我会使用Node和Pyodide,或者使用K8s并在使用完后丢弃容器。 - undefined

0
有趣的帖子,我也在考虑使用现有的AWS基础设施来运行不受信任的Python代码,而不是使用可能会很快变得昂贵的Docker容器。我刚开始研究这个问题,但我的首选是使用restrictedPython添加一些安全保障。
我对Python开发和Lambda都很新,但你提到restrictedPython不是开箱即用的,难道你只需要将其作为依赖项包含在zip文件中并上传到Lambda中就可以了吗?除非我漏掉了什么?
此外,我不确定你是否看过这个视频,我觉得它非常有帮助:https://www.youtube.com/watch?v=sL_syMmRkoU

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接