
wp2shell-Hestia-Scanner — Updated!
Read-only WordPress security scanner for HestiaCP servers. Detects wp2shell compromise indicators (CVE-2026-63030 / CVE-2026-60137) across all hosted sites — per-user email reports, core file diff against clean WordPress, PHP/JS/htaccess/image analysis, and optional AI evaluation via Claude API.
🛡️ wp2shell-Hestia-Scanner
Read-only WordPress security scanner for HestiaCP servers.
Detects wp2shell compromise indicators across all hosted sites — with per-client email reports, core file diff, SHA256 webshell detection, risk scoring, and optional AI evaluation.
⚠️ Safe versions: WordPress 6.8.6 / 6.9.5 / 7.0.2 or newer.
These scripts never modify anything — read-only throughout.
🇬🇧 English
What is wp2shell?
wp2shell is a pre-authentication remote code execution (RCE) chain in WordPress core, disclosed on 17 July 2026. A single anonymous HTTP request against a default installation is enough to create a rogue administrator and execute arbitrary code on the server.
The chain combines:
- CVE-2026-60137 — SQL injection in the
author__not_inparameter ofWP_Query - CVE-2026-63030 — Route confusion in the REST API
/wp-json/batch/v1endpoint
Compromised sites show a rogue admin with login prefix wp2_ and email @wp2shell.invalid.
More information: https://wp2shell.com
Repository contents
| File | Purpose |
|---|---|
wp2shell-scan.sh | Fast server-wide IoC scanner — colour-coded terminal output, risk score per site, auto-saved report to /root/ |
wp2shell-report-per-user.sh | Full scanner — per-HestiaCP-user email reports, core file diff, SHA256 webshell detection, AI evaluation, risk scoring |
known_shells.sha256 | Known webshell hash database (SHA256) — fetched automatically at runtime |
What the scanner checks
Database / User checks
| Check | Severity |
|---|---|
| WordPress version vs. safe versions | HIGH / OK |
Accounts with wp2_ prefix or @wp2shell.invalid email | CRITICAL |
| Administrators created after disclosure (15/07/2026) | MEDIUM |
| Gaps in user-ID sequence (deleted rogue admin traces) | MEDIUM |
Orphaned wp_usermeta rows | MEDIUM |
Poisoned oembed_cache / customize_changeset rows | CRITICAL |
Tampered WP options (upload_path, auto_prepend_file, siteurl) | CRITICAL / HIGH |
Core file integrity
| Check | Severity |
|---|---|
wp core verify-checksums vs. wp.org | HIGH |
Line-by-line diff -U5 against clean downloaded core | CRITICAL / HIGH / OK |
| Extra files not present in clean core (content + metadata shown) | CRITICAL / HIGH |
File analysis
| Check | Severity |
|---|---|
PHP in uploads/ | CRITICAL |
Extra PHP extensions (.php7 .phtml .phar .php5) | HIGH |
| SHA256 match against known webshell database (WSO, FilesMan, b374k, p0wny…) | CRITICAL |
PHP modified after SINCE_DATE AND matching suspicious patterns — with matching line shown inline | CRITICAL / HIGH |
| PHP with suspicious patterns but NOT recently modified | LOW |
JS/HTML modified after SINCE_DATE AND matching obfuscation patterns | MEDIUM |
| External C2/exfiltration URLs (pastebin, ngrok, Discord webhooks, bit.ly…) | CRITICAL |
.htaccess dangerous directives (AddType, auto_prepend_file, external RewriteRule) | HIGH |
.htaccess modified after SINCE_DATE | MEDIUM |
Polyglot images with PHP payload (<?php in .jpg/.png…) | CRITICAL |
Exposed backup/config files (wp-config.php.bak, *.sql…) | MEDIUM |
Persistence
| Check | Severity |
|---|---|
User crontab entries with curl/wget/php/base64 | HIGH |
| System cron files referencing the site path | MEDIUM |
Risk Score
Each site receives a 0–100 risk score with a breakdown of every contributing finding:
+------------------------------------------+
| RISK SCORE: 96/100 COMPROMISED |
+------------------------------------------+
+40 wp2shell fingerprint account
+30 PHP file(s) inside uploads/
+20 Vulnerable WordPress version
+6 Core checksum failure
| Score | Label |
|---|---|
| 0–20 | Probably Clean |
| 21–40 | Low Risk |
| 41–60 | Medium Risk |
| 61–80 | High Risk |
| 81+ | COMPROMISED |
Requirements
- Linux server running HestiaCP
- bash 4.0+
- WP-CLI installed globally as
wp rootaccesssendmail(for email reports)python3(for AI evaluation JSON handling)curl,sha256sum,file,strings,unzip
Install WP-CLI (if missing)
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar && sudo mv wp-cli.phar /usr/local/bin/wp
One-liner install & run
Fast IoC scan
curl -fsSL https://raw.githubusercontent.com/BytesPulse-OE/wp2shell-Hestia-Scanner/main/wp2shell-scan.sh | sudo bash
Full scan with per-client email reports
curl -fsSL https://raw.githubusercontent.com/BytesPulse-OE/wp2shell-Hestia-Scanner/main/wp2shell-report-per-user.sh \
-o wp2shell-report-per-user.sh && sudo bash wp2shell-report-per-user.sh
Note: The full scanner asks interactive questions at startup (AI evaluation, save report, date threshold). Downloading first then running ensures the prompts work correctly.
Usage
wp2shell-scan.sh — fast server-wide scan
sudo bash wp2shell-scan.sh
Finds all WordPress installs under /home/*/web/*/public_html/, runs all checks, prints colour-coded output to terminal, and saves a full report to /root/wp2shell-report-YYYYMMDD-HHMMSS.txt.
At startup it asks for an optional custom date threshold (default: 2026-07-15).
wp2shell-report-per-user.sh — full scan with email reports
sudo bash wp2shell-report-per-user.sh
At startup, three questions:
[AI EVALUATION] Use AI evaluation for ambiguous files? [y/N]
[SAVE REPORT] Save a full report file for later review? [y/N]
[DATE THRESHOLD] Use a different date? Leave blank to keep default [YYYY-MM-DD]:
Always start with DRY_RUN=1 (the default) — emails are previewed on screen, nothing is sent. Change to DRY_RUN=0 only after confirming the output looks correct.
Configuration
wp2shell-scan.sh
| Variable | Default | Description |
|---|---|---|
WEB_ROOT | /home | HestiaCP web root |
SINCE_DATE | 2026-07-15 | "Recently modified" threshold |
WP | wp | Path to WP-CLI |
wp2shell-report-per-user.sh
| Variable | Default | Description |
|---|---|---|
DRY_RUN | 1 | 1 = preview only, 0 = send emails |
SEND_ONLY_IF_ISSUES | 0 | 1 = skip email if site is clean |
SINCE_DATE | 2026-07-15 | "Recently modified" threshold |
MAIL_FROM | security@<hostname> | Envelope sender |
CORE_CACHE | /root/wp2shell-cores | Clean core cache directory |
ANTHROPIC_API_KEY | (empty) | Claude API key for AI evaluation |
AI Evaluation (optional)
For ambiguous diffs that patterns alone cannot classify, the scanner sends the diff to the Claude API (claude-sonnet-4-6) and returns a verdict: DANGER, SUSPICIOUS, REVIEW, or OK with a one-sentence explanation. AI is used only in the grey zone — clear cases are classified instantly without any API call.
Set your key in the script or export before running:
export ANTHROPIC_API_KEY='sk-ant-api03-...'
sudo -E bash wp2shell-report-per-user.sh
API keys: https://console.anthropic.com — separate from claude.ai subscriptions.