User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.3.1 - Authenticated (Subscriber+) PHP Object Injection
Description
The User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration plugin for WordPress is vulnerable to Deserialization of Untrusted Data in versions up to, and including, 4.3.1 This is due to insufficient input validation and type checking on the wpuf_files parameter during form submission, combined with unconditional deserialization via maybe_unserialize() when displaying post content. This makes it possible for authenticated attackers, with Subscriber-level access and above, to inject arbitrary PHP objects, which can be leveraged to execute arbitrary code, delete arbitrary files, or perform other malicious actions if a POP chain is present on the target system.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HTechnical Details
What Changed in the Fix
Changes introduced in v4.3.2
Source Code
WordPress.org SVN# Research Plan: Authenticated PHP Object Injection in WP User Frontend ## 1. Vulnerability Summary The **WP User Frontend** plugin (versions <= 4.3.1) contains a PHP Object Injection vulnerability due to the unsafe handling of the `wpuf_files` parameter. During form submission, the plugin accepts …
Show full research plan
Research Plan: Authenticated PHP Object Injection in WP User Frontend
1. Vulnerability Summary
The WP User Frontend plugin (versions <= 4.3.1) contains a PHP Object Injection vulnerability due to the unsafe handling of the wpuf_files parameter. During form submission, the plugin accepts the wpuf_files input without adequate validation or type checking and stores it as post metadata. When this metadata is later retrieved to display post content (e.g., in the user dashboard or post view), the plugin passes the value to maybe_unserialize(). Because the input is attacker-controlled and can contain a serialized PHP object string, an authenticated user (Subscriber level or higher) can trigger the __wakeup or __destruct magic methods of any class available in the WordPress environment.
2. Attack Vector Analysis
- Endpoint:
admin-ajax.php(for AJAX-based submissions) or the URL of a page containing a WPUF post-submission form. - Action:
wpuf_submit_post(for creating posts) orwpuf_edit_post(for updating). - Vulnerable Parameter:
wpuf_files - Authentication: Required (Subscriber level is sufficient).
- Preconditions:
- A frontend post-submission form must exist and be accessible to the attacker.
- The form should ideally include a "File Upload" or "Image Upload" field, though the attacker can attempt to inject the parameter into any WPUF form submission.
3. Code Flow (Inferred from Description & Architecture)
- Submission: A user submits a form. The request is caught by
wpuf_ajax_submit_post()(likely inincludes/Ajax/Post.phporincludes/Frontend_Render_Form.php). - Processing: The plugin iterates through submitted fields. For file/image fields, it looks for the
wpuf_filesparameter. - Storage: The logic fails to verify if
wpuf_filesis a simple array of IDs. It saves the raw value usingupdate_post_meta($post_id, 'wpuf_files', $injected_string). - Retrieval: When the post is viewed or managed in the frontend dashboard (handled by
includes/Frontend/Dashboard.phportemplates/dashboard.php), the plugin callsget_post_meta($post_id, 'wpuf_files', true). - Sink: The retrieved value is passed to
maybe_unserialize(). Since the injected string follows the PHP serialized format (O:S:N:{...}),unserialize()is executed.
4. Nonce Acquisition Strategy
WPUF forms use nonces for CSRF protection, typically localized in the page source.
- Form Identification: Identify a page containing the WPUF form (e.g.,
[wpuf_addpost]). - Setup:
# Create a form first if none exist (using WP-CLI) # Then create a page for it wp post create --post_type=page --post_title="Submit Post" --post_content='[wpuf_addpost id="123"]' --post_status=publish - Extraction:
- Navigate to the page as a Subscriber user.
- WPUF typically localizes script data. Check for a global JS object like
wpuf_frontendorwpuf_ajax. - Command:
browser_eval("wpuf_frontend.nonce")orbrowser_eval("wpuf_ajax.nonce"). - Alternatively, extract from the hidden field:
browser_eval("document.querySelector('input[name=\"_wpnonce\"]').value").
5. Exploitation Strategy
Step 1: Create a Post with Payload
Send a POST request to admin-ajax.php to create a post, injecting the serialized object into wpuf_files.
- Method: POST
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body Parameters:
action:wpuf_submit_postform_id:123(The ID of the form)_wpnonce:[EXTRACTED_NONCE]wpuf_files:O:8:"stdClass":0:{}(A dummy object to test, or a specific POP chain likeGuzzleHttp\Cookie\FileCookieJarfor file deletion if present).wpuf_post_title:Exploit Testwpuf_post_content:Contentpost_type:post
Step 2: Trigger Deserialization
Access the WPUF Dashboard or the specific post view to trigger the maybe_unserialize call.
- URL:
http://localhost:8080/dashboard/(or wherever the[wpuf_dashboard]shortcode is placed). - The dashboard renders the post list and often pre-loads metadata (like attached files) to display thumbnails, triggering the sink.
6. Test Data Setup
- User: Create a Subscriber user.
wp user create attacker attacker@example.com --role=subscriber --user_pass=password - Form: Ensure a Post Form exists in WPUF.
- Go to "WP User Frontend" -> "Post Forms".
- Create a basic form and note its ID.
- Page: Create a page for the form.
wp post create --post_type=page --post_status=publish --post_content='[wpuf_addpost id="YOUR_FORM_ID"]'
7. Expected Results
- The metadata for the created post will contain the serialized string.
- When the dashboard or post is viewed, the application will attempt to instantiate the injected object.
- If an invalid class is used, it might appear in PHP error logs:
PHP Fatal error: unserialize(): Attempt to read property "..." on nullorClass not found. - If a valid POP chain is used, the side effect (e.g., file creation, command execution) will occur.
8. Verification Steps
- Check Database: Verify the meta was stored as a string, not an array.
wp post meta get [POST_ID] wpuf_files - Monitor Logs: Check
wp-content/debug.logfor any signs of theunserialize()call or class instantiation errors. - Verify POP Effect: If using a file deletion gadget, check if the target file is gone.
9. Alternative Approaches
If wpuf_submit_post is patched or strictly validates wpuf_files as an array of integers:
- Try Nested Parameters: Try
wpuf_files[0]=O:8:"stdClass":0:{}. - Try Edit Action: If submission is secure, check the
wpuf_edit_postaction, which often uses different code paths for updating existing metadata. - Check Profile Forms: WPUF also handles profile updates. Check if
wpuf_filesor similar file upload parameters exist in thewpuf_update_profileaction.
Summary
The WP User Frontend plugin for WordPress is vulnerable to PHP Object Injection in versions up to 4.3.1. This occurs because the plugin stores the 'wpuf_files' parameter from form submissions directly into post metadata without validation and subsequently retrieves it using maybe_unserialize(), allowing authenticated attackers to execute arbitrary PHP objects via a POP chain.
Vulnerable Code
// Inferred from includes/Frontend_Render_Form.php // The plugin fails to validate the type or content of the 'wpuf_files' input before storage if ( isset( $post_data['wpuf_files'] ) ) { update_post_meta( $post_id, 'wpuf_files', $post_data['wpuf_files'] ); } --- // Inferred from templates/dashboard.php or post display logic // The retrieved meta value is passed to a deserialization sink $wpuf_files = get_post_meta( $post_id, 'wpuf_files', true ); $attachments = maybe_unserialize( $wpuf_files );
Security Fix
@@ -1042,7 +1042,8 @@ - if ( isset( $post_data['wpuf_files'] ) ) { - update_post_meta( $post_id, 'wpuf_files', $post_data['wpuf_files'] ); - } + if ( isset( $post_data['wpuf_files'] ) ) { + $wpuf_files = is_array( $post_data['wpuf_files'] ) ? array_map( 'intval', $post_data['wpuf_files'] ) : array(); + update_post_meta( $post_id, 'wpuf_files', $wpuf_files ); + }
Exploit Outline
To exploit this vulnerability, an authenticated attacker with Subscriber-level permissions or higher identifies a page containing a WP User Frontend post submission form. After extracting the required security nonce (usually found in the page source as part of the 'wpuf_frontend' or 'wpuf_ajax' JS objects), the attacker submits a POST request to the admin-ajax.php endpoint with the action 'wpuf_submit_post'. The request includes a serialized PHP object payload in the 'wpuf_files' parameter. Once the post is successfully created and stored, the attacker (or any user viewing the dashboard) triggers the payload by visiting the frontend dashboard or the post itself. The plugin's display logic retrieves the malicious string from the database and passes it to maybe_unserialize(), which instantiates the injected object and triggers its magic methods.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.