文章目录
Java代码审计篇 | ofcms系统审计思路讲解 - 篇1 | 环境搭建、路由机制
1. 前言
我发现很多文章包括教程,大概套路是:只说有漏洞的点,将有漏洞的点指出,然后分析代码;或者黑盒测试出漏洞之后,然后分析代码。
我认为这是在分析漏洞代码,而非代码审计。代码审计文章或教程应该是从0开始找到漏洞所在,包括思路!
所以这里不管有没有漏洞,我都会把审计过程写出来,因此篇幅会很长,但我认为这样对你会很有帮助。
知其然亦知所以然。
由于篇幅较长,因此我会分几篇进行,本篇是整个系列的第1篇,讲解两个内容:
- 项目环境搭建
- 项目路由机制
本系列其他文章
文章中有错误点,或者思路上有什么问题的,欢迎师傅们留言指出~
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();
}
@Override
public 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()
方法,即我们的结论是正确的。