Overview
Froxlor, a popular server management software, has a critical vulnerability in its API authentication mechanism. The vulnerability allows an attacker to bypass Two-Factor Authentication (2FA) when an API key and secret are compromised. This means that even if a user has enabled 2FA on their account, an attacker can still access all API operations without providing a second factor.
Technical Details
The vulnerability is located in the `FroxlorRPC::validateAuth` method, which does not enforce 2FA when authenticating with an API key and secret. The web UI, on the other hand, correctly requires a TOTP code after password verification. The affected code is located in `lib/Froxlor/Api/FroxlorRPC.php:75-105`.
```php
private static function validateAuth(string $key, string $secret): bool
{
// ...
// Missing: ANY check for type_2fa, TOTP verification, or 2FA status
return true;
}
```
Impact Analysis
The impact of this vulnerability is severe. An attacker who obtains a leaked API key and secret for a 2FA-protected account has full access to all API operations without providing a second factor. This allows access to sensitive resources, including:
- Customer data: PII (name, email, address) readable and modifiable
- Domains: Full control over domains, subdomains, DNS records
- Email accounts: Create, read, delete email accounts and forwarders
- FTP accounts: Access home directory paths and credentials
- MySQL databases: Full database management
- SSL certificates: Read private keys, modify certificate bindings
- 165 API functions: Including all write operations
Mitigation
To mitigate this vulnerability, the following steps can be taken:
1. Add 2FA verification to `FroxlorRPC::validateAuth()`. When the authenticated user has `type_2fa != 0`, require a TOTP code as an additional API parameter.
```php
// lib/Froxlor/Api/FroxlorRPC.php, after line 100:
// Check 2FA if enabled for this user
if (!empty($result['adminid'])) {
$user = Database::pexecute_first(
Database::prepare("SELECT type_2fa, data_2fa FROM panel_admins WHERE adminid = :id"),
['id' => $result['adminid']]
);
} else {
$user = Database::pexecute_first(
Database::prepare("SELECT type_2fa, data_2fa FROM panel_customers WHERE customerid = :id"),
['id' => $result['customerid']]
);
}
if ($user && $user['type_2fa'] != 0) {
// Require X-2FA-Code header or 'totp_code' in request body
$totp_code = $_SERVER['HTTP_X_2FA_CODE'] ?? null;
if (empty($totp_code)) {
throw new Exception('2FA code required', 401);
}
$tfa = new FroxlorTwoFactorAuth($user['data_2fa']);
if (!$tfa->verifyCode($totp_code)) {
throw new Exception('Invalid 2FA code', 403);
}
}
```
2. Disable API key creation for accounts with 2FA enabled.
3. Require 2FA re-verification when generating new API keys.