Skip to main content
Blog

BETA DETECTION: WordPress wp2shell Post-Exploitation Persistence and Enumeration Activity

  • July 21, 2026
  • 0 replies
  • 10 views
Aaron Beardslee
Forum|alt.badge.img
name: 'WordPress wp2shell Post-Exploitation Persistence and Enumeration Activity Analytic'
signatureid: WAF-APP02-RUN
category: 'Persistence'
threatname: 'Server Software Component: Web Shell'
functionality: 'Web Proxy'

description: |
Detects the post-exploitation web activity Wiz Research observed following successful exploitation of
the wp2shell WordPress Core RCE chain (CVE-2026-63030 + CVE-2026-60137), disclosed 2026-07-17 and
confirmed exploited in the wild from 2026-07-18. This rule covers what multiple
actors did next on compromised, cloud-self-hosted WordPress instances:

1. Malicious plugin upload for persistence — attackers accessed
/wp-admin/plugin-install.php?tab=upload and POSTed to /wp-admin/update.php?action=upload-plugin to
install backdoors. Observed payloads included a minimal one-liner PHP webshell
(eval($_POST['<param>'] ?? 'http_response_code(404);'), returning 404 as an evasion technique), a
~150KB full-featured webshell masquerading as "CMSmap" — note the genuine Dionach CMSmap project
is a standalone Python CMS scanner, NOT a WordPress plugin, so a plugin directory bearing that
name is itself the finding (GUI, password auth, file management, database access, port scanning,
batch code injection, and MySQL UDF privilege-escalation modules; obfuscated via hex-encoded
string concatenation and
eval(gzuncompress(base64_decode(...)))), and a plugin registering a custom REST route
(/morning/v1/<redacted>) with permission_callback => '__return_true' that passthru()s a
base64-decoded command from the 'c' parameter and returns the output as JSON.
2. User enumeration — requests to /wp-json/wp/v2/users?context=edit to harvest administrator
usernames and email addresses.
3. Local file inclusion — admin-ajax.php?template=../../../wp-config, targeting database credentials
and authentication keys for exfiltration.
4. Authenticated admin panel access — /wp-admin/ returning HTTP 200, indicating a successful session.

Wiz also observed high-volume opportunistic mass scanning without follow-on activity, and had not
identified lateral movement or data exfiltration at time of publication. Note that plugin upload,
user listing, and /wp-admin/ access are all legitimate administrative actions in isolation.
reference:
- https://www.wiz.io/blog/wp2shell-cve-2026-63030-cve-2026-60137
- https://hadrian.io/blog/wp2shell-a-pre-authentication-rce-in-wordpress-cores-rest-batch-api
- https://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/
- https://www.tenable.com/blog/wp2shell-cve-2026-63030-cve-2026-60137-frequently-asked-questions-about-remote-code-execution
- https://thehackernews.com/2026/07/wordpress-wp2shell-exploitation-grows.html
- https://github.com/dionach/CMSmap
labels:
- attack.persistence
- attack.t1505.003
- attack.t1505
- attack.discovery
- attack.t1087
- attack.credential_access
- attack.t1552.001
- attack.initial_access
- attack.t1190
- cve.2026.63030
- cve.2026.60137
- wp2shell
- WordPress
- Web Shell
- CMSmap
logsource:
product: Web Application Firewall
category: web server
detection:
selection_plugin_upload:
RequestUrl|contains:
- '/wp-admin/update.php?action=upload-plugin'
- '/wp-admin/plugin-install.php?tab=upload'
selection_user_enumeration:
RequestUrl|contains:
- '/wp-json/wp/v2/users?context=edit'
- 'rest_route=/wp/v2/users'
- 'rest_route=%2Fwp%2Fv2%2Fusers'
selection_lfi_wpconfig:
RequestUrl|contains|all:
- 'admin-ajax.php'
- 'template='
- 'wp-config'
selection_webshell_rest_route:
RequestUrl|contains:
- '/wp-json/morning/v1/'
- 'rest_route=/morning/v1'
- 'rest_route=%2Fmorning%2Fv1'
condition: selection_plugin_upload or selection_user_enumeration or selection_lfi_wpconfig or selection_webshell_rest_route

violator: RTActivityAccount
verbose_info: 'WordPress post-exploitation activity consistent with wp2shell follow-on tradecraft was observed from ${sourceaddress!"UNKNOWN"} to ${domainname!"UNKNOWN"} (${requesturl!"UNKNOWN"}, status ${statuscode!"UNKNOWN"}).'
violation_summary:
grouping_attribute: 'devicehostname'
level2_attribute: 'domainname'
level2_metadata_attributes:
- requesturl
- statuscode
- sourceaddress
- requestclientapplication

TECHNICAL DETAILS


    Post-exploitation behaviors and webshell descriptions are taken from Wiz Research's 2026-07-20 
    in-the-wild exploitation writeup (Shahar Dorfman, Gili Tikochinski).

    SELECTION-LEVEL FP GUIDANCE
    ---------------------------
    selection_plugin_upload:
      MODERATE-TO-HIGH FP RISK. Legitimate administrators install plugins this way. The signal is source
      and timing, not the path itself. Recommended triage: correlate against SourceAddress (expected admin
      ranges / VPN egress) hit on the same host within the preceding hours. In environments where plugin installation is change-controlled or disabled
      (DISALLOW_FILE_MODS), FP risk drops to near zero and this becomes the single highest-value selector
      in this rule — persistence via malicious plugin was the primary observed objective.

    selection_user_enumeration:
      MODERATE FP RISK. ?context=edit requires an authenticated session with list_users capability, so
      hits from unauthenticated or unexpected sources are strongly suspicious. The broader
      rest_route=/wp/v2/users patterns will also match benign unauthenticated user-listing requests, which
      are extremely common background internet noise against WordPress. Consider tightening to the
      context=edit form only if noise is excessive.

    selection_lfi_wpconfig:
      LOW FP RISK. Requires 'admin-ajax.php' AND both 'template=' and 'wp-config' in the same URL. There
      is no legitimate reason for a template parameter to reference wp-config. Any hit warrants immediate
      credential-rotation assessment: wp-config.php holds DB credentials and the WordPress auth salts/keys.
      Note this pattern is a generic vulnerable-plugin LFI primitive that predates wp2shell and may
      indicate an unrelated plugin vulnerability — either way it is worth investigating.

    selection_webshell_rest_route:
      NEAR-ZERO FP, but PERISHABLE. 'morning/v1' is the REST namespace used by one specific malicious
      plugin Wiz observed; the route name after the namespace was redacted in their publication, so this
      selector matches on namespace only. A different operator, or the same operator in a later wave, will
      use a different namespace. Retain for the specific cluster, but do not treat its absence as evidence
      of no webshell.

    /wp-admin/ ACCESS — DELIBERATELY NOT IMPLEMENTED
    ------------------------------------------------
    Wiz listed "attackers accessed /wp-admin/ and received HTTP 200" as an observed post-exploitation
    behavior. A selector for that would match essentially every legitimate administrator session in the
    environment and was omitted as unmanageably noisy for an alerting rule. Recommend covering it instead
    as a hunting query: /wp-admin/ 200-responses from source addresses with no prior successful
    /wp-login.php POST, or from geographies/ASNs inconsistent with the admin population.

    KNOWN IOCs (Wiz Research, 2026-07-20) — SHA-1 hashes of deployed PHP webshells:
      2a1410d8e2a8337ac2171cedea8c0fdc47c647a0
      58eca847e9eae9e6b08cc211f1559817b71bc4cc
      ebea44890f434d5d67ede22009a3f4bb5cac33f8
      d9a220c8039f1c4d72cae7ccb8b3a33dec8815be
      e9756e2338f84746007235e4cab7a70d5b3ca47f


Policy building walkthrough can be found in this previous post:

 

https://connect.securonix.com/threat%2Dresearch%2Dintelligence%2D62/beta%2Ddetection%2Dtelnyx%2Dteampcp%2Dcredential%2Dexfiltration%2D241