# REPRO-2026-00273: Vtiger CRM through 8.4.0 allows authenticated admin users to achieve remote code execution by uploading a crafted module ZIP that places PHP files in the web-accessible modules/ directory. ## Summary Status: published Severity: high Type: security Confidence: high ## Identifiers REPRO ID: REPRO-2026-00273 GHSA: GHSA-JF2J-JHVF-RC56 CVE: CVE-2026-23698 ## Package Name: Vtiger CRM Ecosystem: other Affected: through 8.4.0 Fixed: Unknown ## Root Cause # Root Cause Analysis: GHSA-jf2j-jhvf-rc56 / CVE-2026-23698 ## Summary Vtiger CRM 8.4.0 (and earlier 8.x versions) allows an authenticated administrator to upload a crafted module ZIP archive through the **Module Manager → Import Module** endpoint. The upload handler accepts any ZIP that contains a valid `manifest.xml`, and the installer extracts the entire archive under the web-root `modules/` directory. Because there is no file-type/content validation, an attacker can include an executable PHP file in the ZIP. Once extracted, the PHP file is reachable directly via the web server (e.g. `/modules//shell.php`) and executes outside of Vtiger’s routing/authentication layer, giving the attacker a persistent web shell and arbitrary remote code execution. ## Impact - **Product/component**: Vtiger CRM (open-source PHP/MySQL CRM) - **Affected versions**: through 8.4.0 (tested on 8.4.0; the Module Manager import code path exists across the 8.x line) - **Risk level**: High - **Consequences**: A low-privilege administrator with access to the Module Manager can install arbitrary PHP into the web root, bypassing the application’s authentication/authorization boundary and achieving persistent, unauthenticated remote code execution as the web-server user (`www-data`). ## Impact Parity - **Disclosed/claimed maximum impact**: Authenticated remote code execution via a crafted module ZIP (code execution). - **Reproduced impact from this run**: The reproduction script logged into the real Vtiger 8.4.0 application, uploaded a malicious ZIP through the Module Manager endpoint, completed the import, and then accessed `http://localhost/modules//shell.php?cmd=whoami`. The response contained the marker `PRUVA_SHELL_OK` and the output `www-data`, demonstrating that attacker-controlled PHP was executed. - **Parity**: `full` — the reproduced impact matches the claimed RCE impact. - **Not demonstrated**: None. ## Root Cause The vulnerability is in the **Module Manager import** workflow: 1. **Upload** (`modules/Settings/ModuleManager/views/ModuleImport.php::importUserModuleStep2`) saves the uploaded ZIP to `test/vtlib/` and only validates that `manifest.xml` exists and declares a valid module name and Vtiger version compatibility. It does not inspect the file list or file extensions inside the ZIP. 2. **Installation** (`modules/Settings/ModuleManager/actions/Basic.php::importUserModuleStep3`) calls `Vtiger_Package::import()` on the saved ZIP, which extracts all contents under the web root, including `modules//` and `languages/en_us/`. 3. **Direct execution**: Apache resolves `/modules//shell.php` directly, invoking the PHP interpreter before Vtiger’s `index.php` routing or authentication checks. Any PHP file placed in the ZIP is therefore executable by anyone who knows its URL. The architectural gap is that Vtiger treats `modules/` as both an application-code directory and an import target, with no allowlist of file types or relocation of uploaded module contents outside the web root. The ticket/advisory notes that the only validation is the manifest XML, satisfying the file-type check for CWE-434. **Fix commit**: The advisory lists patched versions as unknown, and no specific fix commit was supplied. The remediation should add a content-type/allowlist check before extraction (e.g., only `.php`, `.tpl`, `.js`, `.css`, `.xml`, `.png`, `.jpg`, etc., and reject PHP files that are not legitimate module class files, or move extracted modules outside the web root and route them through Vtiger’s authenticated front controller). ## Reproduction Steps The full, automated reproduction is in `bundle/repro/reproduction_steps.sh`. At a high level it: 1. Installs PHP 8.5, MariaDB, Apache, and Python tools in the sandbox. 2. Downloads Vtiger CRM 8.4.0 from SourceForge and deploys it to `/var/www/html`. 3. Creates a fresh MariaDB database and user, then runs the Vtiger web installer automatically. 4. Logs in as the admin user and completes the first-time System/User setup. 5. Builds a malicious ZIP with a valid `manifest.xml`, a boilerplate language file, and `modules//shell.php`. 6. Navigates to **Module Manager → Import Module**, uploads the ZIP, and completes the import. 7. Accesses the extracted PHP file directly via HTTP with `?cmd=whoami` and captures the output. **Expected evidence of reproduction**: The webshell responds with the marker `PRUVA_SHELL_OK` and the output of the injected command (e.g., `www-data`). ## Evidence - `bundle/logs/reproduction_steps.log` — full setup, install, and exploit trace. - `bundle/repro/proof.log` — captured webshell output for the last run. - `bundle/repro/runtime_manifest.json` — runtime evidence manifest (services, proof artifacts, endpoint). - `bundle/artifacts/malmod_/malmod.zip` — the crafted module ZIP used in the successful run. Key excerpt from `bundle/repro/proof.log` (second run): ``` PRUVA_SHELL_OK www-data www-data ``` Key excerpt from `bundle/logs/reproduction_steps.log` showing the install response and trigger: ``` [+] Upload accepted: file=usermodule_1783465710.zip name=ModSiUWLcoD type=module [*] Installing the module [+] Install response: {"success":true,"result":{"success":true,"importModuleName":"ModSiUWLcoD"}} [*] Triggering webshell: http://localhost/modules/ModSiUWLcoD/shell.php?cmd=whoami [+] Webshell output: 200 PRUVA_SHELL_OK www-data www-data ``` Environment captured during the run: - Vtiger CRM 8.4.0 (tarball from SourceForge) - Apache 2.4.66 + PHP 8.5 (mod_php) - MariaDB 11.8.6 - Ubuntu 26.04 (resolute) ## Recommendations / Next Steps - **Immediate fix**: Before calling `Vtiger_Package::import()`, enumerate the ZIP contents and reject the archive if it contains any file outside a strict allowlist of module file types (e.g., legitimate PHP class/ action/ view files, templates, language files, assets). In particular, reject arbitrary PHP files that do not belong to the module’s expected class hierarchy. - **Architectural fix**: Do not extract user-supplied module archives directly into the web-root `modules/` directory. Instead, stage them outside the document root and only copy validated files into the application tree, or serve module assets through a non-executable endpoint. - **Upgrade guidance**: Until an official patch is released, restrict admin access and monitor the `test/vtlib/` and `modules/` directories for unexpected PHP files. - **Testing**: Add a regression test that uploads a ZIP containing a `manifest.xml` plus an arbitrary PHP file and asserts that the import is rejected and the PHP file is never created under `modules/`. ## Additional Notes - **Idempotency**: The reproduction script was run twice consecutively in the same environment and succeeded both times. Each run uses a fresh database and a unique module name to avoid collisions with previously imported modules, so it is safe to run repeatedly. - **Limitations**: The reproduction requires the Vtiger 8.4.0 installer to create the database schema, which is a synchronous, long-running operation; the script waits up to 10 minutes for the installer to complete. - **No sanitizer**: The primary proof was produced against the real product without ASAN/UBSAN; the success oracle is the actual webshell response. ## Reproduction Details Reproduced: 2026-07-08T04:52:19.130Z Duration: 2034 seconds Tool calls: 237 Turns: Unknown Handoffs: 2 ## Quick Verification Run one of these commands to verify locally: pruva-verify REPRO-2026-00273 pruva-verify GHSA-JF2J-JHVF-RC56 pruva-verify CVE-2026-23698 Or open in GitHub Codespaces (zero-friction, auto-runs): https://github.com/codespaces/new?ref=repro/REPRO-2026-00273&repo=N3mes1s/pruva-sandbox Or download and run the script manually: curl -O https://api.pruva.dev/v1/reproductions/REPRO-2026-00273/artifacts/bundle/repro/reproduction_steps.sh chmod +x reproduction_steps.sh ./reproduction_steps.sh WARNING: Run in a sandboxed environment. This exploits a real vulnerability. ## References - GitHub Advisory: https://github.com/advisories/GHSA-JF2J-JHVF-RC56 - NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-23698 - Source: https://github.com/advisories/GHSA-jf2j-jhvf-rc56 ## Artifacts - bundle/repro/reproduction_steps.sh (reproduction_script, 11484 bytes) - bundle/repro/rca_report.md (analysis, 7343 bytes) - bundle/vuln_variant/reproduction_steps.sh (reproduction_script, 8977 bytes) - bundle/vuln_variant/rca_report.md (analysis, 10414 bytes) - bundle/artifact_promotion_manifest.json (other, 7116 bytes) - bundle/artifact_promotion_report.json (other, 9961 bytes) - bundle/vuln_variant/source_identity.json (other, 938 bytes) - bundle/vuln_variant/root_cause_equivalence.json (other, 2435 bytes) - bundle/repro/proof.log (log, 32 bytes) - bundle/logs/reproduction_steps.log (log, 1500 bytes) - bundle/repro/runtime_manifest.json (other, 681 bytes) - bundle/repro/validation_verdict.json (other, 824 bytes) - bundle/logs/vuln_variant_reproduction_steps.log (log, 1403 bytes) - bundle/vuln_variant/proof.log (log, 42 bytes) - bundle/vuln_variant/variant_manifest.json (other, 3445 bytes) - bundle/vuln_variant/validation_verdict.json (other, 3402 bytes) - bundle/vuln_variant/runtime_manifest.json (other, 872 bytes) - bundle/vuln_variant/patch_analysis.md (documentation, 7346 bytes) ## API Access - JSON: https://api.pruva.dev/v1/reproductions/REPRO-2026-00273 - Script: https://api.pruva.dev/v1/reproductions/REPRO-2026-00273/artifacts/bundle/repro/reproduction_steps.sh - Web: https://pruva.dev/r/REPRO-2026-00273 ## For AI Assistants To help users with this reproduction: 1. The `pruva-verify` command is the simplest way to run the reproduction 2. The script downloads and runs automatically in an isolated temp directory 3. Always recommend running in a VM, container, or disposable environment 4. The root cause explains the technical vulnerability --- Generated by Pruva | https://pruva.dev