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) | decoder | rule, level | alert |
|---|---|---|---|
PHP-FPM log: child 12345 exited on signal 11 (SIGSEGV) | none | none | no |
Apache error log, mod_php: PHP Fatal error: Allowed memory size … exhausted with [client 203.0.113.7] | apache-errorlog | 30301, 0 | no |
nginx error log, PHP-FPM: FastCGI sent in stderr: "PHP message: PHP Fatal error: Allowed memory size …" | nginx-errorlog | 31420, 5 | low |
kernel: php-fpm8.3[5678]: segfault at 10 … | kernel | 1010, 5 | low |
Apache: AH00052: child pid 5678 exit signal Segmentation fault (11) (control) | apache-errorlog | 30304, 12 | yes |
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
| input | rule, level | fields |
|---|---|---|
PHP-FPM worker SIGSEGV, 1st and 2nd | 100901, 10 | fpm_pool=www, fpm_child_pid, signame=SIGSEGV |
PHP-FPM worker SIGSEGV, 3rd within 5 min | 100902, 12 | same |
PHP-FPM child started (noise) | 100900, 0 | no alert |
kernel php-fpm8.3[…]: segfault | 100903, 10 | raised from 5 |
kernel nginx[…]: segfault (control) | 1010, 5 | unchanged |
| Apache out-of-memory fatal, 1st to 4th from one client | 100904, 7 | srcip=203.0.113.7 |
| Apache out-of-memory fatal, 5th within 2 min | 100905, 12 | srcip=203.0.113.7 |
| nginx/PHP-FPM out-of-memory fatal, 1st to 4th | 100906, 7 | srcip=198.51.100.9 |
| nginx/PHP-FPM out-of-memory fatal, 5th within 2 min | 100907, 12 | srcip=198.51.100.9 |
| nginx/PHP-FPM other fatal (undefined function, control) | 31421, 5 | unchanged |
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.