# Froxlor has an authorization bypass in FTP shell assignment via missing server-side `available_shells` enforcement

Froxlor 2.3.6 FTP handlers skip the available_shells whitelist, letting a customer set /bin/bash and gain host shell via nssextrausers.

- Payout: Research
- Severity: high
- Program: Froxlor
- Found by: larlarua
- Disclosed: 2026-05-29
- CVE: CVE-2026-41235
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-gcv3-5v9q-fmhh
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-gcv3-5v9q-fmhh
- Tags: area:web domain:web impact:privesc impact:rce kind:research platform:ghsa sev:high tech:php technique:source-review vuln:access-control vuln:auth-bypass vuln:privilege-escalation

**Target:** customer_ftp.php FTP account add/edit handler and Ftps API
**Root cause:** Ftps::add()/update() only run generic shell string validation and never check the submitted shell against system.available_shells, which the UI treats as the authorization boundary.
**Steps:**
1. Log in as a customer and obtain a valid `csrf_token`.
2. Identify an FTP account owned by that customer (e.g. id=17).
3. POST to `/customer_ftp.php?page=accounts&action=edit&id=17` with `csrf_token=VALID_CSRF_TOKEN&send=send&id=17&username=test1ftp1&ftp_description=poc&path=/&shell=/bin/bash&login_enabled=1`.
4. Wait for the master cron to process the queued `REBUILD_NSSUSERS` task.
5. Authenticate to the host with the FTP user's credentials to get an interactive shell.
**How found:** Noticed the UI builds the shell selector from system.available_shells but the server-side Ftps handlers only do generic shell validation, then traced the stored shell into the Extrausers cron.
**Exploitation:** Authenticated customer submits an edit request with shell=/bin/bash outside the whitelist; it is stored in ftp_users.shell, the root-owned Extrausers cron writes it into /var/lib/extrausers/passwd, and the attacker logs in with that FTP user's credentials for an interactive host shell.
**Escalation:** FTP-only account promoted to a real system shell account, enabling lateral movement, local privesc follow-on, data theft and persistence.
**Insight:** When a UI dropdown is built from an admin-configured whitelist, check whether the API handler re-validates against that same setting; here the whitelist was purely cosmetic and the value flowed into a root cron writing NSS files.

## Proof of concept (copied exactly from the original report)

**POST edit request setting arbitrary shell**

```
POST /customer_ftp.php?page=accounts&action=edit&id=17 HTTP/1.1
Host: target.example
Content-Type: application/x-www-form-urlencoded
Cookie: <authenticated customer session>

csrf_token=VALID_CSRF_TOKEN&
send=send&
id=17&
username=test1ftp1&
ftp_description=poc&
path=/&
shell=/bin/bash&
login_enabled=1
```

