泛微云桥e-Bridge任意文件上传漏洞分析
作者:Harder@微步漏洞团队
漏洞详情:
关于最近爆的泛微云桥e-Bridge文件上传感觉很有意思,这个文件上传是绕过了安全函数对.jsp后缀检测,一个多请求文件上传,通过后一个正常图片的请求覆盖Hash表,回传uploadFile对象实现回传而绕过isSafeFile方法对后缀的检测
入口点在weaver.weixin.app.recruit.controller.ResumeController
@ActionKey("/wxclient/app/recruit/resume/addResume")
@Before({Tx.class})
public void addResume() throws Exception {
try {
WxBaseFile wbFile = null;
if (this.getContentType().toLowerCase().startsWith("multipart/form-data")) {
wbFile = this.getWxBaseFile(this.wxBaseFileService, this.getPara("fileElementId"), (String)null, 2097152, (String)null);
}
ResumeModel model = (ResumeModel)this.getModel(ResumeModel.class, "resume");
if (wbFile != null) {
model.set("accessory", wbFile.getId());
}
if (this.resumeService.addResume(model, this.getPara("sysagentid"))) {
this.renderJsonMsgForIE("提交成功", true);
} else {
this.renderJsonMsgForIE("提交失败", false);
}
} catch (Exception var3) {
Exception e = var3;
if (e.getMessage().indexOf("2097152") != -1) {
this.renderJsonMsgForIE("上传文件大小不能超过2M", false);
} else {
this.log.error(e.getMessage(), e);
this.renderJsonMsgForIE("程序异常,请联系管理员!", false);
}
throw e;
}
}
跟着调用看看
public UploadFile getFile(String parameterName, String saveDirectory, Integer maxPostSize, String encoding) {
getFiles(saveDirectory, maxPostSize, encoding);
return getFile(parameterName);
}
大概调用栈就是这样,跟着下面关键代码走就行
weaver.weixin.app.recruit.controller.ResumeController#addResume=>weaver.weixin.core.controller.BaseController#getWxBaseFile=>com.jfinal.core.Controller#getFile=>com.jfinal.core.Controller#getFiles=>com.jfinal.upload.MultipartRequest#MultipartRequest=>com.jfinal.upload.MultipartRequest#wrapMultipartRequest=>javax.servlet.http.HttpServletRequest#MultipartRequest
在这其实已经完成了第一个uploadFile对象的请求上传。然后进行了第二次请求,把第二个uploadFile对象也上传了。然后我们继续往下走
这里的函数multipartRequest.getFilesystemName跟踪进去可以看到,是非常有说法的,它返回的是files的name值的然后转换的UploadedFile对象,然后在根据这个UploadedFile对象的getFilesystemName()的方法获取filesystemName的名字。然后我们可以看看这个files是什么东西
files是类com.oreilly.servlet.MultipartRequest类中的Hash表,是用来存储文件上传的键值对的
其实回头看,我们可以发现我们请求一被覆盖掉了,因为在这个请求里面file是key,两个文件上传的name都是file,键值是一样的。然后就会导致我们第二个请求harder.png会覆盖掉之前的key,然后键值对就会变成png的键值对,后续的请求都是.png的UploadFile对象
这下面就利用这个.png的uploadFile对象绕过了isSafeFile方法的检测
然后就上传成功了。这个洞其实上传的jsp恶意文件是落地到文件夹里面的,所以我们可以用条件竞争的方法来Bypass。但是这个框架的路径是随机1-2位大写字母的,所以这个条件竞争难度较大。
对于JFinal的jsp文件解析绕过,这篇文章讲的很清楚了
我大概总结一下,产生的原因是因为tomcat和JFinal获取和处理路径的方式不同,所以进行了bypass。
绕过方法呢大概就是:
1.对后缀的jsp进行urlencode编码
2.对jsp后面加一个; 比如harder.jsp;就可以实现绕过了
最后十分感谢Le1a师傅的帮助