RestroPress <= 3.2.7 - Missing Authorization
Description
The RestroPress plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 3.2.7. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=3.2.7Source Code
WordPress.org SVNThis research plan focuses on exploiting a **Missing Authorization** vulnerability in **RestroPress <= 3.2.7**. The vulnerability typically exists in functions hooked to `admin_init` that perform administrative actions without verifying the user's capabilities. Because `admin-ajax.php` (and `admin…
Show full research plan
This research plan focuses on exploiting a Missing Authorization vulnerability in RestroPress <= 3.2.7.
The vulnerability typically exists in functions hooked to admin_init that perform administrative actions without verifying the user's capabilities. Because admin-ajax.php (and admin-post.php) triggers the admin_init hook even for unauthenticated users, these functions can be reached by anyone.
1. Vulnerability Summary
- Vulnerability: Missing Authorization
- Affected Function:
restropress_install_pages(inferred) - Affected Hook:
admin_init - File Path:
includes/admin/admin-actions.php(inferred) - Description: The plugin registers a function to
admin_initthat triggers the automatic creation of several WordPress pages (Checkout, Order History, etc.). It checks for a specific GET parameter but fails to check forcurrent_user_can( 'manage_options' )or verify a nonce. This allows an unauthenticated attacker to force the site to regenerate these pages, potentially disrupting site structure or cluttering the database.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php(or any admin URL, butadmin-ajax.phpis the standard unauthenticated entry point). - HTTP Method: GET
- Parameters:
restropress-install-pages=install(inferred) - Authentication: None required.
- Preconditions: The RestroPress plugin must be active.
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user sends a GET request to
http://target/wp-admin/admin-ajax.php?restropress-install-pages=install. - WordPress Loading: WordPress processes the request. Since it's directed at an admin file, it triggers the
admin_inithook. - Hook Execution: The RestroPress plugin has registered a handler in
includes/admin/admin-actions.php:add_action( 'admin_init', 'restropress_install_pages' ); - Vulnerable Logic: The
restropress_install_pages()function checks the global$_GETarray:function restropress_install_pages() { if ( ! empty( $_GET['restropress-install-pages'] ) && 'install' === $_GET['restropress-install-pages'] ) { // VULNERABILITY: No current_user_can() check here // VULNERABILITY: No check_admin_referer() check here rp_install_pages(); // Calls the installer function wp_safe_redirect( admin_url( 'admin.php?page=restropress-settings' ) ); exit; } } - Sink: The
rp_install_pages()function (likely inincludes/rp-install.php) executes, usingwp_insert_post()to create multiple pages.
4. Nonce Acquisition Strategy
This specific attack vector (exploiting admin_init via a direct GET parameter) typically does not require a nonce because the vulnerable code fails to implement check_admin_referer().
However, if testing other AJAX-based functions in RestroPress (e.g., wp_ajax_nopriv_restropress_update_cart), use the following strategy:
- Identify Script Localization: RestroPress localizes scripts using the handle
restropress-scriptsorrp-ajax-scripts. - Shortcode Page: Create a page with the main RestroPress shortcode to ensure scripts are loaded:
wp post create --post_type=page --post_status=publish --post_title="Store" --post_content='[restropress_items]' - Browser Extraction:
- Navigate to the newly created page.
- Use
browser_evalto extract the nonce:browser_eval("window.restropress_vars?.nonce")orbrowser_eval("window.rp_ajax_vars?.nonce").
5. Exploitation Strategy
- Baseline Check: Check the existing pages to confirm the "Checkout" and "Order Confirmation" pages either don't exist or note their current IDs.
- Trigger Action: Send a GET request to the
admin-ajax.phpendpoint with the installation trigger. - Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php?restropress-install-pages=install - Method:
GET - Content-Type:
application/x-www-form-urlencoded
- URL:
- Observe Response: The server will likely return a
302 Redirectto the login page (becausewp_safe_redirectis called, but the user is not logged in) or theadmin-ajax.phpdefault response0. Regardless of the response body, the function logic will have executed before the redirect.
6. Test Data Setup
- Plugin Installation: Ensure RestroPress <= 3.2.7 is installed and activated.
- Clean State: (Optional) Delete any existing pages with titles "Checkout", "Order History", or "Order Confirmation" to make the exploit obvious.
wp post delete $(wp post list --post_type=page --title="Checkout" --field=ID) --force
7. Expected Results
- The request should successfully trigger the
rp_install_pages()function. - New pages will be created in the WordPress database.
- The attacker achieves "Unauthorized Action" (Integrity impact) by modifying the site's page structure.
8. Verification Steps
- Database Check: Use WP-CLI to list pages and look for the newly created RestroPress pages.
wp post list --post_type=page --post_status=publish - Count Verification: Verify that the number of pages has increased.
wp post list --post_type=page --count - Log Check: If possible, check the WordPress debug log (if
WP_DEBUGis on) for any output from the installation process.
9. Alternative Approaches
If restropress-install-pages is not the correct parameter, check for other admin_init triggers in the codebase:
- Alternative Parameter 1:
?rp_notice_dismiss=some_notice_id(Triggeringrestropress_dismiss_notice) - Alternative Parameter 2:
?restropress-action=remove_data(Check for data cleanup functions) - AJAX Endpoint: If the vulnerability is in an AJAX handler, use
POST /wp-admin/admin-ajax.phpwithaction=restropress_....- Common missing auth AJAX candidate:
restropress_update_order_statusorrestropress_save_customer_note. - These would require a nonce, which can be extracted from the frontend as described in Section 4.
- Common missing auth AJAX candidate:
Summary
The RestroPress plugin for WordPress is vulnerable to unauthorized page creation due to a missing capability check in its administrative initialization logic. An unauthenticated attacker can trigger the re-installation of default plugin pages (such as Checkout and Order History) by sending a crafted GET request, potentially leading to database clutter and disruption of the site's structure.
Vulnerable Code
// File: includes/admin/admin-actions.php add_action( 'admin_init', 'restropress_install_pages' ); /** * Install RestroPress pages */ function restropress_install_pages() { if ( ! empty( $_GET['restropress-install-pages'] ) && 'install' === $_GET['restropress-install-pages'] ) { // VULNERABILITY: No current_user_can() check // VULNERABILITY: No check_admin_referer() check rp_install_pages(); wp_safe_redirect( admin_url( 'admin.php?page=restropress-settings' ) ); exit; } }
Security Fix
@@ -3,6 +3,11 @@ */ function restropress_install_pages() { if ( ! empty( $_GET['restropress-install-pages'] ) && 'install' === $_GET['restropress-install-pages'] ) { + + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + rp_install_pages(); wp_safe_redirect( admin_url( 'admin.php?page=restropress-settings' ) ); exit;
Exploit Outline
The exploit leverages the fact that the 'admin_init' hook is triggered during requests to administrative endpoints, even by unauthenticated users. 1. Target Endpoint: The attacker targets the /wp-admin/admin-ajax.php endpoint via a GET request. 2. Payload: The request includes the parameter `restropress-install-pages=install` in the query string. 3. Authentication: No authentication or nonces are required for this request to trigger the vulnerable function. 4. Execution Flow: The plugin's `restropress_install_pages` function, hooked to `admin_init`, detects the GET parameter and immediately executes `rp_install_pages()`. This results in the creation of several new WordPress pages (Checkout, Order Confirmation, Order History, etc.) in the database, regardless of the attacker's privilege level.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.