CTIPilot
AI-generated · no human review · verify critical claims against the linked source. how it works →
← Back to Daily brief 2026-09-23
ROUTINECVE-2026-43641 +2updatedNATOB2vulnerability

Virtualizor VPS/hypervisor control panel: a login-page guard's own exemption for act=login lets an unauthenticated attacker reach root

A single mis-scoped pre-auth check in a hosting control panel exposes three unauthenticated flaws, one a path to root

Analysis

VulnCheck's Initial Access Intelligence team discloses three unauthenticated vulnerabilities in Virtualizor, Softaculous' commercial VPS/hypervisor control panel (KVM/OpenVZ/LXC), all reached through a single mis-scoped pre-authentication guard. In enduser/admin.php, the admin panel (ports 4084/4085) redirects every request to the login page except one: "the redirect that guards the admin panel fires for every action except one. That one is login" (VulnCheck, 2026-09-22). The act=login request that should only reach the login page instead falls through the guard and reaches an unauthenticated from_billing_module handler with no session, API key or slave credentials. CVE-2026-43641 (CWE-78 OS command injection) is the flagship: the handler's uid field, taken unvalidated from an unserialized attacker POST body, is concatenated into a shell command inside billing_unsuspend() → vexec() → proc_open(), giving remote root command execution. VulnCheck states "verified on the lab: /tmp/x reads uid=0(root) gid=0(root) groups=0(root)" (VulnCheck, 2026-09-22). Exploitation requires an existing in-house-billing account on the target that is currently suspended and paid up, server state that exists on any install using that billing mode by design, and no separate enumeration step is needed because the same request path is a non-destructive timing oracle: injecting a sleep payload via the uid field hangs the response only for a valid, eligible uid. The bug additionally needs MySQL's default non-strict sql_mode, which VulnCheck confirmed is what Virtualizor's own bundled MySQL 5.5.62 stack ships uncorrected, so this is a default-production condition, not a lab artifact. The root-level impact is possible because Virtualizor's EMPS stack splits PHP execution across separate php-fpm pools by port: the admin-panel index.php on ports 4084/4085 runs in a pool that executes as root, while the client panel and every other .php file run in an unprivileged pool. The exploit therefore never drops a PHP web shell (which would run unprivileged) and instead relays each command's output to a randomly named static file written into the webroot and served directly by nginx.

CVE-2026-43642 (CWE-502 PHP object injection) reaches the same unauthenticated handler's native unserialize() call on attacker-controlled POST data with no allowed_classes restriction; VulnCheck demonstrates no working gadget chain in the stock code, but the primitive is live for any add-on or plugin that introduces a class with a __wakeup or __destruct method. CVE-2026-43643, which VulnCheck's advisory classes as CWE-862 missing authorization (VulnCheck, 2026-09-22) and its blog post's table as CWE-639, lets an unauthenticated caller zero out or inflate any tenant's account balance through the same handler's whmcs branch, via a parameterized but unauthenticated balance UPDATE with no ownership check. VulnCheck audited 3.2.9 patch 7 and, in a 2026-09-20 re-test from decoded source, found patch 8 vulnerable as well (VulnCheck, 2026-09-22). "Softaculous patched all three in 3.2.9 patch 9 (2026-09-01), and the fix carries into 3.3.0 (2026-09-09), the current build. Patch 7, the build audited above, and patch 8 are both still vulnerable" (VulnCheck, 2026-09-22). The fix requires a validated API call (HMAC API key or admin credentials) before the billing hook is reachable at all, casts the uid value to an integer before it reaches the shell, restricts the deserialization call with allowed_classes => false, and adds an ownership check to the balance-write branch. VulnCheck's post does not state whether it has observed in-the-wild exploitation; it also turned the command-injection flaw into a self-contained exploit module, built on VulnCheck's own open-source "go-exploit" framework, that fingerprints the Virtualizor admin panel, finds an eligible suspended account on its own via the timing oracle, and returns a root shell with no credentials and no account information supplied by the operator. VulnCheck's post demonstrates this module against its own lab instance and does not state that the CVE-specific module itself was released publicly, only that it is built on the publicly available go-exploit framework.

Detection concept: VulnCheck's exploit reaches the admin panel on ports 4084/4085 with act=login and from_billing_module set and a serialized billing_data field in the POST body (VulnCheck, 2026-09-22). On any self-managed Virtualizor installation, look in admin-panel access logs for unauthenticated requests carrying that combination, since a login request has no use for billing-module parameters. The injected commands run in the admin panel's root php-fpm pool and relay their output through randomly named static files written into the webroot and then removed (VulnCheck, 2026-09-22), so in host telemetry alert on processes spawned by that pool outside Virtualizor's own process tree and on short-lived static files created in the webroot outside a deployment. Triage: in the fixed build the billing hook runs only after a validated API call, a valid API key or admin API credentials (VulnCheck, 2026-09-22), so a request reaching the billing handler with no session or API-key context is the discriminator, whatever its act parameter claims.

Cited evidence

The redirect that guards the admin panel fires for every action except one. That one is login.

Verified on the lab: /tmp/x reads uid=0(root) gid=0(root) groups=0(root).

Softaculous patched all three in 3.2.9 patch 9 (2026-09-01), and the fix carries into 3.3.0 (2026-09-09), the current build. Patch 7, the build audited above, and patch 8 are both still vulnerable

VulnCheck 2026-09-22

Updates3

Correction

VulnCheck's disclosure gives no CVSS scores for the three flaws (VulnCheck, 2026-09-22). The scores shown earlier are not on that page. The weakness classes, CWE-78, CWE-502 and CWE-639, come from VulnCheck's own table (VulnCheck, 2026-09-22).

Correction

VulnCheck says no working gadget chain is demonstrated in the stock code, not that none exists (VulnCheck, 2026-09-22). The entry moves to routine priority: no exploitation is reported, a vendor fix has existed since 2026-09-01, the root path needs an existing suspended billing account, and Virtualizor sits outside the typical public-administration estate.

Improvement

VulnCheck, the CVE Numbering Authority for the three flaws, publishes CVSS 4.0 base scores on its per-CVE advisories: 9.3 for CVE-2026-43641 (VulnCheck, 2026-09-22), 9.2 for CVE-2026-43642 (VulnCheck, 2026-09-22) and 8.7 for CVE-2026-43643 (VulnCheck, 2026-09-22). The advisory classes CVE-2026-43643 as CWE-862 missing authorization, where the table in VulnCheck's blog post gives CWE-639 (VulnCheck, 2026-09-22; VulnCheck, 2026-09-22).

Sources4

Revision history

  1. Published 2026-09-23T0405Z-intel
  2. Correction 2026-09-30T0639Z-audit

    Priority is lowered from high to notable: a flaw in hosting-provider billing software outside the typical public-administration estate. CVSS scores that the cited disclosure does not carry are removed from the text and the structured data, and the sourcing note keeps provenance only. The patch-level statement now separates the audited patch 7 from VulnCheck's re-test of patch 8, the summary no longer calls VulnCheck's exploit module internal or unpublished, and the detection concept and triage line now cite VulnCheck. The default-configuration tag is removed, because the root command injection needs an existing suspended in-house-billing account. The headline now says only one of the three flaws reaches root.

    Changed: priority cves body sourcing_note summary tags headline techniques

  3. Correction 2026-10-11T1307Z-audit

    VulnCheck says no working gadget chain is demonstrated in the stock code, not that none exists; the wording now follows the source. Priority lowers to routine: no exploitation, a vendor fix since 2026-09-01, a root path that needs an existing suspended billing account, and a product outside the typical public-administration estate. The patch action is dropped: the takeaway carries it for a routine item.

    Changed: body priority actions

  4. Improvement 2026-10-21T0800Z-audit

    VulnCheck's per-CVE advisories, as the CVE Numbering Authority, publish CVSS 4.0 scores of 9.3, 9.2 and 8.7 for the three flaws; the scores are restored from those pages, and the earlier correction now says only that the blog post lacks them. CVE-2026-43643 is classed CWE-862 missing authorization in VulnCheck's advisory, against CWE-639 in its blog's table, and the analysis states both.

    Changed: body cves sources sourcing_note

PROVENANCE

AI-generated · no human review · this permalink is the shareable record for the finding · verify operationally critical claims against the linked primary source.