JAVA 代码审计 | 某充电桩系统代码审计

admin 2025年5月18日03:10:28评论4 views字数 3906阅读13分1秒阅读模式

JAVA 代码审计 | 某充电桩系统代码审计

前言

马上临近毕业, 给朋友要了一下他的毕业设计源码 (毕业设计基于SpringBoot的XXX系统懂的都懂), 周六搭建一下简单玩一玩.

系统架构

网站架构解释

开发语言:Java

框架:SpringBoot

JDK版本:JDK 1.8

服务器:tomcat7

数据库:Mysql 5.7

后台路径地址:localhost:8080/springboot9f1sp4rb/admin/dist/index.html (默认账号admin 密码admin)

前台路径地址:localhost:8080/springboot9f1sp4rb/front/dist/index.html

POM.XML 初步分析

首先使用OpenSCA Xcheckpom.xml文件进行分析, 大致浏览一下:

JAVA 代码审计 | 某充电桩系统代码审计

可以后续在安全组件方面进行入手.

静态资源访问策略分析

而由于是/front/dist/index.html, 要么存在该RequestMapping控制器定义要么在application.yml中定义了静态资源映射, 要么继承了WebMvcConfigurationSupport类并实现了它的addResourceHandlers方法, 打开application.yml一探究竟:

JAVA 代码审计 | 某充电桩系统代码审计

不存在front目录的配置, 全局搜索是否存在front的控制器:

JAVA 代码审计 | 某充电桩系统代码审计

这里使用了WebMvcConfigurationSupport这种方式, 从意外收获中可以发现的是, 鉴权使用的是自定义的Interceptor而并不是pom.xml中定义的Shiro框架. 所以之后的分析都在AuthorizationInterceptor这个类中:

JAVA 代码审计 | 某充电桩系统代码审计

包之间的关系梳理

JAVA 代码审计 | 某充电桩系统代码审计

基于自写鉴权逻辑的鉴权分析

CORS 漏洞挖掘

在上面我们看到了该系统使用AuthorizationInterceptor::preHandle进行鉴权的, 那么接下来对其进行分析:

JAVA 代码审计 | 某充电桩系统代码审计

在分析的途中我们发现了意外收获, 这边ACAC & ACAO完全可被利用, 所以存在一个 CORS 漏洞. 那么先不管, 看一下如何进行身份鉴权验证的.

未授权部分

JAVA 代码审计 | 某充电桩系统代码审计

从中可以看到的是, 若一个方法使用了IgnoreAuth注解进行声明, 那么直接无需鉴权即可访问, 所以在代码审计的过程中尽量去找一些以@IgnoreAuth注解声明的方法即可挖掘未授权相关的漏洞.

授权部分【缺陷:无视用户身份垂直越权】

JAVA 代码审计 | 某充电桩系统代码审计

在授权校验过程中, 通过HTTP请求过来的Header-Token头与token表中进行匹配, 若匹配成功才可通过授权. 否则页面会返回请先登录. 而由于管理员的token与普通用户的token在同一张表中, 所以这里会出现一个垂直越权的问题, 用普通用户的token即可操作管理员后台的功能.

基于 MyBatis-Plus 的 SQL 注入漏洞挖掘

由于使用了MyBatis-Plus框架, 所以全局搜索${, 查看一些能够利用的点:

JAVA 代码审计 | 某充电桩系统代码审计

从结果中可以看到有很多包含 ${ 的, 不过这个`${ew.sqlSegment}由于是使用了MyBatis-Plus的条件查询从API层传递过来的, 所以不在我们的考虑范围内, 那么如何过滤掉这些所有的呢?直接用该正则表达式即可:^(?!.1=1).?${.*$`, 最终效果如下:

JAVA 代码审计 | 某充电桩系统代码审计

能出来的结果还是多的, 下面针对性的挑一些经典的放在文章中.

未授权 SELECT 型注入(一)

CommonDao.xml文件中存在如下定义, 并从DAO层往上查找到Controller层如下:

JAVA 代码审计 | 某充电桩系统代码审计

更值得一提的是该方法使用了@IgnoreAuth注解进行声明, 无需授权, 构造HTTP包如下:

GET /springboot9f1sp4rb/option/dual%23/user() HTTP/1.1
Host: localhost:8080


结果如下:

JAVA 代码审计 | 某充电桩系统代码审计

授权 SELECT 型注入(二)

JAVA 代码审计 | 某充电桩系统代码审计

这里需要用户登录之后, 进行闭合SQL语句, 完整HTTP包如下:

DELETE /springboot9f1sp4rb/chongdianjilu/value/id/id)),user()FROM%20chongdianjilu%23 HTTP/1.1
Host: localhost:8080
Token: 9sq4y8arlhnmfsnfwb9pz1l9i74x05bf


RequestMapping兼容所有类型请求, 运行结果:

JAVA 代码审计 | 某充电桩系统代码审计

授权 UPDATE 型注入 (三) 失败案例

以上案例是通过 SELECT 并且语句中全使用了 ${ 的案例, 接下来这个案例比较特殊, 看似存在注入, 但实际上会遇到参数不匹配的错误:

JAVA 代码审计 | 某充电桩系统代码审计

虽然看起来是存在注入的, 但MyBatis中有个特性, 就是注释中不能存在#{.

当我们注入${table}字段后, 由于我们需要通过#或者--空格闭合进行SQL注入, 由于后面存在#{sfsh}以及#{id}刚好满足了MyBatis中注释后面不能存在#, 所以我们在${table}处不可以使用注释符进行闭合语句.

可参考: https://blog.csdn.net/hanpenghu/article/details/84061990 || https://www.ctyun.cn/zhishi/p-164413

基于 Vue 的 XSS 漏洞挖掘

由于该系统使用的是Vue, 在Vue中模板渲染产生漏洞的也就是v-html, 那么假设在插入到数据库中的字符没有经过过滤, 在视图层则会解析HTML, 所以在这里全局搜索v-html, 查看哪些位置是允许输出HTML的:

JAVA 代码审计 | 某充电桩系统代码审计

那么打开该文件后, 审计Vue资源, 查看detail.content来自于哪里:

JAVA 代码审计 | 某充电桩系统代码审计

由于是RESTFUL风格, 所以这边可以通过搜索/aboutus/detail/{进行查询到具体是调用的哪个方法:

JAVA 代码审计 | 某充电桩系统代码审计

随便找到其中的一条SQL语句发现操作的是aboutus表, 在该Controller上找到添加方法:

JAVA 代码审计 | 某充电桩系统代码审计

该接口可以进行操作, 并且与之相同可以操作的是update方法:

JAVA 代码审计 | 某充电桩系统代码审计

最终向该API接口添加数据如下:

POST /springboot9f1sp4rb/aboutus/update HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:138.0) Gecko/20100101 Firefox/138.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Content-Type: application/json; charset=utf-8
Token: s9mek0i9ysuoc608unw1nuelqec9e55w
Content-Length: 252
Origin: http://localhost:8080
Connection: keep-alive
Cookie: JSESSIONID=1E3C40A0C8F8B8E50D3E3137D596CEA9
Priority: u=0

{"id":1,"title":"关于我们","subtitle":"ABOUT US","content":"<img src=x onerror=alert(2222)>","picture1":"upload/aboutus_picture1.jpg","picture2":"upload/aboutus_picture2.jpg","picture3":"upload/aboutus_picture3.jpg","addtime":"2024-02-24 11:44:41"}

访问首页触发:

JAVA 代码审计 | 某充电桩系统代码审计

其他v-html不一一演示了.

文件操作类

文件上传漏洞

搜索MultipartFile如下:

JAVA 代码审计 | 某充电桩系统代码审计

结果如下:

JAVA 代码审计 | 某充电桩系统代码审计

直接未授权, 并且文件后缀没有限制, 这里能够上传一把梭准备如下HTML表单:

<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>上传表单</title>
</head>
<body>
<formaction="http://localhost:8080/springboot9f1sp4rb/file/upload"method="post"enctype="multipart/form-data">
        文件: <inputtype="file"name="file"><br>
        类型: <inputtype="text"name="type"value="no"><br>
<inputtype="submit">
</form>
</body>
</html>

最终上传结果如下:

JAVA 代码审计 | 某充电桩系统代码审计

文件替换漏洞

除了该代码逻辑, 还存在一个任意文件删除的逻辑, 如下:

JAVA 代码审计 | 某充电桩系统代码审计

这里是一个文件替换的操作, deleteOnExit在虚拟机停止时进行删除, 下面则是重新覆盖:

JAVA 代码审计 | 某充电桩系统代码审计

文件下载漏洞

在该类下还存在一个文件下载的口子, 任意下载:

JAVA 代码审计 | 某充电桩系统代码审计

直接../跳目录就行:

JAVA 代码审计 | 某充电桩系统代码审计

逻辑漏洞类

任意密码重置

翻一下UsersController, 结果如下:

JAVA 代码审计 | 某充电桩系统代码审计

水平越权修改他人密码

原理之前垂直越权说过, 鉴权肯定能过.

JAVA 代码审计 | 某充电桩系统代码审计

这里直接根据传递过来的用户信息进行修改的, 存在漏洞的. 以及下面有个用户删除:

JAVA 代码审计 | 某充电桩系统代码审计

Ending...

原文始发于微信公众号(Heihu Share):JAVA 代码审计 | 某充电桩系统代码审计

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年5月18日03:10:28
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JAVA 代码审计 | 某充电桩系统代码审计http://cn-sec.com/archives/4076254.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息