Wazuh fix note · PHP2Shell · stock ruleset gap

PHP2Shell: stock Wazuh does not alert on PHP-FPM crashes or out-of-memory floods

PHP2Shell (CVE-2026-109618, CVE-2026-109619) names two memory-safety flaws in PHP core, patched on 21 October 2026: one in out-of-memory handling, one a use-after-free between requests. On Wazuh 4.14.9, a PHP-FPM worker that dies on SIGSEGV is not decoded at all, and a burst of PHP out-of-memory fatals from one client stays at level 0 (Apache) or 5 (nginx). One decoder and eight rules close both; measured below on a real manager.

Dong Nguyen, ATK New Technology · 23 October 2026 · measured on wazuh-manager 4.14.9 (logtest) · advisories: CISA, Rapid7


Patch first. Fixed releases are 8.2.35, 8.3.36, 8.4.27 and 8.5.12; 8.1 and older have no upstream fix. Crash and out-of-memory events are signals, not proof of exploitation, and their absence does not prove a server is safe. These rules tell you where to look while you patch.

What the stock 4.14.9 ruleset does with these lines

log line (source)decoderrule, levelalert
PHP-FPM log: child 12345 exited on signal 11 (SIGSEGV)nonenoneno
Apache error log, mod_php: PHP Fatal error: Allowed memory size … exhausted with [client 203.0.113.7]apache-errorlog30301, 0no
nginx error log, PHP-FPM: FastCGI sent in stderr: "PHP message: PHP Fatal error: Allowed memory size …"nginx-errorlog31420, 5low
kernel: php-fpm8.3[5678]: segfault at 10 …kernel1010, 5low
Apache: AH00052: child pid 5678 exit signal Segmentation fault (11) (control)apache-errorlog30304, 12yes

Apache with mod_php is covered: its segfault line already alerts at level 12. PHP-FPM, the most common way PHP is served behind nginx, is the gap. Its master log is not decoded, and one client sending many requests that each end in an out-of-memory fatal looks the same as one bad script.

Fix: one decoder, eight rules

1. Ship the PHP-FPM master log. In the agent's ossec.conf (path depends on distribution: Debian/Ubuntu /var/log/php8.3-fpm.log, RHEL family /var/log/php-fpm/error.log):

<localfile>
  <log_format>syslog</log_format>
  <location>/var/log/php8.3-fpm.log</location>
</localfile>

2. Add to /var/ossec/etc/decoders/local_decoder.xml:

<!-- ATK · PHP2Shell signals (CVE-2026-109618 / CVE-2026-109619) · decoder for PHP-FPM master log lines -->
<decoder name="php-fpm">
  <prematch>^[\d\d-\w\w\w-\d\d\d\d \d\d:\d\d:\d\d] \w+: [pool </prematch>
</decoder>

<decoder name="php-fpm-child-signal">
  <parent>php-fpm</parent>
  <regex>[pool (\S+)] child (\d+) exited on signal (\d+) \((\w+)\)</regex>
  <order>fpm_pool,fpm_child_pid,signal,signame</order>
</decoder>

3. Add as /var/ossec/etc/rules/0900-local-php2shell.xml. The parents live in 0020-syslog_rules.xml (1010), 0250-apache_rules.xml (30301) and 0265-php_rules.xml (31420), so the file name must sort after all three; 0900- does.

<!-- ATK · PHP2Shell signals (CVE-2026-109618 / CVE-2026-109619)
     Crash and out-of-memory signals that stock Wazuh 4.14.9 does not alert on.
     These are SIGNALS, not proof of exploitation. Patching PHP is the only complete fix. -->
<group name="php,php2shell,">

  <rule id="100900" level="0">
    <decoded_as>php-fpm</decoded_as>
    <description>PHP-FPM messages grouped.</description>
  </rule>

  <rule id="100901" level="10">
    <if_sid>100900</if_sid>
    <field name="signame" type="pcre2">^SIG(SEGV|BUS|ABRT|ILL)$</field>
    <description>PHP-FPM worker $(fpm_child_pid) in pool $(fpm_pool) crashed with $(signame). Memory-corruption signal; check PHP version against CVE-2026-109618/109619.</description>
    <mitre><id>T1190</id></mitre>
  </rule>

  <rule id="100902" level="12" frequency="3" timeframe="300">
    <if_matched_sid>100901</if_matched_sid>
    <description>Repeated PHP-FPM worker crashes (3 in 5 minutes). Possible PHP2Shell exploitation attempts.</description>
    <mitre><id>T1190</id></mitre>
  </rule>

  <rule id="100903" level="10">
    <if_sid>1010</if_sid>
    <match type="pcre2">\bphp[\w.-]*\[\d+\]: segfault at</match>
    <description>Kernel: PHP process segfaulted. Raised from level 5; check PHP version against CVE-2026-109618/109619.</description>
    <mitre><id>T1190</id></mitre>
  </rule>

  <rule id="100904" level="7">
    <if_sid>30301</if_sid>
    <match>Allowed memory size of</match>
    <description>Apache: PHP out-of-memory fatal error for client $(srcip).</description>
  </rule>

  <rule id="100905" level="12" frequency="5" timeframe="120">
    <if_matched_sid>100904</if_matched_sid>
    <same_source_ip />
    <description>5 PHP out-of-memory fatals from $(srcip) in 2 minutes. Possible CVE-2026-109618 trigger attempts.</description>
    <mitre><id>T1190</id></mitre>
  </rule>

  <rule id="100906" level="7">
    <if_sid>31420</if_sid>
    <match>Allowed memory size of</match>
    <description>Nginx/PHP-FPM: PHP out-of-memory fatal error for client $(srcip).</description>
  </rule>

  <rule id="100907" level="12" frequency="5" timeframe="120">
    <if_matched_sid>100906</if_matched_sid>
    <same_source_ip />
    <description>5 PHP-FPM out-of-memory fatals from $(srcip) in 2 minutes. Possible CVE-2026-109618 trigger attempts.</description>
    <mitre><id>T1190</id></mitre>
  </rule>

</group>

With the fix, same lines

inputrule, levelfields
PHP-FPM worker SIGSEGV, 1st and 2nd100901, 10fpm_pool=www, fpm_child_pid, signame=SIGSEGV
PHP-FPM worker SIGSEGV, 3rd within 5 min100902, 12same
PHP-FPM child started (noise)100900, 0no alert
kernel php-fpm8.3[…]: segfault100903, 10raised from 5
kernel nginx[…]: segfault (control)1010, 5unchanged
Apache out-of-memory fatal, 1st to 4th from one client100904, 7srcip=203.0.113.7
Apache out-of-memory fatal, 5th within 2 min100905, 12srcip=203.0.113.7
nginx/PHP-FPM out-of-memory fatal, 1st to 4th100906, 7srcip=198.51.100.9
nginx/PHP-FPM out-of-memory fatal, 5th within 2 min100907, 12srcip=198.51.100.9
nginx/PHP-FPM other fatal (undefined function, control)31421, 5unchanged

No load warnings, every rule fired, controls unchanged. Thresholds (3 crashes in 5 minutes, 5 out-of-memory fatals in 2 minutes from one address) are starting points: a busy pool with a known leaky script will need its own baseline.

Scope. Measured with the manager's logtest engine on 4.14.9, sample lines in each server's default format, frequency rules fed in one session. We did not run a PHP2Shell exploit; public proofs of concept are reported to work only on narrow OS, PHP and web-server combinations, and an exploit that succeeds may leave no crash at all. Out-of-memory fatals also come from ordinary bugs; the per-client threshold is what separates a flood from a leak.

Let your AI agent check the PHP side

Our MCP server has a free check_php2shell tool. The agent runs php -v, php-fpm -i, cat /etc/os-release and dpkg -l 'php*' (or rpm -qa 'php*') on the server, pastes the output, and gets back patched, vulnerable or check_vendor_backport, the changelog command that decides distribution builds (Ubuntu and RHEL backport fixes without changing the upstream number), upgrade commands, and config mitigations until patched. Nothing is fetched from your servers. Add https://atkvn.com/agent/mcp, or call it directly:

{ php -v; php -i | grep -E 'Server API|memory_limit|upload_progress|fatal_error_backtraces';
  cat /etc/os-release; dpkg -l 'php*' 2>/dev/null | grep ^ii; rpm -qa 'php*' 2>/dev/null; } \
| python3 -c 'import json,sys; print(json.dumps({"evidence": sys.stdin.read()}))' \
| curl -s https://atkvn.com/agent/v1/php2shell -H 'content-type: application/json' -d @-

The rules above can be run against your own lines on a real 4.14.9 manager with test_wazuh_rule on the same server. How to connect.