Like leaving a loaded gun in a rarely-visited cabin that only people with a key and a specific toolkit can reach
CVE-2026-87909 is a remote code execution flaw in the wppa_image_magick function of the WP Photo Album Plus WordPress plugin (all versions through 9.2.09.002). When a user uploads a photo, the plugin builds an ImageMagick CLI command by concatenating the multipart upload filename into a string passed to exec(). The developer applied escapeshellcmd() to the *entire command*, which escapes shell metacharacters (;, |, ` `) but leaves spaces intact — meaning an attacker-controlled filename can inject *additional arguments* into the ImageMagick convert binary. ImageMagick's -write and MSL delegates have historically been abusable to write arbitrary files (webshells). The DB-layer filename sanitizer never touches the physical temp path, so the injection survives to the exec()` call. Authentication is required at the subscriber level or above.
The vendor's HIGH / 7.5 rating reflects the theoretical ceiling: authenticated RCE with full C/I/A impact. But the CVSS vector already includes AC:H (high complexity), and several compounding real-world prerequisites — WordPress open registration disabled by default, ImageMagick CLI required on the server *and* enabled in plugin settings, exec() not disabled by the host, and only ~10,000 active installs worldwide — mean the reachable population is a thin slice of a thin slice. The vendor score is technically defensible but overstates operational urgency for most defenders.
5 steps from start to impact.
Obtain subscriber-level WordPress account
Settings → General → Anyone can register is unchecked). On sites that do allow registration, Subscriber is the default role. The attacker either registers on an open-registration site or uses a compromised/insider credential.- Target WordPress site has open registration enabled, OR attacker has existing subscriber credentials
- WordPress registration is off by default — fewer than ~15-20% of public WordPress sites enable it
- Many sites that enable registration use CAPTCHA, email verification, or approval workflows that slow mass exploitation
wp_users table and auth logs; Wordfence, Sucuri, and iThemes Security flag registration anomalies.Confirm ImageMagick CLI is available and enabled in plugin settings
convert binary path. Additionally, the server must have exec() enabled in php.ini — many shared hosts add exec to disable_functions. If either condition is unmet, the attack path is dead.- ImageMagick CLI tools installed on server
- PHP
exec()not indisable_functions - Plugin setting 'Use ImageMagick' enabled with valid binary path
- Most shared WordPress hosts disable
exec()in production - GD is the more common image backend; admin must actively configure ImageMagick CLI in the plugin
- Managed WordPress hosts (WP Engine, Kinsta, Flywheel) typically sandbox PHP execution and block shell calls
phpinfo() for disable_functions; check plugin option wppa_use_imagemagick in wp_options table.Upload crafted filename via multipart form
innocent.jpg -write /var/www/html/wp-content/uploads/shell.php could inject a -write argument. The escapeshellcmd() wrapper will not strip the spaces, allowing the injected arguments to be parsed by the convert binary as separate parameters.- Front-end upload capability enabled for subscriber role in plugin settings
- Plugin processes the uploaded file through
wppa_image_magickfunction
- The plugin's upload feature may be admin-only or restricted to higher roles depending on configuration
- Filename length and character restrictions at the web server or WAF layer may truncate or reject the payload
- The exact exploitation technique depends on the server's ImageMagick version and compiled delegates — modern ImageMagick (7.x) has restricted many dangerous delegates by default via
policy.xml
filename headers; ModSecurity CRS rules for ImageMagick abuse patterns; Wordfence firewall rules (added post-disclosure).ImageMagick processes injected arguments
convert binary parses the attacker-injected arguments. Depending on the ImageMagick version and policy.xml configuration, the attacker can use delegates like -write, ephemeral:, or MSL scripting to write an arbitrary PHP file (webshell) to a web-accessible directory. Modern ImageMagick 7.x with default policy.xml restrictions on MVG, MSL, EPHEMERAL, and URL delegates significantly limits this, but many older or misconfigured installations remain permissive.- ImageMagick
policy.xmldoes not block dangerous delegates - Web server document root is writable by the PHP process
- ImageMagick 7.x default policies block most dangerous delegates since the 2016 ImageTragick fixes
- SELinux/AppArmor on hardened hosts may prevent writes outside temp directories
- PHP open_basedir restrictions may constrain file writes
wp-content/uploads/; YARA rules for webshell signatures; endpoint detection for unexpected child processes spawned by convert.Execute webshell for full server compromise
www-data or apache). From here, standard post-exploitation follows: credential harvesting from wp-config.php, lateral movement, privilege escalation.- Webshell successfully written to web-accessible path
- No file integrity monitoring or real-time webshell detection
- EDR/AV agents detect common webshell patterns
- Cloud WAFs (Cloudflare, Sucuri) can detect webshell access patterns
- Immutable infrastructure (containers, read-only filesystems) prevents persistent file writes
The supporting signals.
| In-the-Wild Exploitation | No evidence. Not listed in CISA KEV. No known campaigns or threat actor attribution as of 2026-09-22. Composite risk score of 43.8/100 per automated threat intel platforms. |
|---|---|
| Proof of Concept | No public PoC identified. No exploit code on GitHub, ExploitDB, or Metasploit as of assessment date. The technique (ImageMagick argument injection via escapeshellcmd) is well-documented generically but no weaponized exploit specific to this CVE has surfaced. |
| EPSS Score | 0.00525 (0.53%) — 57th percentile. Indicates low predicted exploitation probability within 30 days. Consistent with the high friction chain. |
| CISA KEV Status | Not listed. No known due date for federal remediation. |
| CVSS Vector | CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H — Network-reachable but high complexity, low-privilege auth required, no user interaction. Scope unchanged (no hypervisor/sandbox escape). Full impact triad when successful. |
| Affected Versions | All versions of WP Photo Album Plus up to and including 9.2.09.002. Plugin author: opajaap. |
| Fixed Version | 9.3.02.003 (current release as of 2026-09-22, updated within hours of assessment). No explicit vendor advisory, but version jump from 9.2.x to 9.3.x and timing strongly suggest the fix is included. No distro backports applicable (WordPress plugin). |
| Install Base / Exposure | ~10,000 active WordPress installations per wordpress.org. This is a niche photo gallery plugin — roughly 0.002% of the ~500M WordPress sites globally. No Shodan/Censys/GreyNoise fingerprint exists for this plugin specifically. |
| Disclosure Timeline | CVE reserved 2026-09-09, published 2026-09-19. Assigned by Wordfence (CNA). Wordfence firewall rules likely deployed to premium users on or before publication. |
| Researcher / Org | Discovered and reported via the Wordfence Bug Bounty Program. Specific researcher name not disclosed in public advisory. |
Why this verdict
- Authentication gate: Requires subscriber-level WordPress credentials. WordPress ships with registration disabled by default — the majority of the ~10,000 installs are not open-registration sites, compressing the unauthenticated attack surface to near zero.
- ImageMagick CLI dependency: The vulnerable code path only executes when the admin has configured the plugin to use the ImageMagick CLI binary AND the server has
exec()enabled in PHP. Many shared hosts disableexec(); many installs use GD instead. This eliminates a large fraction of the already-small install base. - High attack complexity confirmed: CVSS AC:H is warranted — exploitation requires chaining filename injection through
escapeshellcmd()with a permissive ImageMagickpolicy.xmlthat doesn't block dangerous delegates. Post-ImageTragick (2016), most modern ImageMagick 7.x defaults restrict the delegates needed for file-write primitives. - Tiny blast radius: ~10,000 active installs worldwide. Even at 100% exploitation success, the absolute number of vulnerable targets is minuscule compared to any enterprise fleet's WordPress footprint.
- Role multiplier: WP Photo Album Plus is a photo gallery widget — it is never a high-value infrastructure component. It does not run on domain controllers, hypervisors, CI/CD pipelines, or network edge appliances. The blast radius of a successful exploit is one WordPress web server (host-level). There is no identity-scale, fleet-scale, or supply-chain escalation path inherent to this component. No high-value-role floor applies.
- No exploitation evidence: Zero PoCs, zero ITW campaigns, not KEV-listed, EPSS at 0.53%. The threat is entirely theoretical as of assessment date.
Why not higher?
The vendor's HIGH/7.5 would be appropriate if this were a widely-deployed component with low-friction exploitation. It is neither. The install base is ~10,000 (trivial), the chain requires authentication + a specific server configuration (ImageMagick CLI + exec() enabled + permissive policy.xml) that most real deployments lack, and there is zero exploitation evidence. No high-value deployment role raises the floor. Keeping this at HIGH would misallocate patching priority away from genuinely critical vulnerabilities in your fleet.
Why not lower?
When the full chain succeeds, the outcome is unauthenticated-equivalent RCE (webshell) on the WordPress host — a complete server compromise including database credentials, user data, and a pivot point into the hosting network. The technique (ImageMagick argument injection) is well-understood by attackers, and a motivated adversary targeting a specific site that runs this plugin with the right configuration could exploit it reliably. LOW would understate the impact for the small population that *is* vulnerable.
What to do — in priority order.
- Update to WP Photo Album Plus 9.3.02.003 immediately — The current release (9.3.02.003, published 2026-09-22) almost certainly contains the fix given the version jump and disclosure timing. This is the definitive remediation. As a MEDIUM verdict, the noisgate remediation SLA allows up to 365 days, but given this is a simple plugin update with no compatibility risk, deploy within the next maintenance window.
- Disable ImageMagick CLI in plugin settings — Navigate to WP Photo Album Plus → Settings → ImageMagick and disable the ImageMagick option or remove the binary path. The plugin falls back to PHP GD, which does not invoke
exec()and eliminates the vulnerable code path entirely. This is the fastest compensating control — no mitigation SLA applies for MEDIUM, but do this today if you can't update immediately. - Add exec() to PHP disable_functions — In
php.ini, addexectodisable_functionsif not already present. This kills the entire class of shell-execution vulnerabilities in PHP, not just this one. Requires a PHP-FPM/Apache restart. Verify the plugin and other functionality still work with GD fallback. - Disable WordPress open registration — Ensure
Settings → General → Anyone can registeris unchecked on all WordPress instances. This eliminates the unauthenticated-to-subscriber escalation path. Audit with WP-CLI:wp option get users_can_register(should return0). - Deploy WAF rule for multipart filename injection — Add a ModSecurity or Cloudflare WAF rule that rejects multipart upload requests where the
filenameheader contains ImageMagick argument flags (-write,-script,ephemeral:,msl:). This provides defense-in-depth even if the plugin isn't updated.
- WordPress core auto-updates — WordPress auto-updates core but does NOT auto-update plugins unless explicitly enabled per-plugin. Do not assume this plugin will self-patch.
- PHP Imagick extension (PECL) — disabling or uninstalling the PHP Imagick extension does NOT help. This vulnerability uses the ImageMagick CLI binary via
exec(), which is completely separate from the PHP extension. - File upload size limits — restricting upload file size does not prevent argument injection through filenames. The payload is in the filename metadata, not the file body.
Crowdsourced verification payload.
Run this on each WordPress host where WP Photo Album Plus may be installed. Requires read access to the WordPress installation directory. Execute as the web server user or root: sudo bash check_cve_2026_87909.sh /var/www/html
#!/usr/bin/env bash
# CVE-2026-87909 Checker — WP Photo Album Plus ImageMagick RCE
# Usage: bash check_cve_2026_87909.sh /path/to/wordpress
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
WP_PATH="${1:?Usage: $0 /path/to/wordpress}"
PLUGIN_DIR="$WP_PATH/wp-content/plugins/wp-photo-album-plus"
# Check if plugin is installed
if [ ! -d "$PLUGIN_DIR" ]; then
echo "PATCHED — WP Photo Album Plus is not installed at $WP_PATH"
exit 0
fi
# Extract version from readme.txt or the main plugin file
VERSION=""
if [ -f "$PLUGIN_DIR/wp-photo-album-plus.php" ]; then
VERSION=$(grep -i 'Version:' "$PLUGIN_DIR/wp-photo-album-plus.php" | head -1 | sed 's/.*Version:[[:space:]]*//' | tr -d '[:space:]')
fi
if [ -z "$VERSION" ] && [ -f "$PLUGIN_DIR/readme.txt" ]; then
VERSION=$(grep -i 'Stable tag:' "$PLUGIN_DIR/readme.txt" | head -1 | sed 's/.*Stable tag:[[:space:]]*//' | tr -d '[:space:]')
fi
if [ -z "$VERSION" ]; then
echo "UNKNOWN — Could not determine WP Photo Album Plus version"
exit 2
fi
echo "Detected WP Photo Album Plus version: $VERSION"
# Compare version — vulnerable: <= 9.2.09.002, fixed: >= 9.3.x
# Use sort -V for version comparison
FIXED_VERSION="9.2.09.003"
if printf '%s\n%s' "$FIXED_VERSION" "$VERSION" | sort -V | head -1 | grep -qx "$FIXED_VERSION"; then
echo "PATCHED — Version $VERSION is at or above the fix threshold"
exit 0
else
# Additional check: look for escapeshellarg in the vulnerable function
if grep -rq 'escapeshellarg' "$PLUGIN_DIR/wppa-photo-files.php" 2>/dev/null || \
grep -rq 'escapeshellarg' "$PLUGIN_DIR/wppa-functions.php" 2>/dev/null; then
echo "PATCHED — Version $VERSION contains escapeshellarg fix in image processing code"
exit 0
fi
echo "VULNERABLE — Version $VERSION is affected by CVE-2026-87909"
echo " Affected: all versions <= 9.2.09.002"
echo " Fix: update to 9.3.02.003 or later"
echo " Mitigate: disable ImageMagick in plugin settings"
exit 1
fi- Wordfence Threat Intel — WP Photo Album Plus
- Strix CVE-2026-87909 Analysis
- OffSeq Threat Radar — CVE-2026-87909
- GitHub Vuln Alert — CVE-2026-87909
- WordPress.org — WP Photo Album Plus Plugin Page
- WP Photo Album Plus ImageMagick Documentation
- ImageTragick — ImageMagick Exploit Background
- OpenCVE — WP Photo Album Plus Vulnerabilities
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.