JustAppSec
Back to news

OpenCATS installer writes attacker PHP into config, enabling unauthenticated RCE

2 min readPublished 28 Apr 2026Updated 28 Apr 2026Source: CVEProject (cvelistV5)

TL;DR - OpenCATS deployments with an active installer (INSTALL_BLOCK absent) are exposed to unauthenticated RCE. An attacker hits the installer databaseConnectivity AJAX route, injects PHP into config.php via a define() breakout, and that code runs on every subsequent page load. CVSS 9.2. Fixed in commit 3002a29.

What happened

OpenCATS is a PHP applicant tracking system. During installation it accepts database connection settings through an installer AJAX route and writes them directly into config.php.

CVE-2026-27760 (CWE-94) is a code injection in that flow. The databaseConnectivity handler passes raw $_REQUEST values to CATSUtility::changeConfigSetting(), which writes them into a define(...) call in config.php without safe escaping. An attacker breaks out of the quoted string - for example by injecting '); ... // - and appends arbitrary PHP. Because config.php is globally included on every request, that payload executes persistently with no further interaction required.

The gate is installer state. The vulnerable route is only reachable when INSTALL_BLOCK is absent, meaning the installation wizard was never completed. This is the classic forgotten-installer failure mode, except here the installer writes code directly into a file the application always loads. The persistence makes it worse than a typical SSRF or file-read: one successful request leaves a backdoor that survives restarts.

Commit 3002a29 (PR #706) addresses both the root cause and the persistence vector. It restricts ajax.php behaviour when INSTALL_BLOCK is missing, and it changes how installer values are written to config.php, using safer serialisation (for example var_export(...)) instead of raw string interpolation.

Who is impacted

  • OpenCATS versions <= 0.9.7.4, or any build prior to commit 3002a29.
  • Deployments where INSTALL_BLOCK is absent and the installation wizard was never completed.
  • Any internet-reachable instance where an attacker can reach /ajax.php?f=install:ui&a=databaseConnectivity.
ItemDetail
Affected componentInstaller AJAX databaseConnectivity flow writing to config.php
Affected versions<= 0.9.7.4 / prior to commit 3002a29
Fixed incommit 3002a29 (PR #706)
SeverityCVSS v4.0 9.2 (Critical)

What to do now

  • Update to a build that includes commit 3002a29 (PR #706) as soon as possible.
  • Check installer exposure before patching. Probe GET /ajax.php?f=install:ui&a=databaseConnectivity: a response containing setActiveStep means the installer is active and you are vulnerable; installLocked means it is closed.
  • Audit config.php for injected PHP - inspect every define(...) line for unexpected content or breakout patterns. Do this even if you patch, because a prior compromise may have already written a payload.
  • If you suspect past exploitation:
    • Rotate database credentials and any other secrets reachable from the OpenCATS host or process.
    • Treat config.php as a persistence point and restore it from a known-good copy after patching.
  • While patching is in progress, block network access to the installer AJAX route at your edge - at minimum prevent untrusted networks from reaching it.

Related


Content is AI-assisted and reviewed by our team, but issues may be missed and best practices evolve rapidly, send corrections to [email protected]. Always consult official documentation and validate key implementation decisions before making design or security choices.

Need help?Get in touch.