代码审计可以说是安全从业者必备的基本能力了,代码审计在各种场景都需要用到,比如渗透测试、漏洞研究、企业安全运营等。比如说总所周知的SDL开发流程,代码审计在其中也发挥了重要的作用。
简单的代码审计流程可以是这样的:
1、熟悉业务流程。
2、分析程序架构,根据不同的架构有不同的审计流程。
3、人工审计。
4、工具审计。
下面来介绍本次要审计的SSM框架
SSM框架,即SpringMVC+Spring+Mybatis三个开源框架整合在一起的缩写。
1.1 SpringMVC
是一种基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架,使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发。
1.2 Spring
是分层的 Java SE/EE full-stack 轻量级开源框架,以 IOC(Inverse of Control,控制反转)和 AOP(Aspect Oriented Programming,面向切面编程)为内核,使用基本的 JavaBean 完成以前只可能由 EJB 完成的工作,取代了 EJB 臃肿和低效的开发模式,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
1.3 Mybatis
是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
1.4 Servlet
还有一项技术虽然名称没有出现在这三个开源框架中但是SpringMVC的底层就是以此技术进行构建的,这项技术就是Servlet。
Servlet是基于Java技术的Web组件,由容器管理并产生动态的内容。Servlet与客户端通过Servlet容器实现的请求/响应模型进行交互。
相对以SSM框架搭建的java web项目进行审计,上述这些都是要有一定程度的了解的。
上面说明过对于不同的架构会有不同的审计方式,所以说针对这次SSM框架,我们可以遵循下方的流程来审计。
1、熟悉业务流程。
2、阅读配置文件。
3、阅读可能存在漏洞的功能点。
4、通读Controller模块。
5、工具审计。
审计流程
搭建的流程以及系统的名字略过,审计的系统是在其他审计的文章中找到的,很容易搜到相关文章可以自行查找。
1.熟悉业务流程
这个系统是一个在线教育系统,简单来说就是卖网课的,学生可以在网站上看学习视频,发表评论,功能点不是很多,在个人中心可以修改资料,上传头像。
2.阅读配置文件
在熟悉完流程之后,开始看代码,首先是配置文件
在红框内的都是我们需要去查看的配置文件
这个文件相对比较重要,这里我们可以发现对于路由的鉴权是怎样的,此处是一个伏笔。
还可以看看pom.xml里面项目引入了什么依赖
好的,在阅读完配置文件之后我们开始对一些可疑的功能点进行审计。
3.阅读可能存在漏洞的功能点
3.1 任意文件上传
用户可以修改个人头像
相关请求
我们根据URL去寻找相关代码
在SSM框架中我们就只需要寻找@RequestMapping 注解中包含gok4
的文件就可以了
但是刚开始的时候发现并找不到相关的文件,说明这个功能可能并不是代码文件中提供的,我们可以在IDEA底下的Spring标签中找到所有的Controllers,可以看到这个功能是由导入的lib中实现的。
找到代码之后我们开始审计
public String gok4(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "uploadfile",required = true) MultipartFile uploadfile, @RequestParam(value = "param",required = false) String param, @RequestParam(value = "fileType",required = true) String fileType, @RequestParam(value = "pressText",required = false) String pressText) {
try {
long maxSize = 4096000L;
System.out.println(uploadfile.getSize());
if (uploadfile.getSize() > maxSize) {
return this.responseErrorData(response, 1, "上传的图片大小不能超过4M。");
} else {
String[] type = fileType.split(",");
this.setFileTypeList(type);
String ext = FileUploadUtils.getSuffix(uploadfile.getOriginalFilename());
if (fileType.contains(ext) && !"jsp".equals(ext)) {
String filePath = this.getPath(request, ext, param);
File file = new File(this.getProjectRootDirPath(request) + filePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
uploadfile.transferTo(file);
return this.responseData(filePath, 0, "上传成功", response);
} else {
return this.responseErrorData(response, 1, "文件格式错误,上传失败。");
}
}
} catch (Exception var13) {
logger.error("gok4()--error", var13);
return this.responseErrorData(response, 2, "系统繁忙,上传失败");
}
}
唯一的过滤是在if (fileType.contains(ext) && !"jsp".equals(ext))
fileType是我们可以控的,但是后缀不能够为jsp,这时就可以使用末尾添加::$DATA截断上传。
成功上传jsp文件
还存在另外一个任意文件上传点/video/uploadvideo
,而且没有后缀限制。
3.2 SQL注入
在mybatis中,如果Mapper中的语句传递参数使用的是${}
而不是#{}
的话就会发生sql注入问题,#{}在底层是使用了预编译来实现的(PrepareStatement)。
如果说项目使用了mybatis的话,有一种方法可以快速的找出可能存在的sql注入问题。
在IDEA界面 ctrl + shift + f
搜索 ${
就可以找出大部分的sql注入问题。
我们来看看这个deleteCourseFavoritesById
可以看到是根本没有任何过滤的,在配置文件中也没有看到关于的过滤。
于是可以直接注入
注入点也不止这一个,大多都是相似的就不多说。
4. Controller
可能存在问题的功能点看完了,可以依次看看Controller
4.1 反射型XSS
在IDEA下方的Spring窗口中依次查看Controller,首先先跳过需要鉴权的admin目录,看到DialogController.class
文件。
@RequestMapping({"/common/dialog"})
public String getDialog(HttpServletRequest request, Model model) {
try {
Map<String, Object> mapDialog = new HashMap();
mapDialog.put("title", request.getParameter("title"));
mapDialog.put("context", request.getParameter("context"));
mapDialog.put("height", request.getParameter("height") == null ? 157 : request.getParameter("height"));
model.addAttribute("dialog", mapDialog);
return "/common/dialog";
} catch (Exception var4) {
logger.error("getDialog", var4);
return this.setExceptionRequest(request, var4);
}
}
代码的意思就是从请求中获取参数,然后再返回到视图,中间好像没有任何过滤,试一试XSS payload。
成功弹窗
4.2 用户信息泄露
从配置文件我们可以知道 admin
和 uc
目录都有相关的鉴权操作,但是发现到一些可疑的路由
尝试不带Cookie访问
如果是国外的SRC这算是严重漏洞了。
当然其他的端点也有同样的问题,这里就不重复说了。
这一部分我并没践行好,没有将所有的Controller看完,毕竟通读所有代码还是比较耗时的。
5.工具审计
我这里使用的是fortify,扫描用了半个小时。
看了一遍除了sql注入之外,没有很好可以直接利用的漏洞
小结
对于这个系统我并没有进行彻底的审计,但是从上面的漏洞看来此系统在设计之初并没有考虑到安全设计的方面,所以导致存在很多简单但又有危害的漏洞。
其实对于一般web应用来说代码审计并不是很难的事情,SSM框架审计漏洞的方式同正常的java代码审计没有区别,网上有很多非常优秀的java代码审计文章,关于每个漏洞的审计方式写的都非常全面,我们需要的就只是将其移植到SSM框架的审计中来,我们明白SSM的执行流程了,自然就明白了该怎么在SSM框架中跟踪参数。
参考资料
https://paper.seebug.org/1075/#3-ssm
https://p0rz9.github.io/2019/05/11/SSM%E6%A1%86%E6%9E%B6%E5%AE%A1%E8%AE%A1%E6%80%9D%E8%B7%AF/
https://blog.nowcoder.net/n/be73b8f592504ae8b1d00368433061be