| Название | RainyGao DocSys 2.02.85 SQL Injection |
|---|
| Описание | A vulnerability was found in RainyGao DocSys up to 2.02.85. Affected is the function createDBForMysql of the file /Manage/resetDatabase.do of the component Database Management. Performing manipulation of the argument url results in SQL injection. The attack can be initiated remotely without any authentication. The exploit has been made public and could be used. The vendor was contacted early about this disclosure but did not respond in any way.
TECHNICAL DETAILS
Vulnerability type: CWE-89 Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection').
Affected endpoint: POST /DocSystem/Manage/resetDatabase.do
The database-reset feature is vulnerable to SQL injection. The url request parameter flows into BaseController.createDBForMysql(), where an attacker-controlled database name is concatenated into raw SQL and executed through a plain java.sql.Statement with no parameterization, escaping or validation.
The sink builds two SQL strings by literal concatenation with the attacker-controlled dbName and runs them through a raw Statement, never a PreparedStatement:
String checkdatabase = "show databases like \"" + dbName + "\""; // checks if the database exists
String createdatabase = "create database " + dbName; // creates the database
These strings are then executed directly:
ResultSet resultSet = stmt.executeQuery(checkdatabase);
...
if(stmt.executeUpdate(createdatabase) != 0)
The dbName is not user input at rest. It is derived from the url request parameter by getDBNameFromUrl() (BaseController.java), which takes url.split("?")[0], splits it on "/" and returns the last segment. That extraction is substring-preserving: it strips only the scheme, host and query string, so backticks, semicolons, double quotes, spaces and SQL comment markers all survive into the final statement.
Full flow from the external entry to the sink:
1. Spring MVC binds the HTTP url parameter of POST /Manage/resetDatabase.do to the url string of ManageController.resetDatabase (src/com/DocSystem/controller/ManageController.java) as an identity transform.
2. superAdminAccessCheck(authCode, "docSysInit", session, rt) passes because the attacker can supply a valid authCode leaked from the unauthenticated getDocSysInitConfig.do endpoint.
3. After testDB(...) returns false (the attacker points the URL at a database that does not exist), getDBNameFromUrl(type, url) is called.
4. getDBNameFromUrl returns the segment after the last "/" as dbName. For "jdbc:mysql://127.0.0.1:3306/REACH_MARKER_7f3a9`; DROP TABLE user;--" the result is "REACH_MARKER_7f3a9`; DROP TABLE user;--".
5. createDB(type, dbName, url, user, pwd) dispatches on type == "mysql" to createDBForMysql(dbType, dbName, url, user, pwd).
6. createDBForMysql concatenates dbName into checkdatabase and createdatabase and executes both through a bare Statement.
Authentication note: the reset-database endpoint is protected by an authCode check rather than a user session. A valid authCode is disclosed by the unauthenticated GET /Manage/getDocSysInitConfig.do endpoint, so the whole chain is reachable without any login.
PROOF OF CONCEPT
Step 1: unauthenticated fetch of the leaked docSysInitAuthCode.
GET /Manage/getDocSysInitConfig.do
Header: X-Requested-With: XMLHttpRequest
-> extract authCode from the response body.
Step 2: submit the injection with ONLY the leaked authCode, no login_user session.
POST /Manage/resetDatabase.do
Header: X-Requested-With: XMLHttpRequest
Body: authCode=<leaked>&type=mysql&url=jdbc:mysql://127.0.0.1:3306/REACH_MARKER_7f3a9`; DROP TABLE user;--&user=root&pwd=x
The DROP TABLE user statement is executed against the MySQL backend, proving arbitrary SQL execution. The REACH_MARKER_7f3a9 value embedded in the JDBC URL confirms the injected payload reached the sink.
IMPACT
An attacker can inject arbitrary SQL into the DocSys database backend through the url request parameter of the reset-database endpoint. This enables:
- Arbitrary data reads from the backend database.
- Schema and data modification, including dropping or altering tables, inserting rogue administrator accounts or deleting the user table.
- Depending on the database privileges of the configured connection account (often root), further compromise of the database server.
The attack is fully unauthenticated because the required authCode is disclosed by the unauthenticated getDocSysInitConfig.do endpoint, making it remotely exploitable by any network attacker.
REMEDIATION
1. Use PreparedStatement with parameter binding for both checkdatabase and createdatabase queries; never concatenate attacker-controlled input into SQL text.
2. Restrict or validate the database name derived from the url parameter (allow only [a-zA-Z0-9_$], reject backticks, semicolons, quotes, spaces and comment markers).
3. Protect the reset-database functionality with a real authenticated super-admin session check instead of a static authCode, and stop disclosing the authCode from the unauthenticated getDocSysInitConfig.do endpoint.
REFERENCES
- Repository: https://gitee.com/RainyGao/DocSys
- Issue: https://gitee.com/RainyGao/DocSys/issues/IK8NEU |
|---|
| Источник | ⚠️ https://gitee.com/RainyGao/DocSys/issues/IK8NEU |
|---|
| Пользователь | CyanM0un (UID 99906) |
|---|
| Представление | 30.08.2026 15:14 (1 месяц назад) |
|---|
| Модерация | 03.10.2026 21:44 (1 month later) |
|---|
| Статус | принято |
|---|
| Запись VulDB | 413377 [RainyGao DocSys до 2.02.85 Database Management BaseController.java BaseController.createDBForMysql url SQL-инъекция] |
|---|
| Баллы | 20 |
|---|