Skip to main content
Press slash or control plus K to focus the search. Use the arrow keys to navigate results and press enter to open a threat.
Reconnecting to live updates…

Froxlor customer can create MySQL databases on disallowed servers via Mysqls.add API

0
Medium
Published: 07/02/2026 (07/02/2026, 19:23:49 UTC)
Source: GCVE Database
Product: froxlor/froxlor

Description

## Summary The `Mysqls.add` API command (`lib/Froxlor/Api/Commands/Mysqls.php`) accepts a customer-controlled `mysql_server` parameter and only validates that the value is numeric and that the server index exists in `userdata.inc.php`. It never checks the value against the calling customer's `allowed_mysqlserver` allowlist. A customer can therefore create a database, plus a MySQL user with a password they choose, on any MySQL server the operator has configured — including servers that were explicitly excluded from that customer (e.g. a separate cluster, premium-tier host, or another tenant pool). The same `allowed_mysqlserver` check is correctly enforced in `MysqlServer::get()` / `MysqlServer::listing()` and in the customer-facing UI (`customer_mysql.php`), confirming the omission is a bug, not by-design. ## Details **Vulnerable code path** — `lib/Froxlor/Api/Commands/Mysqls.php:69-99` (`add()`): ```php public function add() { if (($this->getUserDetail('mysqls_used') < $this->getUserDetail('mysqls') || ...) { ... $customer = $this->getCustomerData('mysqls'); // line 80 $dbserver = $this->getParam('mysql_server', true, // line 81 — user-controlled $this->getDefaultMySqlServer($customer)); ... $dbserver = Validate::validate($dbserver, ..., '/^[0-9]+$/', ...); // line 92 — numeric only Database::needRoot(true, $dbserver, false); // line 93 — root ctx for ANY index Database::needSqlData(); $sql_root = Database::getSqlData(); Database::needRoot(false); if (!is_array($sql_root)) { // line 97 — only existence check throw new Exception("Database server with index #" . $dbserver . " is unknown", 404); } ... $username = $dbm->createDatabase($newdb_params['loginname'], $password, $dbserver, ...); // line 116/118 — DB+user created ... Database::pexecute($stmt, ["customerid"=>$customer['customerid'], ..., "dbserver"=>$dbserver], ...); } } ``` The `$customer['allowed_mysqlserver']` field IS read on line 80 but is only consumed by `getDefaultMySqlServer()` (lines 566-573) to compute a default when the request omits `mysql_server`. As soon as the client supplies the parameter, the default path is skipped and no further authorization gate runs. **Cross-file evidence the check is intended elsewhere:** - `lib/Froxlor/Api/Commands/MysqlServer.php:319-323` — `get()` rejects with HTTP 405 when `$dbserver` is not in `allowed_mysqlserver`: ```php if ($this->isAdmin() == false) { $allowed_mysqls = json_decode($this->getUserDetail('allowed_mysqlserver'), true); if ($allowed_mysqls === false || empty($allowed_mysqls) || !in_array($dbserver, $allowed_mysqls)) { throw new Exception("You cannot access this resource", 405); } ... } ``` - `lib/Froxlor/Api/Commands/MysqlServer.php:252-257` — same allowlist filter on `listing()`. - `customer_mysql.php:222` — UI rejects with `Response::dynamicError('No permission')` when `empty($allowed_mysqlservers)`. **Chain of execution (attacker → impact):** 1. Customer authenticates to `api.php` with apikey/secret. The only API gate is `cust_api_allowed`; `allowed_mysqlserver` is not consulted at auth time. 2. Customer sends JSON `{"command":"Mysqls.add","params":{"mysql_password":"<valid>","mysql_server":<disallowed_idx>}}`. 3. `Mysqls.php:71` quota check passes (`mysqls_used < mysqls`). 4. `Mysqls.php:80` `getCustomerData('mysqls')` returns the caller's own row. 5. `Mysqls.php:81` `$dbserver` is set from the request (default-fallback path skipped). 6. `Mysqls.php:92` numeric regex passes. 7. `Mysqls.php:93-99` `Database::needRoot(true, $dbserver, false)` switches to the root context of the attacker-chosen server; existence check passes. 8. `Mysqls.php:116/118` `DbManager::createDatabase(...)` runs against the disallowed server using stored root credentials, creating the DB and granting the supplied password to `<loginname>_<sqlN>` (DbManager.php:177-218). 9. `Mysqls.php:127-141` inserts a row into `TABLE_PANEL_DATABASES` with the attacker's `customerid` and the disallowed `dbserver`, allowing later management via `Mysqls.get/update/delete` (which only filter by `customerid` for non-admins, e.g. `Mysqls.php:282`). ## PoC Preconditions on the target instance: - ≥2 MySQL servers configured in `lib/userdata.inc.php` (e.g. index 0 default, index 1 internal/premium). - Customer X with `allowed_mysqlserver=[0]`, `cust_api_allowed=1`, `mysqls > 0`, and an issued API key (`apikey:secret`). Request — customer creates a database on server `1`, which is *not* in their allowlist: ```bash curl -k -u 'CUST_APIKEY:CUST_SECRET' \ -H 'Content-Type: application/json' \ -X POST \ -d '{"command":"Mysqls.add","params":{"mysql_password":"ValidP@ssw0

CVSS v3.1

Score 4.3medium

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
None
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N

Affected software

Packagistghsa
froxlor/froxlor
Affected versions
<2.3.7

Run on your own infrastructure? Check whether these packages are installed with threat-finder — our free open-source scanner.

AI-Powered Analysis

Machine-generated threat intelligence

AILast updated: 07/02/2026, 23:13:13 UTC

Technical Analysis

The Mysqls.add API command in Froxlor (lib/Froxlor/Api/Commands/Mysqls.php) accepts a customer-controlled mysql_server parameter and only validates that it is numeric and exists in the server index list. It does not check if the mysql_server is in the calling customer's allowed_mysqlserver allowlist. This omission allows a customer to create databases and MySQL users on any MySQL server configured by the operator, including those explicitly excluded from that customer. Other API commands and the UI correctly enforce the allowed_mysqlserver check, confirming this is a bug. The vulnerability affects Froxlor versions before 2.3.7. Exploitation requires authenticated API access and allows unauthorized database creation on disallowed servers.

Potential Impact

An authenticated customer can create MySQL databases and users on any MySQL server configured in Froxlor, including servers that are explicitly disallowed for that customer. This can lead to unauthorized use of database resources, potential privilege escalation, and cross-tenant access in multi-tenant environments. The vulnerability does not disclose data directly but allows unauthorized modification of database resources on restricted servers.

Mitigation Recommendations

A fix is available in Froxlor version 2.3.7 and later. Users should upgrade to version 2.3.7 or newer to ensure the mysql_server parameter is properly validated against the customer's allowed_mysqlserver list. Until patched, restrict API access to trusted customers only and monitor for unauthorized database creation attempts. Patch status is not explicitly stated in the input but the affectedVersions field indicates versions before 2.3.7 are vulnerable, implying 2.3.7 contains the fix.

Pro Console: star threats, build custom feeds, automate alerts via Slack, email & webhooks.Upgrade to Pro

Technical Details

Gcve Source
db.gcve.eu
Osv Id
GHSA-q4rm-m6xh-5pv7
Osv Schema Version
1.4.0
Aliases
[]
Ecosystems
["Packagist"]
Database Specific Severity
MODERATE
Cvss Version
3.1

Threat ID: 6a46ecb927e9c7971943cb39

Added to database: 07/02/2026, 22:56:57 UTC

Last enriched: 07/02/2026, 23:13:13 UTC

Last updated: 07/31/2026, 12:27:30 UTC

Views: 36

Community Reviews

0 reviews

Crowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.

Sort by
Loading community insights…

Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.

Actions

PRO

Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.

Please log in to the Console to use AI analysis features.

Need more coverage?

Upgrade to Pro Console for AI refresh and higher limits.

For incident response and remediation, OffSeq services can help resolve threats faster.

Latest Threats

Breach by OffSeqOFFSEQFRIENDS — 25% OFF

Check if your credentials are on the dark web

Instant breach scanning across billions of leaked records. Free tier available.

Scan now
OffSeq TrainingCredly Certified

Lead Pen Test Professional

Technical5-day eLearningPECB Accredited
View courses