NVD has published CVE-2026-13447, a CVSS 9.8 (Critical), network-exploitable vulnerability affecting the Mstore Api plugin for WordPress — a mobile app backend plugin widely used to power WooCommerce storefront applications. While the headline frames the affected component as 'openssl,' the reality defenders need to internalize is more insidious: this is not a flaw in OpenSSL itself, but a fatal implementation error in which the plugin's FirebasePhoneAuthHelper::verify_id_token() function decodes and superficially validates Firebase ID token claims — alg, kid, aud, iss — without ever calling openssl_verify() or any equivalent signature verification against Google's actual public key certificates.
The result: an unauthenticated attacker anywhere on the internet can mint a self-signed RSA key pair, craft a Firebase Phone Auth JWT asserting any phone number or user identity, and impersonate arbitrary users — including administrative accounts — on any WordPress site running Mstore Api version 4.20.0 or earlier. No credentials, no user interaction, no prior access required. If you operate WooCommerce storefronts with mobile app backends, this is a patch-today event.
Technical Analysis
Affected Products and Versions
| Attribute | Detail |
|---|---|
| CVE | CVE-2026-13447 |
| CVSS 3.1 Score | 9.8 (CRITICAL) |
| Attack Vector | NETWORK (unauthenticated, remote) |
| Affected Component | Mstore Api plugin for WordPress (WooCommerce mobile app backend) |
| Affected Versions | All versions up to and including 4.20.0 |
| Vulnerable Function | FirebasePhoneAuthHelper::verify_id_token() |
| CWE Class | CWE-347: Improper Verification of Cryptographic Signature |
How the Vulnerability Works
JSON Web Tokens are only as trustworthy as the signature verification behind them. A Firebase ID token is a JWT signed by Google's private key, and correct validation requires fetching Google's rotating public certificates (published at a well-known JWKS endpoint), matching the token's kid header to the correct certificate, and cryptographically verifying the RS256 signature.
The Mstore Api plugin skips that last — and only meaningful — step. From a defender's perspective, the attack chain looks like this:
- Attacker generates a throwaway RSA key pair locally. No interaction with the target is needed for this step.
- Attacker constructs a forged JWT with
alg: RS256, a fabricatedkid, and claims matching a legitimate Firebase project (aud,iss) — these values are trivially discoverable from the target site's mobile app configuration or JavaScript bundles, since Firebase project identifiers are not secrets. - The payload claim is set to the victim's phone number / user identity, and the token is signed with the attacker's private key.
- The forged token is POSTed to the plugin's phone-auth REST endpoint (the Mstore Api plugin exposes custom REST routes under the WordPress
wp-jsonnamespace for Firebase phone authentication). verify_id_token()decodes the token, checksalg,kid,aud, andissas string comparisons, finds them plausible, and returns success — the signature is never verified becauseopenssl_verify()is never invoked.- The attacker receives an authenticated WordPress session as the impersonated user. If the victim account is a shop manager or administrator, full site compromise follows: plugin/theme uploads, database access, payment skimmer injection into the WooCommerce checkout flow.
The mention of openssl_verify() in the advisory is what likely drove the 'openssl' framing — but OpenSSL is functioning exactly as designed. The defect is that the calling application never asked it to verify anything.
Exploitation Status
At time of writing, CVE-2026-13447 is newly published. Given the vulnerability class — a deterministic, unauthenticated authentication bypass with a trivial exploitation cost (forge-and-send) — defenders should treat exploitation as imminent if not already underway. JWT-forgery auth bypasses in WordPress plugins historically appear in mass-scanning and automated exploitation within days of disclosure. Check CISA KEV for updates, but do not wait for a KEV listing to act on a 9.8 unauthenticated bypass in an internet-facing e-commerce component.
Detection & Response
This is a technical threat. The following detections target the observable behaviors of exploitation: forged-token requests against the plugin's REST endpoints and the post-exploitation actions that follow successful impersonation.
The strongest detection signal is at the web server / WAF layer: unauthenticated requests to Mstore Api phone-authentication routes carrying JWT-shaped bodies, especially bursts of such requests, or requests followed by administrative activity from accounts that have no corresponding legitimate Firebase session.
---
title: Suspicious Requests to Mstore Api Phone Auth Endpoint
tid: 3f8c1a92-7d4e-4b6a-9c15-2e8f0a1b3d44
status: experimental
description: Detects HTTP requests to WordPress Mstore Api plugin Firebase phone authentication REST routes, which may indicate exploitation of CVE-2026-13447 JWT forgery authentication bypass. Tune to baseline volume for your storefronts.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-13447
author: Security Arsenal
date: 2026/01/15
tags:
- attack.initial_access
- attack.t1190
logsource:
category: webserver
product: apache
detour:
note: Also applicable to nginx and IIS logs via equivalent field mappings
detection:
selection:
cs-uri-stem|contains:
- '/wp-json/mstore'
- 'mstore-api'
- 'firebase'
- 'phone'
filter_method:
cs-method: 'POST'
condition: selection and filter_method
falsepositives:
- Legitimate mobile app authentication traffic from genuine users
level: medium
---
title: JWT-Shaped Payload in WordPress REST Authentication Request
tid: 8a2e5f17-1b3c-4d9e-a762-4f9c2d5e8b11
status: experimental
description: Detects POST requests to WordPress REST API auth endpoints containing a base64url-encoded RS256 JWT header pattern, consistent with forged Firebase ID tokens submitted to exploit CVE-2026-13447 in Mstore Api <= 4.20.0.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-13447
author: Security Arsenal
date: 2026/01/15
tags:
- attack.initial_access
- attack.t1190
- attack.t1078
logsource:
category: webserver
product: nginx
detection:
selection:
cs-method: 'POST'
request_body|contains:
- 'eyJhbGciOiJSUzI1NiI' # base64url of {"alg":"RS256"
- 'id_token'
- 'idToken'
filter_namespace:
cs-uri-stem|contains: '/wp-json/'
condition: selection and filter_namespace
falsepositives:
- Legitimate Firebase phone auth logins from the mobile application
level: high
---
title: WordPress Admin Activity Following Mstore Api Authentication
tid: c47d9b30-6e21-4a58-bf84-7c2a9e5d1f66
status: experimental
description: Detects PHP process spawned by the web server user accessing wp-admin or plugin/theme editor functionality shortly after Mstore Api endpoint requests, indicating post-exploitation activity following successful CVE-2026-13447 impersonation.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-13447
author: Security Arsenal
date: 2026/01/15
tags:
- attack.persistence
- attack.t1505.003
- attack.privilege_escalation
logsource:
category: process_creation
product: linux
detection:
selection:
ParentImage|endswith:
- '/php-fpm'
- '/apache2'
- '/nginx'
Image|endswith:
- '/sh'
- '/bash'
- '/curl'
- '/wget'
- '/zip'
- '/php'
condition: selection
falsepositives:
- Legitimate WordPress maintenance scripts and backup plugins invoking shell utilities
level: high
A note on fidelity: legitimate mobile app traffic will hit these endpoints continuously on a busy storefront, so the raw endpoint rule is a hunting and correlation primitive, not a standalone alert. The high-value analytic is correlating Mstore Api auth requests with subsequent privileged actions — a user authenticating via the phone-auth route who then immediately accesses /wp-admin/plugin-editor.php or /wp-admin/plugin-install.php is your smoking gun. The second rule, matching the decoded RS256 JWT header prefix (eyJhbGciOiJSUzI1NiI) in request bodies, is far more precise because it keys on the actual attack payload shape; it requires request-body logging (ModSecurity, WAF, or a full-packet proxy) to be effective.
// Hunt for potential CVE-2026-13447 exploitation against Mstore Api WordPress plugin
// Requires web server / WAF logs ingested into Sentinel (IIS, Apache/Nginx via CEF/Syslog, or W3CIISLog)
let lookback = 7d;
let MstoreAuthRequests =
CommonSecurityLog
| where TimeGenerated > ago(lookback)
| where RequestURL has_any ("/wp-json/mstore", "mstore-api") or RequestURL has "firebase"
| where RequestMethod == "POST"
| project TimeGenerated, SourceIP, RequestURL, RequestMethod, RequestPayload = AdditionalExtensions, DeviceVendor;
let IisRequests =
W3CIISLog
| where TimeGenerated > ago(lookback)
| where csUriStem has_any ("/wp-json/mstore", "mstore-api")
| where csMethod == "POST"
| project TimeGenerated, cIP, csUriStem, csMethod, scStatus, csUserAgent;
union MstoreAuthRequests, IisRequests
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), RequestCount=count(),
DistinctURIs=dcount(csUriStem), StatusCodes=make_set(scStatus), UserAgents=make_set(csUserAgent)
by SourceIP = coalesce(SourceIP, cIP)
| where RequestCount > 20 or DistinctURIs > 1 // tuning thresholds: bursts or endpoint probing
| order by RequestCount desc;
// Correlate: source IPs hitting Mstore auth endpoints that ALSO reach wp-admin plugin/theme management
let AuthSources =
W3CIISLog
| where TimeGenerated > ago(lookback)
| where csUriStem has_any ("/wp-json/mstore", "mstore-api") and csMethod == "POST"
| summarize by cIP;
W3CIISLog
| where TimeGenerated > ago(lookback)
| where cIP in (AuthSources)
| where csUriStem has_any ("plugin-editor", "plugin-install", "theme-editor", "update.php", "user-new")
| project TimeGenerated, cIP, csUriStem, csMethod, scStatus, csUserAgent
| order by TimeGenerated asc;
-- Hunt for post-exploitation artifacts on WordPress hosts following potential
-- CVE-2026-13447 abuse: recently modified PHP files in wp-content, new admin
-- user artifacts, and web-spawned processes.
LET web_roots = SELECT FullPath FROM glob(globs=['/var/www/*/wp-content/plugins/**', '/srv/www/*/wp-content/plugins/**'])
-- Recently created/modified PHP files in wp-content (potential webshells or backdoored plugin files)
SELECT FullPath, Size, Mtime, Ctime
FROM glob(globs=['/var/www/**/wp-content/**/*.php', '/srv/www/**/wp-content/**/*.php'])
WHERE Mtime > now() - 604800
ORDER BY Mtime DESC
-- Web-server-spawned shell or utility processes (live triage)
SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Username =~ 'www-data|apache|nginx|nobody'
AND Name =~ 'sh|bash|curl|wget|nc|ncat|python|perl|php'
#!/bin/bash
# CVE-2026-13447 verification and containment script for WordPress hosts (run on each web server)
# 1) Identify Mstore Api plugin presence and version
# 2) Check for signs of recent auth-endpoint abuse in access logs
# 3) Temporarily block the vulnerable endpoint at the web server if patching is pending
set -euo pipefail
WP_PATHS=("/var/www" "/srv/www" "/home/*/public_html")
echo "=== [1] Locating Mstore Api plugin installations ==="
found=0
for base in "${WP_PATHS[@]}"; do
for readme in $base/*/wp-content/plugins/mstore-api/readme.txt $base/*/wp-content/plugins/mstore-api/readme.md; do
[ -f "$readme" ] || continue
found=1
ver=$(grep -im1 'Stable tag' "$readme" | awk '{print $NF}')
echo "FOUND: $readme -- version: ${ver:-unknown}"
if dpkg --compare-versions "${ver:-0}" le "4.20.0" 2>/dev/null; then
echo " !!! VULNERABLE to CVE-2026-13447 (<= 4.20.0) — update immediately"
else
echo " OK: version is above 4.20.0"
fi
done
done
[ "$found" -eq 0 ] && echo "No mstore-api plugin readme found in scanned paths. Verify manually via wp-cli: wp plugin list | grep -i mstore"
echo "=== [2] Scanning access logs for Mstore auth endpoint abuse (last 7 days) ==="
for log in /var/log/nginx/access.log* /var/log/apache2/access.log* /var/log/httpd/access_log*; do
[ -f "$log" ] || continue
echo "-- $log"
zgrep -hE 'POST .*(/wp-json/mstore|mstore-api|firebase)' "$log" 2>/dev/null \
| awk '{print $1}' | sort | uniq -c | sort -rn | head -20 \
| awk '$1 > 20 {print " SUSPICIOUS:", $0} $1 <= 20 {print " baseline:", $0}'
done
echo "=== [3] Checking for recently created WordPress admin users (DB check) ==="
echo "Run manually per-site: wp user list --role=administrator --format=table"
echo "Cross-reference user_registered timestamps against Mstore endpoint hits above."
echo "=== [4] OPTIONAL: temporary nginx block for the vulnerable endpoint ==="
cat <<'EOF'
# Add inside your server{} block until the plugin is updated past 4.20.0:
# location ~* /wp-json/mstore.*(firebase|phone) { return 403; }
# Then: nginx -t && systemctl reload nginx
EOF
echo "Done. Patch the plugin, then audit admin accounts and wp-content for webshells."
Remediation
Immediate actions (today):
- Update the Mstore Api plugin to the latest release via WordPress admin → Plugins, or via WP-CLI (
wp plugin update mstore-api). Any version at or below 4.20.0 is vulnerable. Check the plugin's WordPress.org repository page and the vendor's changelog for the fixed version number, and confirm the fix release specifically references signature verification of Firebase ID tokens. - If you cannot patch immediately, disable Firebase phone authentication in the plugin settings, or deactivate the plugin entirely. As a compensating control, block the vulnerable REST routes at your WAF or web server (see the nginx rule in the script above).
- Audit for prior compromise. A 9.8 unauthenticated bypass that has existed in the codebase means you must assume exploitation predates disclosure:
- Review
wp_usersfor administrator or shop-manager accounts you did not create — checkuser_registeredtimestamps against access-log hits to the Mstore endpoints. - Sweep
wp-content/uploadsandwp-content/pluginsfor PHP files with recent modification times; the VQL hunt above operationalizes this. - Rotate credentials and API keys for all administrative accounts, and invalidate active sessions (
wp session destroy --allper user, or force-logout via a security plugin). - If WooCommerce processes payments, review checkout templates and payment-gateway settings for skimmer injection — impersonated admins monetize e-commerce access fast.
- Review
- Rotate Firebase-adjacent secrets. While Firebase project IDs are public, any service-account keys, WooCommerce consumer keys/secrets, or mobile-app API keys that an impersonated admin could have read should be treated as exposed.
Strategic hardening (this quarter):
- Deploy a WAF with request-body inspection (ModSecurity with OWASP CRS, Cloudflare, or equivalent) in front of WordPress. Endpoint-only logging would have been blind to this attack class.
- Centralize web access logs into your SIEM — the correlation queries above are useless if Apache/Nginx logs never leave the host.
- Enforce least-privilege on WordPress roles. A forged phone-auth session for a customer account is bad; for an administrator it is game over. Audit role assignments and remove standing admin from accounts that authenticate through mobile-app flows.
- Add plugin provenance review to your change process. This is CWE-347 — a JWT that is decoded but never signature-verified. Any plugin implementing custom JWT/OAuth/Firebase validation should be code-reviewed (or pen-tested) for exactly this defect before deployment. If you want a second set of eyes on your WordPress attack surface, that is precisely what application penetration testing exists for.
Monitor the NVD entry and CISA KEV for updates on confirmed exploitation and any mandated remediation deadlines.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.