Java代码审计篇 | ofcms系统审计思路讲解 - 篇1 | 环境搭建、路由机制

文章目录

  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇1 | 环境搭建、路由机制
  • 1. 前言
  • 2. 项目环境搭建
  • 3. 项目路由机制
        • 3.1. 1)先搜索pom.xml文件,看看使用了什么框架
        • 3.2. 2)确定是否是spring的路由机制
        • 3.3. 3)确定自写路由机制的特点
        • 3.4. 4)从前端探索
        • 3.5. 5)断点调试
        • 3.6. 6)寻找路径后的`.json`
        • 3.7. 7)测试下结论

Java代码审计篇 | ofcms系统审计思路讲解 - 篇1 | 环境搭建、路由机制

1. 前言

我发现很多文章包括教程,大概套路是:只说有漏洞的点,将有漏洞的点指出,然后分析代码;或者黑盒测试出漏洞之后,然后分析代码。

我认为这是在分析漏洞代码,而非代码审计。代码审计文章或教程应该是从0开始找到漏洞所在,包括思路!

所以这里不管有没有漏洞,我都会把审计过程写出来,因此篇幅会很长,但我认为这样对你会很有帮助。

知其然亦知所以然。

由于篇幅较长,因此我会分几篇进行,本篇是整个系列的第1篇,讲解两个内容:

  • 项目环境搭建
  • 项目路由机制

本系列其他文章

  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇1 | 环境搭建、路由机制
  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇2 | SQL注入漏洞审计

文章中有错误点,或者思路上有什么问题的,欢迎师傅们留言指出~

2. 项目环境搭建

项目地址:https://gitee.com/oufu/ofcms

版本:v1.1.2

下载地址:https://gitee.com/oufu/ofcms/archive/refs/tags/V1.1.2.zip

1)下载项目源码,解压,使用idea打开;修改数据库连接信息。

  • 配置文件位置:ofcms-V1.1.2/ofcms-admin/src/main/resources/dev/conf/db.properties

2)新建数据库,默认数据库名ofcms,并导入sql文件

  • 项目sql文件位置:ofcms-V1.1.2/ofcms-admin/src/main/resources/conf/sql/install.sql
  • 打开install.sql文件,全选语句,点击左上角执行,完毕之后,查看数据库表是否完整

3)加载项目依赖后,配置tomcat:

注意项目名称,否则无法访问

4)启动tomcat项目,默认弹出首页,环境搭建成功。

3. 项目路由机制

在真正审计之前,最好是先确定下项目的路由机制,有了路由我们才能更好的了解前端功能是如何与后端功能函数搭配的,也是我们验证漏洞的必要条件。

如何项目使用了某些框架,那么项目路由机制和框架路由机制大概率是相同的;但是有些可能不同,比如本项目就是一个和使用框架不太相同的路由机制。(在这里费了好长时间~)

在这里,我们先分析下本项目的路由机制。

3.1. 1)先搜索pom.xml文件,看看使用了什么框架

我们可以看到,该项目使用了 springframework,那该项目大概率使用的就是spring的路由机制。

3.2. 2)确定是否是spring的路由机制

搜索@Mapping@Request等spring的路由机制的常用注解,发现没有!

那大概率,这里就是自己写的路由机制了。

3.3. 3)确定自写路由机制的特点

这里根据不同的项目会有不同的方式,而该项目在前面已经知道使用了springframework,那么应该会有Controller,寻找一下Controller,因为在springframework中一般路由映射是写在Controller上面的。

通过搜索几个Controller之后,发现:该项目的路由看似像通过@Action注解完成的,但是类中的功能函数并没有什么注解。这里会有一个疑问?通过注解中的路径可以定位到类,但怎么定位到功能函数呢?

这里卡了很久。不行就换个思路,从前端尝试探索。

  • 这里多说一下:@Action一般是Struts2中的路由注解,所以这里我还怀疑了该项目使用了Struts2框架,但是搜索struts2.xml没有搜到!
3.4. 4)从前端探索

登录后台,之后随便找个功能,点击一下,并抓包

路径是这样的~

接下来怎么办?我的方法是在后端搜索该路径,当然不要搜全路径(搜索的时候可以不断的缩小路径)

一路搜索下来之后,到达了@Action注解,点进去看一下。

刚才请求的路径是这样的:/ofcms_admin_war/admin/comn/service/del.json?sqlid=system.log.delete,当前定位的类在admin目录下,所以前面这段admin/comn/service路径对上了,但是后面的del.json是什么?

我们可以发现,该ComnController类中存在del()方法,难到del.json对应就是这个方法吗?

我们可以打断点调试看一下:

3.5. 5)断点调试

在del()方法处打个断点,然后启动调试,重新点击该功能。

发现,确实停留到此处。

也就是说/ofcms_admin_war/admin/comn/service/del.json对应的就是admin目录下的存在@Action(path="/comn/service")注解的类中的del()方法。其实到这里已经够用了。

但是这里稍微深入一下,为什么路径是del.json

3.6. 6)寻找路径后的.json

这里该如何找呢?我们可以在项目源码中搜索.json,而且找的应该是字符串~因为这里只是路径中的字符串,不是方法什么的…

大概看一下,发现存在一个这样的语句,看红框位置,点进去看一下

这个类名字叫ActionHandler,名字看起来就和@Action注解有关。

再看下注释:“请求后缀名处理”。看来我们寻找的没错了。

大概分析下代码:

public class ActionHandler extends Handler {private String[] suffix = { ".html", ".jsp", ".json" };public static final String exclusions = "static/";public ActionHandler(String[] suffix) {super();this.suffix = suffix;}public ActionHandler() {super();}@Overridepublic void handle(String target, HttpServletRequest request,HttpServletResponse response, boolean[] isHandled) {/*** 不包括 suffix 、以及api 地址的直接返回*///过虑静态文件if(target.contains(exclusions)){return;}target = isDisableAccess(target);BaseController.setRequestParams();next.handle(target, request, response, isHandled);}private String isDisableAccess(String target) {for (int i = 0; i < suffix.length; i++) {String suffi =  getSuffix(target);if (suffi.contains(suffix[i])) {return target.replace(suffi, "");}}return target;}public static String getSuffix(String fileName) {if (fileName != null && fileName.contains(".")) {return fileName.substring(fileName.lastIndexOf("."));}return "";}
}

可以看到,请求的地址中后缀内容需要包含".html", “.jsp”, “.json”。对,是包含,不是等于。

也就是说我们请求的地址可以是以上三种,也可以是".jsonaaa",当然这里也没什么意义,只是分析下~

3.7. 7)测试下结论

将路径修改为del.jsonaaa,发现可以正常进入del()方法,即我们的结论是正确的。

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

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

相关文章

golang学习笔记05——golang协程池,怎么实现协程池?

推荐学习文档 golang实战大纲golang优秀开发常用开源库汇总golang学习笔记01——基本数据类型golang学习笔记02——gin框架及基本原理golang学习笔记03——gin框架的核心数据结构golang学习笔记04——如何真正写好Golang代码&#xff1f; 协程池是一种用于高效处理任务的机制&…

面试—JavaSE

目录 面向对象三大特征 重载和重写的区别 final和static修饰符 接口和抽象类的区别 String、StringBuilder、StringBuffer的区别 面向对象三大特征 封装、继承、多态 封装 将对象的属性和方法放入到一个类中&#xff0c;通过访问修饰符来控制对类的访问权限 继承 继承是…

【ruby java】登陆功能/邮件发送模版240903

Rails 风格登录系统添加全面而详细的注释&#xff0c;解释每个部分的功能和用途。​​​​​​​​​ 详细注释&#xff0c;解释了每个文件和代码块的功能。以下是一些关键点的总结&#xff1a; 1. 控制器&#xff08;Controllers&#xff09;: - ApplicationController: …

苏茵茵:以时尚之名,诠释品质生活

在女性追求个性化与自我表达的今天&#xff0c;时尚早已超越了简单的穿着打扮&#xff0c;它成为女性展现自我风格、彰显独特魅力的重要方式。从广泛的兴趣爱好到精心雕琢的个人风格&#xff0c;每一处细节都闪耀着女性对个性独特与自我表达的深切渴望。正是这股不可阻挡的潮流…

强化学习指南:训练过程与评估过程的区别

强化学习指南&#xff1a;训练过程与评估过程的区别 在强化学习&#xff08;RL&#xff09;中&#xff0c;训练和评估是两个截然不同但密切相关的过程。本指南将详细解释这两个过程的区别&#xff0c;以及如何正确实施它们。 1. 训练过程 训练是RL中最核心的部分&#xff0c…

Java 中常用内置接口函数

在 Java 8 及以后的版本中&#xff0c;引入了许多函数式编程的特性&#xff0c;其中最重要的就是内置的函数式接口。这些接口使得编写更简洁、可读性更强的代码成为可能。今天我将介绍四个常用的内置接口&#xff1a;Predicate、Function、Consumer 和 Supplier&#xff0c;并提…

static 变量和 static 函数各有什么特点?

static 关键字在 C、C 等编程语言中用于指定变量和函数的存储类型和可见性&#xff0c;其特点如下&#xff1a; static 变量 作用域&#xff1a; 局部静态变量&#xff1a;在函数内部声明&#xff0c;作用域限制在该函数内&#xff0c;但其生命周期贯穿程序整个运行过程。它只…

关于schneider施耐德140模块

SCHNEIDER 140模块是施耐德电气&#xff08;Schneider Electric&#xff09;公司生产的一系列工业自动化和控制产品&#xff0c;这些模块通常用于Quantum系列PLC&#xff08;可编程逻辑控制器&#xff09;系统中&#xff0c;以实现各种自动化和控制任务。以下是对SCHNEIDER 140…

2024.9.9 Python,有效的括号,三数之和,回溯算法解决括号生成

1.有效的括号 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。…

使用Protocol Buffers传输数据

使用 Google Protocol Buffers&#xff08;ProtoBuf&#xff09;与 Kafka 结合来定义和传输数据&#xff0c;可以确保传输数据的结构性、可扩展性和高效性。以下是一个简单的步骤指南&#xff0c;帮助你实现生产者和消费者。 1. 定义 ProtoBuf 消息格式 首先&#xff0c;你需…

笔记整理—内核!启动!—kernel部分(3)init进程—进程1

内核态下干了什么——构建内核。 在init进程中&#xff0c;一个进程有两种状态。1为内核态&#xff0c;init属于内核进程。2.用户态&#xff0c;自己将init转为用户态。从进程1之后的进程就都可以工作在用户态。 内核态中重点干了一件事情&#xff0c;挂载rootfs&#xff0c;找…

ffmpeg 视频编码及基本知识

理论 H264编码原理&#xff08;简略&#xff09; 1. 视频为什么需要进行编码压缩 降低视频数据大小&#xff0c;方便存储和传输 2. 为什么压缩的原始数据采用YUV格式 彩色图像的格式是 RGB 的&#xff0c;但RGB 三个颜色是有相关性的。 采用YUV格式&#xff0c;利用人对图像的…

【C语言必学知识点七】什么?还有人不知道什么是柔性数组?还不速来!!!

动态内存管理——详细解读柔性数组 导读一、什么是柔性数组二、柔性数组的特点三、柔性数组的使用四、柔性数组的优势结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;&#xff01; 在上一篇内容中我们介绍了C/C程序中的内存分区&#xff0c;在C/C…

C++11 --- 可变参数模板

序言 不知道大家有没有细细研究过在 C 语言 中的 printf 函数&#xff0c;也许我们经常使用他&#xff0c;但是我们可能并不是那么了解他。先看一下调用格式&#xff1a;int printf ( const char * format, ... );&#xff0c;在这里的 format 代表我们的输出格式&#xff0c;后…

欧拉下搭建第三方软件仓库—docker

1.创建新的文件内容 切换目录到etc底下的yum.repos.d目录&#xff0c;创建docker-ce.repo文件 [rootlocalhost yum.repos.d]# cd /etc/yum.repos.d/ [rootlocalhost yum.repos.d]# vim docker-ce.repo 编辑文件,使用阿里源镜像源&#xff0c;镜像源在编辑中需要单独复制 h…

华为防火墙 nat64

如果设备接收到的IPv6报文的前缀是设备为NAT64定义的前缀&#xff0c;说明报文的目的地址是IPv4网络&#xff0c;报文将经过NAT64处理后被转发至IPv4网络。 如果设备接收到的IPv6报文的前缀不是设备为NAT64定义的前缀&#xff0c;说明报文的目的地址是IPv6网络&#xff0c;报文…

java直接实例化对象和使用接口实例化对象之间的区别(java小知识点)

文章目录 1.定义一个MyClass类和一个 MyInterface接口2.具体使用场景3.如何调用 MyClass 自己的特有方法&#xff1f;4.总结 1.定义一个MyClass类和一个 MyInterface接口 public interface MyInterface {void doSomething(); // 权限修饰符默认是public }public class MyClass…

设计模式 | 单例模式

定义 单例设计模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。这种模式常用于需要控制对某些资源的访问的场景&#xff0c;例如数据库连接、日志记录等。 单例模式涉…

网站钓鱼——挂马技术手段介绍

更多网安实战内容&#xff0c;可前往无问社区查看http://wwlib.cn/index.php/artread/artid/10194.html 网站挂马目前已经成为流氓软件以及红队人员快速获取目标主机权限的常用手段之一&#xff0c;在长时间的实战中也是出现了层出不穷的钓鱼方法&#xff0c;这次分享一下实际…

【北京迅为】《STM32MP157开发板使用手册》-第十三章 编译QtE5.12文件系统

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…