Request a Quote <= 2.5.3 - Missing Authorization
Description
The Request a Quote Form Plugin – Price Quote Request Management Made Easy plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.5.3. This makes it possible for authenticated attackers, with Subscriber-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
<=2.5.3Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-64248 ## 1. Vulnerability Summary The **Request a Quote Form Plugin** (versions <= 2.5.3) is vulnerable to **Missing Authorization**. While the plugin correctly implements CSRF protection via nonces in its AJAX handlers, it fails to perform a capability check…
Show full research plan
Exploitation Research Plan - CVE-2025-64248
1. Vulnerability Summary
The Request a Quote Form Plugin (versions <= 2.5.3) is vulnerable to Missing Authorization. While the plugin correctly implements CSRF protection via nonces in its AJAX handlers, it fails to perform a capability check (e.g., current_user_can( 'manage_options' )) to ensure the request is originating from an authorized administrator. This allows any authenticated user (starting from the Subscriber role) to perform administrative actions, specifically deleting quote requests.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
raq_delete_quote(inferred from plugin naming convention and standard AJAX registration) - Parameters:
action:raq_delete_quotesecurity: A valid nonce (action:raq_nonce)id: The ID of the quote request to delete
- Authentication: Required (Subscriber role or higher).
- Preconditions: At least one quote request must exist in the system to be deleted.
3. Code Flow
- Entry Point: The plugin registers AJAX actions in its admin class (likely
includes/admin/class-request-quote-admin.phporadmin/class-request-a-quote-admin.php). - Hook Registration:
add_action( 'wp_ajax_raq_delete_quote', array( $this, 'raq_delete_quote_callback' ) ); - Vulnerable Function: The callback function (e.g.,
raq_delete_quote_callback) is invoked. - Nonce Verification: The function calls
check_ajax_referer( 'raq_nonce', 'security' ). This passes if the user is logged in and provides a valid nonce. - Missing Check: The function proceeds to perform database operations (e.g.,
$wpdb->delete) without checking if the current user has themanage_optionscapability. - Sink: The quote record corresponding to the provided
idis deleted from the database.
4. Nonce Acquisition Strategy
The plugin uses wp_localize_script to pass the nonce to the admin dashboard. Even if a Subscriber cannot access the plugin's settings page, the script is often enqueued for all admin pages or the dashboard.
- Shortcode/Page Requirement: The plugin handles quote submissions via a frontend shortcode (e.g.,
[request_a_quote]). However, the deletion nonce is intended for the admin side. - Detection: Check if the script is enqueued on
wp-admin/index.phpfor a Subscriber. - Execution Agent Steps:
- Log in as a Subscriber.
- Navigate to
/wp-admin/index.php. - Use
browser_evalto extract the nonce:window.raq_ajax_obj?.raq_nonce || window.raq_data?.nonce - (Alternative) Search the page source for
raq_nonce.
5. Exploitation Strategy
Step 1: Create Test Data
As an unauthenticated user (or via the admin if easier for setup), submit a quote request to ensure the database is populated.
Step 2: Login as Subscriber
Use the http_request tool to authenticate as a Subscriber user.
Step 3: Obtain Nonce and ID
Navigate to the WordPress dashboard as the Subscriber and extract the security token (nonce) and identify a target quote ID.
Step 4: Execute Deletion
Perform an unauthenticated-authorized POST request to admin-ajax.php.
Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Content-Type:
application/x-www-form-urlencoded - Body:
action=raq_delete_quote&security=[NONCE]&id=[QUOTE_ID]
6. Test Data Setup
- Create Administrator: Ensure an admin user exists.
- Create Subscriber: Create a user with the
subscriberrole. - Plugin Setup: Activate the plugin.
- Create Quote:
- Create a page with the shortcode
[request-a-quote-form](verify exact shortcode viagrep -r "add_shortcode" .). - Visit the page and submit a test quote request.
- Create a page with the shortcode
- Identify ID: Use
wp db query "SELECT id FROM wp_raq_quotes LIMIT 1;"to find the ID of the quote to delete.
7. Expected Results
- Response: The AJAX handler should return a success status (e.g.,
1or a JSON{"success":true}). - Database State: The row in the quote table (likely
wp_raq_quotesor similar) associated with theidshould be removed. - Unauthorized Bypass: The action succeeds despite the user being a Subscriber, whereas it should require Admin permissions.
8. Verification Steps
- Check Database:
If the count iswp db query "SELECT COUNT(*) FROM wp_raq_quotes WHERE id = [ID];"0, the exploit was successful. - Verify Role: Confirm the user used for the request has only the
subscriberrole:wp user get [USER_ID] --field=roles
9. Alternative Approaches
- Bulk Delete: Check for a bulk delete action (e.g.,
raq_bulk_delete) which might also lack authorization checks. - Quote Status Update: If deletion is not possible, check for an action like
raq_update_statusthat allows a Subscriber to change quote statuses (e.g., marking a quote as "Approved"). - Parameter Fuzzing: If the ID is not easily guessable, the agent should attempt to iterate through small integers if the response differs between "ID not found" and "Success".
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.