Skip to main content
NewsPublished 10/24/2026

I spun up a free, read-only script to check WordPress sites for signs of PHP2Shell compromise. Looking for feedback

Source Reddit BlueTeam

0

Mentions 3 CVEs : update to 8.2.35

Mentioned vulnerabilities

Discussion

This content describes a free, read-only bash script designed to triage WordPress sites for signs of compromise related to the PHP2Shell vulnerabilities (CVE-2026-109618, CVE-2026-109619) and a third CVE-2026-115560. The script checks PHP versions, WordPress core and plugin integrity, suspicious PHP files in uploads, recent file modifications, common web-shell patterns, user accounts, cron jobs, logs, Docker containers, and configuration settings relevant to the vulnerabilities. It generates detailed Markdown reports without modifying the target systems. The PHP2Shell vulnerabilities are critical remote code execution bugs patched in PHP releases 8.2.35, 8.3.36, 8.4.27, and 8.5.12, but the third CVE has no fixed build yet, with a recommended mitigation of setting session.upload_progress.enabled=0. The script helps detect potential backdoors planted before patching, as updating PHP alone does not remove them.

r/blueteamsec (opens in a new tab)u/82miles0 points0 comments

Patching PHP fixes PHP2Shell (CVE-2026-109618 / 109619), but it does nothing about a backdoor someone planted before the patch. Amazon's honeypots caught an exploitation attempt on Oct 17, four days before disclosure, and Amazon's advice is to investigate from at least that date.

So I used Claude Code to spin up a bash script to triage WordPress sites. It checks:

* PHP CLI version vs. the fixed releases

* Core and plugin checksums (via WP-CLI)

* PHP files in uploads

* Files modified since Oct 17 (adjustable)

* auto_prepend_file hooks in .user.ini / .htaccess / php.ini

* mu-plugins

* Common web-shell patterns in wp-content

* Admin accounts and any users created in the window

* Injected scripts in options and posts

* WP-Cron, the site user's crontab, and SSH authorized_keys

It's read-only and never modifies or deletes anything. It runs WP-CLI with --skip-plugins --skip-themes so a backdoored plugin can't execute during the check. It works on one site, every site on a server, or a list of remote servers over SSH, and it writes a Markdown report per site plus a summary.

Repo (MIT): https://github.com/brentmartinmiller/php2shell-check

Caveats: a clean report lowers the odds of compromise but doesn't prove a site is clean. It doesn't parse web server logs, so pull those separately before rotation eats the Oct 17+ window. A few false positives are expected, like Wordfence's prepend file, header-script plugins, and obfuscated premium plugins. The README covers how to read them.

I'd appreciate feedback, especially false positives you hit, indicators I'm missing, or quirks on shared hosts. Issues and PRs welcome.

**************

UPDATES:
5xx in the access logs. Added as a new section. It finds the access, error and FPM logs next to the site, under the home directory or under /var/log, including rotated .gz files, and counts requests and 5xx per day for the window against up to seven days before it. It also lists the URLs that returned 5xx inside the window, so the "random URLs" pattern is visible at a glance, and greps the error and FPM logs for segfault and bus-error lines. Your baseline point is baked into the verdict: a window with 5xx only gets a review flag when there is no baseline or it runs clearly above it. On the first real host I ran it against there was a full seven-day baseline and a flat zero across the window. There's a LOGS= variable for logs that live somewhere unusual.

The l10n.php false positive. Those files are now counted separately instead of flooding the list. I was careful about the exclusion: a file only counts as a translation pack if it has exactly the shape WordPress writes, which is <?php followed by a single return [...] statement whose non-string content is nothing but brackets, arrows, commas and integer keys. I tested it against a few planted variants, including code hidden inside the array expression, and all of them stay in the main list and get flagged. So the exclusion can't be used as a hiding place.

Docker. Two things. On the host, the report now lists every running container that has a php binary, the version inside it graded against the fixed releases, and whether the container still runs an older build than the image on disk. That last one is your three-days-on-8.3.35 case: pulled, but never recreated. Separately, you can list docker:container:path as a target and the whole check runs inside the container via docker exec, nothing installed. The one catch is that Alpine images don't ship bash, which the README now says.

And the third CVE. CVE-2026-115560 went out on the 23rd with no fixed build, so I added a check for the session.upload_progress.enabled=0 mitigation php.net asked for. It reads PHP-FPM's own view and every readable php.ini, pool and Apache config, and reports but doesn't credit .user.ini or .htaccess, since php.net says those are too late to help. It's graded as review rather than a likely problem, because the vector needs app code that switches the session serializer at runtime and WordPress never does that.

Pull requests welcome.

Impact

The PHP2Shell vulnerabilities allow remote code execution on affected PHP versions, enabling attackers to execute arbitrary code on vulnerable WordPress sites. Exploitation attempts were detected before public disclosure, indicating active threat activity. Even after patching PHP, previously compromised sites may retain backdoors or malicious artifacts that allow continued unauthorized access. The third CVE (2026-115560) currently lacks a patch, increasing risk until mitigated by configuration changes. The impact includes potential full site compromise, data manipulation, and persistence of attacker access.

Defensive guidance

Official patches are available for CVE-2026-109618 and CVE-2026-109619 in PHP versions 8.2.35, 8.3.36, 8.4.27, and 8.5.12; updating to these or later versions closes the vulnerabilities. For CVE-2026-115560, no fixed PHP build exists yet; php.net recommends setting session.upload_progress.enabled=0 in php.ini or PHP-FPM pool configurations as a temporary mitigation. The provided script can be used to detect signs of compromise and backdoors left by attackers prior to patching. It is read-only and does not modify systems. Defenders should investigate findings from the script and perform appropriate incident response. The script’s README and documentation provide guidance on interpreting results and known false positives. Regularly updating PHP and monitoring for suspicious activity remain important.

Summary

The PHP2Shell vulnerabilities (CVE-2026-109618 and CVE-2026-109619) are critical remote code execution flaws in the PHP engine disclosed on October 21, 2026, with patches available in PHP 8.2.35, 8.3.36, 8.4.27, and 8.5.12. Exploitation attempts were observed at least as early as October 17, 2026, before public disclosure. Sites running unpatched PHP during this window may have been compromised with backdoors that remain after patching. A third related vulnerability, CVE-2026-115560, was disclosed on October 23, 2026, with no fixed build yet; mitigation involves disabling session.upload_progress.enabled in php.ini or PHP-FPM pool configurations. The provided script performs a comprehensive, read-only triage of WordPress sites to detect indicators of compromise such as unauthorized PHP files, modified files, suspicious hooks, unusual user accounts, injected scripts, cron jobs, and Docker container PHP versions. It runs WP-CLI with plugins and themes disabled to avoid interference from backdoored code. The script produces detailed reports to assist defenders in investigating potential compromises.

References

Community reviews

Loading reviews…