PublishPress Revisions: Duplicate Posts, Submit, Approve and Schedule Content Changes <= 3.7.23 - Unauthenticated SQL Injection
Description
The PublishPress Revisions: Duplicate Posts, Submit, Approve and Schedule Content Changes plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 3.7.23 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=3.7.23What Changed in the Fix
Changes introduced in v3.7.24
Source Code
WordPress.org SVN```markdown # Exploitation Research Plan: CVE-2026-32539 (PublishPress Revisions SQL Injection) ## 1. Vulnerability Summary The PublishPress Revisions plugin (<= 3.7.23) contains an unauthenticated SQL injection vulnerability. The issue originates from the `Revisionary_Archive_List_Table` and `Revi…
Show full research plan
# Exploitation Research Plan: CVE-2026-32539 (PublishPress Revisions SQL Injection)
## 1. Vulnerability Summary
The PublishPress Revisions plugin (<= 3.7.23) contains an unauthenticated SQL injection vulnerability. The issue originates from the `Revisionary_Archive_List_Table` and `Revisionary_List_Table` classes (and associated global filters), where user-supplied parameters from `$_REQUEST` are insufficiently sanitized (using `sanitize_text_field` instead of `prepare`) and then concatenated into SQL queries. Specifically, parameters like `origin_post_type` and `s` are used to build a `$base_query` which is then interpolated into further SQL statements. Because the plugin failed to properly enforce capabilities for the Revision Archive and Queue screens in affected versions, these endpoints—and the underlying vulnerable queries—are accessible to unauthenticated attackers.
## 2. Attack Vector Analysis
- **Endpoint**: `/wp-admin/admin.php?page=revisionary-archive` (The Past Revisions screen).
- **Vulnerable Parameter**: `origin_post_type` (and potentially `s`).
- **Authentication**: Unauthenticated (due to improper capability enforcement in version 3.7.23).
- **Action**: A GET or POST request to the admin page with an SQL injection payload in the `origin_post_type` parameter.
## 3. Code Flow
1. **Entry Point**: A request is made to `
Summary
The PublishPress Revisions plugin for WordPress is vulnerable to unauthenticated SQL injection due to improper preparation of user-supplied parameters like 'origin_post_type' and 's' within the revision archive and queue list tables. Because version 3.7.23 and earlier failed to enforce administrative capabilities for these screens, unauthenticated attackers can extract sensitive database information by sending crafted requests to the plugin's administration endpoints.
Vulnerable Code
// File: admin/class-list-table-archive.php // Lines 530-532 if( isset( $_REQUEST['origin_post_type'] ) && ! empty( $_REQUEST['origin_post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $args['origin_post_type'] = sanitize_text_field( $_REQUEST['origin_post_type'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } // Lines 535-545 $base_query = $this->do_query( $args ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $results = $wpdb->get_results( $wpdb->prepare( "{$base_query} LIMIT %d,%d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $offset, $per_page ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $total_items = $wpdb->get_var( "SELECT COUNT(*) as total_items FROM ($base_query) as total_items_subquery" // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared );
Security Fix
@@ -228,10 +228,11 @@ function fltAdminBodyClass($classes) { + // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if (!empty($_REQUEST['page']) && in_array($_REQUEST['page'], ['revisionary-settings', 'rvy-net_options', 'rvy-default_options', 'revisionary-q', 'revisionary-deletion', 'revisionary-archive'])) { $classes .= ' revisionary'; - switch ($_REQUEST['page']) { + switch ($_REQUEST['page']) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended case 'revisionary-archive': $classes .= ' revisionary-archive'; break; @@ -674,12 +674,12 @@ printf( esc_html__('Edit of %s', 'revisionary'), - "<span title='$this->active_revision_title'>" . $status_label . '</span>' + "<span title='" . esc_attr($this->active_revision_title) . "'>" . esc_html($status_label) . '</span>' ); } elseif ($this->parent_from_revision_workflow) { printf("<span title='%s'>%s</span>", - $this->from_revision_title, + esc_html($this->from_revision_title), esc_html__('Edit of published Revision', 'revisionary') ); } elseif ($this->direct_edit) {
Exploit Outline
1. **Identify Vulnerable Endpoint**: Target the Past Revisions screen via `/wp-admin/admin.php?page=revisionary-archive`. 2. **Verify Accessibility**: Confirm that the page is accessible without authentication (fixed in 3.7.24 by enforcing the `view_revision_archive` capability). 3. **Inject Payload**: Send a GET or POST request to the endpoint with a SQL injection payload in the `origin_post_type` parameter (e.g., `origin_post_type=post' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -`). 4. **Observe Response**: Use time-based blind injection or boolean-based techniques to infer database contents from the response latency or page output. 5. **Data Extraction**: Automate the process to dump sensitive information like administrator password hashes or configuration details from the `wp_users` and `wp_options` tables.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.