Cachet is an open source status page system. Prior to version 2.5.1, authenticated users, regardless of their privileges (User or Admin), can exploit a new line injection in the configuration edition feature (e.g. mail settings) and gain arbitrary code execution on the server. This issue was addressed in version 2.5.1 by improving `UpdateConfigCommandHandler` and preventing the use of new lines characters in new configuration values. As a workaround, only allow trusted source IP addresses to access to the administration dashboard.
{"id": "PRION:CVE-2021-39172", "vendorId": null, "type": "prion", "bulletinFamily": "NVD", "title": "Design/Logic Flaw", "description": "Cachet is an open source status page system. Prior to version 2.5.1, authenticated users, regardless of their privileges (User or Admin), can exploit a new line injection in the configuration edition feature (e.g. mail settings) and gain arbitrary code execution on the server. This issue was addressed in version 2.5.1 by improving `UpdateConfigCommandHandler` and preventing the use of new lines characters in new configuration values. As a workaround, only allow trusted source IP addresses to access to the administration dashboard.", "published": "2021-08-27T23:15:00", "modified": "2022-12-13T16:51:00", "epss": [{"cve": "CVE-2021-39172", "epss": 0.00257, "percentile": 0.63381, "modified": "2023-11-20"}], "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}, "cvss2": {"cvssV2": {"version": "2.0", "vectorString": "AV:N/AC:L/Au:S/C:P/I:P/A:P", "accessVector": "NETWORK", "accessComplexity": "LOW", "authentication": "SINGLE", "confidentialityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "availabilityImpact": "PARTIAL", "baseScore": 6.5}, "severity": "MEDIUM", "exploitabilityScore": 8.0, "impactScore": 6.4, "acInsufInfo": false, "obtainAllPrivilege": false, "obtainUserPrivilege": false, "obtainOtherPrivilege": false, "userInteractionRequired": false}, "cvss3": {"cvssV3": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH", "baseScore": 8.8, "baseSeverity": "HIGH"}, "exploitabilityScore": 2.8, "impactScore": 5.9}, "href": "https://www.prio-n.com/kb/vulnerability/CVE-2021-39172", "reporter": "PRIOn knowledge base", "references": ["https://github.com/fiveai/Cachet/releases/tag/v2.5.1", "https://github.com/fiveai/Cachet/security/advisories/GHSA-9jxw-cfrh-jxq6", "https://blog.sonarsource.com/cachet-code-execution-via-laravel-configuration-injection/"], "cvelist": ["CVE-2021-39172"], "immutableFields": [], "lastseen": "2023-11-22T00:59:50", "viewCount": 0, "enchantments": {"dependencies": {"references": [{"type": "checkpoint_advisories", "idList": ["CPAI-2021-1286"]}, {"type": "cve", "idList": ["CVE-2021-39172"]}, {"type": "github", "idList": ["GHSA-9JXW-CFRH-JXQ6"]}, {"type": "githubexploit", "idList": ["AAB95082-FA5E-592D-A514-EB82DC0E4955"]}, {"type": "osv", "idList": ["OSV:GHSA-9JXW-CFRH-JXQ6"]}, {"type": "sonarsource", "idList": ["SONARSOURCE:F5F06080F1D214075031C0B15519A0AE"]}]}, "score": {"value": 9.0, "uncertanity": 0.1, "vector": "NONE"}, "vulnersScore": 9.0}, "_state": {"dependencies": 1700614808, "score": 1700615001}, "_internal": {"score_hash": "f2d6008c239ecb4a935ad403ead7bf07"}, "affectedSoftware": [{"version": "2.5.1", "operator": "lt", "name": "catchet"}], "vendor_cvss2": {"score": "6.5", "vector": "AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"}, "vendor_cvss3": {}}
{"checkpoint_advisories": [{"lastseen": "2022-10-14T02:02:19", "description": "A remote code execution vulnerability exists in CachetHQ Cachet. Successful exploitation of this vulnerability could allow a remote attacker to execute arbitrary code on the affected system.", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 8.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2022-10-13T00:00:00", "type": "checkpoint_advisories", "title": "CachetHQ Cachet Remote Code Execution (CVE-2021-39172)", "bulletinFamily": "info", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "baseScore": 6.5, "vectorString": "AV:N/AC:L/Au:S/C:P/I:P/A:P", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "impactScore": 6.4, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-39172"], "modified": "2022-10-13T00:00:00", "id": "CPAI-2021-1286", "href": "", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "cve": [{"lastseen": "2023-11-28T15:46:02", "description": "Cachet is an open source status page system. Prior to version 2.5.1, authenticated users, regardless of their privileges (User or Admin), can exploit a new line injection in the configuration edition feature (e.g. mail settings) and gain arbitrary code execution on the server. This issue was addressed in version 2.5.1 by improving `UpdateConfigCommandHandler` and preventing the use of new lines characters in new configuration values. As a workaround, only allow trusted source IP addresses to access to the administration dashboard.", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 8.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2021-08-27T23:15:00", "type": "cve", "title": "CVE-2021-39172", "cwe": ["CWE-93"], "bulletinFamily": "NVD", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "baseScore": 6.5, "vectorString": "AV:N/AC:L/Au:S/C:P/I:P/A:P", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "impactScore": 6.4, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-39172"], "modified": "2022-12-13T16:51:00", "cpe": [], "id": "CVE-2021-39172", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-39172", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}, "cpe23": []}], "osv": [{"lastseen": "2023-05-22T16:41:42", "description": "### Impact\n\nAuthenticated users, regardless of their privileges (_User_ or _Admin_), can exploit a new line injection in the configuration edition feature (e.g. mail settings) and gain arbitrary code execution on the server.\n\n### Patches\n\nThis issue was addressed by improving `UpdateConfigCommandHandler` and preventing the use of new lines characters in new configuration values.\n\n### Workarounds\n\nOnly allow trusted source IP addresses to access to the administration dashboard.\n\n### References\n\n- https://blog.sonarsource.com/cachet-code-execution-via-laravel-configuration-injection\n\n### For more information\n\nIf you have any questions or comments about this advisory, you can contact:\n- The original reporters, by sending an email to vulnerability.research [at] sonarsource.com;\n- The maintainers, by opening an issue on this repository.\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 8.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2021-08-30T16:11:24", "type": "osv", "title": "Cachet vulnerable to new line injection during configuration edition", "bulletinFamily": "software", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "baseScore": 6.5, "vectorString": "AV:N/AC:L/Au:S/C:P/I:P/A:P", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "impactScore": 6.4, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-39172"], "modified": "2023-05-22T16:41:17", "id": "OSV:GHSA-9JXW-CFRH-JXQ6", "href": "https://osv.dev/vulnerability/GHSA-9jxw-cfrh-jxq6", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "github": [{"lastseen": "2023-11-28T16:13:55", "description": "### Impact\n\nAuthenticated users, regardless of their privileges (_User_ or _Admin_), can exploit a new line injection in the configuration edition feature (e.g. mail settings) and gain arbitrary code execution on the server.\n\n### Patches\n\nThis issue was addressed by improving `UpdateConfigCommandHandler` and preventing the use of new lines characters in new configuration values.\n\n### Workarounds\n\nOnly allow trusted source IP addresses to access to the administration dashboard.\n\n### References\n\n- https://blog.sonarsource.com/cachet-code-execution-via-laravel-configuration-injection\n\n### For more information\n\nIf you have any questions or comments about this advisory, you can contact:\n- The original reporters, by sending an email to vulnerability.research [at] sonarsource.com;\n- The maintainers, by opening an issue on this repository.\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 8.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2021-08-30T16:11:24", "type": "github", "title": "Cachet vulnerable to new line injection during configuration edition", "bulletinFamily": "software", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "baseScore": 6.5, "vectorString": "AV:N/AC:L/Au:S/C:P/I:P/A:P", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "impactScore": 6.4, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-39172"], "modified": "2023-05-22T16:23:34", "id": "GHSA-9JXW-CFRH-JXQ6", "href": "https://github.com/advisories/GHSA-9jxw-cfrh-jxq6", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}}], "githubexploit": [{"lastseen": "2023-11-28T18:51:58", "description": "# CVE-2021-39172\nCachet 2.4: Code Execution via Laravel C...", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 8.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2022-09-17T07:58:33", "type": "githubexploit", "title": "Exploit for CRLF Injection in Catchethq Catchet", "bulletinFamily": "exploit", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "baseScore": 6.5, "vectorString": "AV:N/AC:L/Au:S/C:P/I:P/A:P", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "impactScore": 6.4, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-39172"], "modified": "2023-11-25T10:04:49", "id": "AAB95082-FA5E-592D-A514-EB82DC0E4955", "href": "", "cvss": {"score": 6.5, "vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P"}, "privateArea": 1}], "sonarsource": [{"lastseen": "2021-12-30T09:01:30", "description": "\n\nStatus pages are now an essential service offered by all Software-as-a-Service companies ([we do it too](<https://sonarcloud.statuspage.io/>)!). To help their adoption, startups quickly conceived status pages as-a-service, and open-source self-hosted alternatives were made available. [Cachet](<https://github.com/cachethq/Cachet>), also sometimes referred to as CachetHQ, is a broadly adopted status page system written in PHP and has many community forks such as [fiveai/Cachet](<https://github.com/fiveai/Cachet>). \n\nCompromising Cachet instances is rewarding for attackers, as they store secrets for various services such as caches, databases, email servers, etc. This initial foothold in the infrastructure is helpful for them to pivot into the internal network of the affected company and to perform further attacks. In this article, we present the technical analysis of three security bugs we discovered in Cachet 2.4. They can enable attackers to compromise the server. \n\n## Impact\n\nThe exploitation of these vulnerabilities was verified on the last official release of Cachet at the time (2.3.18), as well as on the development branch (2.4). An attacker aspiring to exploit these vulnerabilities requires a valid user account with basic privileges, a scenario that can realistically be leveraged by:\n\n * Using credentials stuffing, thanks to the considerable amount of accounts leaked every year;\n * A compromised or malicious user;\n * The presence of a Cross-Site Scripting vulnerability on the same perimeter;\n * The exploitation of CVE-2021-39165, a pre-authenticated SQL injection in Cachet fixed in January 2021.\n\nThe first vulnerability (CVE-2021-39172) we describe is a newline injection that happens when users update an instance's configuration, such as the email settings. It allows attackers to inject new directives and to alter the behavior of core features, ultimately leading to the execution of arbitrary code.\n\nThe following video shows the exploitation of this vulnerability. For demonstration purposes, several steps are performed manually, but they could be automated by attackers:\n\nThe second one (CVE-2021-39174) is also related to this feature and allows the attacker to exfiltrate secrets that are stored in the configuration file, e.g. SMTP server password, the application encryption key, etc. \n\nFinally, the last bug (CVE-2021-39173) is much simpler and allows going through the setup process even if the instance is already fully configured. That way, attackers can trick the Cachet instance into using an arbitrary database under their control, ultimately leading to arbitrary code execution. \n\nPatches for these three vulnerabilities are available in [release 2.5.1](<https://github.com/fiveai/Cachet/releases/tag/v2.5.1>) of the FiveAI fork. \n\n## Technical Details\n\nIn this section, we describe the technical details of each vulnerability and the way they were mitigated in the latest release of the community fork.\n\n### CVE-2021-39172 - Remote Code Execution\n\nThe dashboard of Cachet exposes several configuration views (even to non-administrator users) to change the instance name, mail server settings, etc. Application-level persistent settings are saved in the database, and other framework-level values are directly saved in the application's configuration file. The Laravel framework uses _dotenv _configuration files, a format similar to how you would declare environment variables in a shell script, and their support is implemented in the third-party library [vlucas/phpdotenv](<https://github.com/vlucas/phpdotenv>). \n\nWhen changing the email provider settings, the controller instantiates an object of the class UpdateConfigCommand. Laravel Commands, in the context of the Command Bus, are a way to remove application-specific logic from controllers; they will be synchronously executed upon an execute() call on the object. This is what happens at [1]: \n\n**app/Http/Controllers/Dashboard/SettingsController.php**\n \n \n public function postMail()\n {\n \u00a0\u00a0\u00a0 $config = Binput::get('config');\n \u00a0\u00a0\u00a0 execute(new UpdateConfigCommand($config));\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 // [1]\n \u00a0\u00a0\u00a0 return cachet_redirect('dashboard.settings.mail')\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ->withInput(Binput::all())\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ->withSuccess(trans('dashboard.notifications.awesome'));\n }\n\nThe associated handler, UpdateConfigCommandHandler, is responsible for performing changes in the existing _dotenv_ file, by replacing existing entries with new ones.\n\nUpdateConfigCommandHandler can be triggered by code at two different locations:\n\n * SetupController@postStep3, the last step of the setup process. Once the instance is installed, this code path can\u2019t be reached anymore;\n * SettingsController@postMail, when updating the _dotenv_ entries related to email servers.\n\nIt will first evaluate the full configuration file to populate the process environment ([1]), identify if the directive to update is already defined ([2]) and then replaced the entry with its new value ([3]):\n\n**app/Bus/Handlers/Commands/System/Config/UpdateConfigCommandHandler.php**\n \n \n class UpdateConfigCommandHandler\n {\n \u00a0\u00a0\u00a0 // [...]\n \u00a0\u00a0\u00a0 public function handle(UpdateConfigCommand $command)\n \u00a0\u00a0\u00a0{\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach ($command->values as $setting => $value) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this->writeEnv($setting, $value);\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n \u00a0\u00a0\u00a0}\n \u00a0\u00a0\u00a0// [...]\n \u00a0\u00a0\u00a0protected function writeEnv($key, $value)\n \u00a0\u00a0\u00a0{\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $dir = app()->environmentPath();\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $file = app()->environmentFile();\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $path = \"{$dir}/{$file}\";\n \u00a0\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (new Dotenv($dir, $file))->load(); \u00a0 \u00a0 \u00a0 // [1]\u00a0\u00a0\u00a0\n \u00a0\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $envKey = strtoupper($key);\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $envValue = env($envKey) ?: 'null';\u00a0 \u00a0 \u00a0 // [2]\n \u00a0\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 file_put_contents($path, str_replace(\u00a0 \u00a0 // [3]\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"{$envKey}={$envValue}\",\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"{$envKey}={$value}\",\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 file_get_contents($path)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ));\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } catch (InvalidPathException $e) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throw $e;\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n \u00a0\u00a0\u00a0}\n }\n\nNo validation is performed on the incoming data: as long as the configuration entry already exists, it will be replaced with a value coming from the parameter. If an attacker provides a value containing new lines, it will create new entries in the _dotenv_ file and may alter framework-level functionalities. It is worth noting that only the first definition of a variable in a _dotenv_ file will be used, subsequent ones will be ignored. \n\nOn Laravel projects, this primitive is enough to gain arbitrary code execution. The initial _dotenv_ configuration file will probably look like this on most instances:\n\n**.env**\n \n \n APP_ENV=production\n [...]\n DEBUGBAR_ENABLED=false\n DB_DRIVER=sqlite\n [...]\n DB_PREFIX=\n CACHE_DRIVER=file\n SESSION_DRIVER=file\n QUEUE_DRIVER=array\n MAIL_DRIVER=smtp\n MAIL_HOST=foo\n [...]\n REDIS_HOST=null\n REDIS_DATABASE=null\n REDIS_PORT=null\n\nAttackers could replace the CACHE_DRIVER key and register a Redis server under their control as new session backend:\n \n \n file\\nREDIS_HOST=some.remote.server\\nREDIS_DATABASE=0\\nREDIS_PORT=6379\\nSESSION_DRIVER=redis\n\nAfter sending a request that sets CACHE_DRIVER to this value, the _dotenv_ file will look like this\n\n**.env**\n \n \n APP_ENV=production\n APP_DEBUG=false\n APP_URL=http://cachet.internal\n APP_TIMEZONE=UTC\n // [...]\n CACHE_DRIVER=file\n REDIS_HOST=some.remote.server\n REDIS_DATABASE=0\n REDIS_PORT=6379\n SESSION_DRIVER=redis\n SESSION_DRIVER=file\n QUEUE_DRIVER=null\n // [...]\n\nBecause Laravel sessions are serialized using PHP\u2019s native format, they are parsed with the function unserialize(). This is a known weakness that can be leveraged into the execution of arbitrary code by using a sequence of specially-crafted objects, a concept named \u201cpopchains\u201d. The tool [PHPGGC](<https://github.com/ambionics/phpggc>) can generate such chains for Laravel projects. \n\nOther ways to leverage command execution from a new line injection in a _dotenv_ file may exist, but we did not pursue more research in this direction. We are curious to know if you\u2019re aware of other techniques, though!\n\n### CVE-2021-39174 - Configuration Leak\n\nAs we described in the previous section, one can have direct read and write control over values stored in the _dotenv_ file. Writing to this file ultimately leads to arbitrary code execution, but can it also be taken advantage of the fact that values of this file are displayed in the interface?\n\nThe documentation of vlucas/phpdotenv describes that it supports [nested variables assignment](<https://github.com/vlucas/phpdotenv#nesting-variables>): when declaring a variable, you can reference a previously declared one with the syntax ${NAME}.\n\nThis feature is convenient: by referencing another variable in an entry of the _dotenv_ configuration file and displaying this entry in the interface, it reveals another's variable value. \n\nIt is already [widely](<https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/unix/http/laravel_token_unserialize_exec.rb>) [documented](<https://blog.truesec.com/2020/02/12/from-s3-bucket-to-laravel-unserialize-rce/>) that leaking APP_KEY leads to code execution if the session driver is set to cookie, and this primitive can also be used to leak DB_PASSWORD and MAIL_PASSWORD to perform further attacks. \n\n\n\n### CVE-2021-39173 - Forced Reinstall\n\nThe setup page cannot be accessed if the instance is already installed, as implemented in the middleware SetupAlreadyCompleted:\n\n**app/Http/Middleware/SetupAlreadyCompleted.php**\n \n \n class SetupAlreadyCompleted\n {\n \u00a0\u00a0\u00a0// [...]\n \u00a0\u00a0\u00a0public function handle(Request $request, Closure $next)\n \u00a0\u00a0\u00a0{\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($this->settings->get('app_name')) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return cachet_redirect('dashboard');\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } catch (ReadException $e) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 // not setup then!\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n \u00a0\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return $next($request);\n \u00a0\u00a0\u00a0}\n }\n\nThe check is solely based on the value of the setting app_name: if not defined or empty, the middleware will consider that the instance is installed. \n\nIn case you\u2019re wondering what else can evaluate to false, here is a quick primer on PHP\u2019s typing system during comparisons until PHP 8. Comparison can be performed using an equality check (==) or an identity check (===). Equality checks imply that the type of the operands is not accounted for and that strings can be cast to numbers beforehand. This behavior has been named \u201ctype juggling\u201d and has been exploited in various real-life vulnerabilities ([CVE-2017-1001000](<https://nvd.nist.gov/vuln/detail/CVE-2017-1001000>), [CVE-2019-10231](<https://nvd.nist.gov/vuln/detail/CVE-2019-10231>)). In the case of the comparison above, any value equal to an empty string or 0 will evaluate to false and give access to the setup pages.\n\nThe value of app_name is not validated during settings\u2019 update in SettingsController@postSettings, at [1]:\n\n**app/Http/Controllers/Dashboard/SettingsController.php**\n \n \n class SettingsController extends Controller\n {\n \u00a0\u00a0\u00a0// [...]\n \u00a0\u00a0\u00a0public function postSettings()\n \u00a0\u00a0\u00a0{\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $setting = app(Repository::class);\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 // [...]\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $parameters = Binput::all();\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 // [...]\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $excludedParams = [\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 '_token',\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'app_banner',\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'remove_banner',\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'header',\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'footer',\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'stylesheet',\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ];\n \u00a0\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach (Binput::except($excludedParams) as $settingName => $settingValue) {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($settingName === 'app_analytics_pi_url') {\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0 \u00a0 $settingValue = rtrim($settingValue, '/');\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $setting->set($settingName, $settingValue); // <-- [1]\n // [...]\n\nTherefore, an authenticated user can update it to a value evaluating to false and then access /setup again to re-install the instance with a new administrator account (elevation of privileges) or to exploit our first finding and gain code execution (remember, UpdateConfigCommandHandler can also be exploited from this code path!).\n\n### Patch\n\nThe new line injection vulnerability (CVE-2021-39172) was addressed by improving the validation of incoming values in UpdateConfigCommandHandler, [rejecting any modification containing newline characters](<https://github.com/fiveai/Cachet/commit/6442976c25930cb370c65a22784b9caee7ed1de2#diff-eb49382226800036f840983b448fee50b5167e6ccba0a08a7d95e3f8a3288d44R105-R106>). \n\nThe configuration leak bug (CVE-2021-39174) was more complex to patch, as the latest version of the _dotenv_ library could not be imported due to the existing dependencies. Instead, [relevant code was ported](<https://github.com/fiveai/Cachet/commit/6442976c25930cb370c65a22784b9caee7ed1de2#diff-eb49382226800036f840983b448fee50b5167e6ccba0a08a7d95e3f8a3288d44R75-R92>) to allow the command handler to identify if a value contains a nested variable. \n\nFinally, it is not possible to force a re-installation of existing instances (CVE-2021-39173) [thanks to improved checks in the impacted middleware](<https://github.com/fiveai/Cachet/commit/ee7781e63f43d3bb3db56b74794c440fba2255ef>).\n\n## Timeline\n\n<table class="table table-striped"><thead><tr><th>Date</th><th>Action</th></tr></thead><tbody><tr><td nowrap>2021-03-26</td><td>Issues reported by email to the official security disclosure address of the upstream project</td></tr><tr><td nowrap>2021-06-25</td><td>We send the security issues and patches to the community-supported fork (fiveai/Cachet)</td></tr><tr><td nowrap>2021-08-27</td><td>Release 2.5.1 of the FiveAI fork is published, with fixes for CVE-2021-39172, CVE-2021-39173, and CVE-2021-39174.</td></tr></tbody></table>\n\n## Summary\n\nIn this article, we analyzed three vulnerabilities in Cachet and demonstrated the ability to take over instances with only basic user permissions using Laravel configuration files. We also described the patches applied by the maintainers and how they prevent the attacks we presented. \n\nFinally, we would like to thank the maintainers of the FiveAI fork of Cachet for acknowledging our advisory and fixing these vulnerabilities in a timely and professional manner.\n\n## Related Blog Posts\n\n * [WordPress File Delete to Code Execution](<https://blog.sonarsource.com/wordpress-file-delete-to-code-execution>)", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 9.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2021-09-21T00:00:00", "type": "sonarsource", "title": "Cachet 2.4: Code Execution via Laravel Configuration Injection", "bulletinFamily": "blog", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "baseScore": 7.5, "vectorString": "AV:N/AC:L/Au:N/C:P/I:P/A:P", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 6.4, "obtainUserPrivilege": false}, "cvelist": ["CVE-2017-1001000", "CVE-2019-10231", "CVE-2021-39165", "CVE-2021-39172", "CVE-2021-39173", "CVE-2021-39174"], "modified": "2021-09-21T00:00:00", "id": "SONARSOURCE:F5F06080F1D214075031C0B15519A0AE", "href": "https://blog.sonarsource.com/cachet-code-execution-via-laravel-configuration-injection", "cvss": {"score": 7.5, "vector": "AV:N/AC:L/Au:N/C:P/I:P/A:P"}}]}