Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Tools/GitHubGitHub/brentmartinmiller/php2shell-check
Defensive ToolsVulnerability AnalysisScripting & AutomationConfiguration AuditingWeb SecurityMalware AnalysisDigital ForensicsIncident ResponseLog Analysis

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
GitHubbrentmartinmiller/php2shell-check

php2shell-check

Read-only triage script for WordPress sites after PHP2Shell (CVE-2026-109618, CVE-2026-109619). Checks for signs of compromise and writes a report per site.

View Repository
31212 days agoNot yet reviewed
Share

php2shell-check

A read-only triage script for WordPress sites after PHP2Shell (CVE-2026-109618 and CVE-2026-109619), the pair of critical remote code execution bugs in the PHP engine disclosed on October 21, 2026.

Patching PHP closes the door, but Amazon's honeypots logged an exploitation attempt on October 17, four days before the public disclosure, while the bugs were still under embargo. That is the earliest activity anyone has published, not the day attacks began, so treat it as a floor. Any site that was reachable on an unpatched PHP during that window may already have a backdoor, and updating PHP won't remove it. This script checks one or many WordPress sites for the things an attacker with code execution typically leaves behind, and writes a Markdown report for each.

A third bug, CVE-2026-115560, was announced on October 23. It has no fixed build yet: the October point releases (8.2.35, 8.3.36, 8.4.27, 8.5.12) do not cover it, and the fix is due with the next regular release in November. php.net asks everyone to set session.upload_progress.enabled=0 in php.ini or the PHP-FPM pool until then. The script checks whether that has been done.

It never modifies or deletes anything. It lists, verifies and reports. What to do with the findings is up to you.

What it checks

AreaCheck
PHPInstalled CLI version vs. the fixed releases (8.2.35, 8.3.36, 8.4.27, 8.5.12). Flags end-of-life branches, which got no release from php.net; see Older PHP branches.
Upload progressWhether session.upload_progress.enabled=0, the CVE-2026-115560 mitigation, is set where it counts: PHP-FPM's own view (php-fpm -i), every readable php.ini, conf.d, FPM pool and Apache config. Site-level .user.ini and .htaccess are reported but not credited, because php.net says they don't work for this setting.
Core integritywp core verify-checksums against wordpress.org
Plugin integritywp plugin verify-checksums --all, and lists premium/custom plugins it can't verify
UploadsAny PHP-executable file under wp-content/uploads (ignores "Silence is golden" stubs)
Recent changesPHP and config files modified since the window start (default 2026-10-17). WordPress translation packs (wp-content/languages/**/*.l10n.php) are counted separately once they pass a strict shape test; one that fails it is flagged.
Prepend hooksauto_prepend_file / auto_append_file in .user.ini, .htaccess, php.ini
Must-use pluginsContents of wp-content/mu-plugins (runs on every request, hidden from the normal plugin list)
Code patternsClassic web-shell signatures (eval(base64_decode(...)), $_POST[...](), etc.) in wp-content
UsersAll administrators, and any account registered inside the window
Databasesiteurl/home, options and posts containing injected scripts or obfuscated code
CronWP-Cron scheduled events
LogsAccess logs: 5xx responses per day for the window vs. a baseline of up to 7 days before it, plus the URLs returning 5xx in the window. Error and PHP-FPM logs: worker crashes (segfault/bus error).
ServerThe site user's crontab and SSH authorized_keys
DockerEvery running container with a php binary: the PHP version inside it, and whether the container still runs an older build than the image on disk (pulled but not recreated)

WP-CLI is run with --skip-plugins --skip-themes so a backdoored plugin or theme can't execute while the check runs.

Requirements

On each machine being checked:

  • bash 3.2+, find, grep and sort -V (standard on Linux hosts; also works from a stock macOS workstation)
  • WP-CLI for the checksum, user and database checks. Without it the file-system checks still run and the report says what was skipped.
  • php on the path, for the version check

For remote sites: SSH key access from the machine you run the script on. The script runs itself over SSH; nothing needs to be installed on the remote host beyond the above.

Usage

On the server itself

curl -O https://raw.githubusercontent.com/brentmartinmiller/php2shell-check/main/php2shell-check.sh
chmod +x php2shell-check.sh

# One site
./php2shell-check.sh /var/www/example.com
less php2shell-reports/*.md

# Every site on the box
printf '%s\n' /var/www/*/public_html > sites.txt
./php2shell-check.sh sites.txt
cat php2shell-reports/SUMMARY.md

Run it as the user that owns the site files where you can. It works as root (WP-CLI gets --allow-root), but the crontab and SSH-key checks then inspect root's instead of the web user's.

From your workstation, against many servers

git clone https://github.com/brentmartinmiller/php2shell-check.git
cd php2shell-check
cp sites.txt.example sites.txt   # edit: one site per line
./php2shell-check.sh sites.txt

For each user@host:path entry the script SSHes in, runs itself there, and brings the report back to php2shell-reports/ on your machine. Nothing is installed on the remote host. SSH runs with BatchMode=yes, so key-based access that works without a password prompt is required.

Shared hosting

Most shared hosts (Hostinger, SiteGround, Bluehost and the like) offer SSH but often don't have wp on the path. Check with which wp. If it's missing, download WP-CLI once into your home directory and point the script at it:

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
WP="php $HOME/wp-cli.phar" ./php2shell-check.sh domains/example.com/public_html

Without WP-CLI the file-system checks still run and the report notes what was skipped. Either way, ask the host directly when they rolled out the patched PHP, since that's the one thing an account-level check can't see.

Site list format

sites.txt has one site per line, either a local path or user@host:path. Relative remote paths are relative to the SSH user's home directory. Lines starting with # are ignored. See sites.txt.example. The file is in .gitignore so client hostnames don't end up in a commit.

Non-standard SSH ports, keys and jump hosts belong in ~/.ssh/config:

Host client-a
    HostName 203.0.113.10
    Port 2222
    User deploy
    IdentityFile ~/.ssh/client-a

Then list the site as client-a:/var/www/html.

Docker

php -v on a Docker host tells you nothing about the containers, and pulling a fixed image patches nothing until the container is recreated from it. One team's site sat on 8.3.35 for three days after the pull for exactly that reason.

When the script runs on a host where docker ps works, the report gets a Docker containers section listing every running container that has a php binary, the PHP version inside it, and whether the container is stale (a newer build of its image is on disk but the container was never recreated). Recreate with docker compose up -d, or stop, remove and run the container again.

To run the full check inside a container, list it as a target:

docker:wordpress-php-1:/var/www/html

The script is piped into docker exec and runs there; nothing is installed in the container. It needs bash inside the container. The official php:* and wordpress:* Debian-based images have it; Alpine-based ones (-alpine) don't, so either docker exec NAME apk add bash first or settle for docker exec NAME php -v. The database is usually in a separate container, so the user, options and cron checks are skipped unless the PHP container can reach it.

Options

Set these as environment variables:

Download Tool