Location Weather <= 3.0.2 - Missing Authorization to Authenticated (Contributor+) Block Settings Modification and Cache Purging
Description
The Location Weather plugin for WordPress is vulnerable to unauthorized modification of data due to missing capability checks on the `splw_update_block_options()` and `lwp_clean_weather_transients()` functions in all versions up to, and including, 3.0.2. This makes it possible for authenticated attackers, with Contributor-level access and above, to disable all weather blocks and purge all weather cache transients. The nonce required for these actions is exposed to all authenticated users via `wp_localize_script()` on the `init` hook.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=3.0.2What Changed in the Fix
Changes introduced in v3.0.3
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-7249 - Location Weather Missing Authorization ## 1. Vulnerability Summary The **Location Weather** plugin (versions <= 3.0.2) contains a missing authorization vulnerability in two AJAX functions: `splw_update_block_options()` and `lwp_clean_weather_transients(…
Show full research plan
Exploitation Research Plan: CVE-2026-7249 - Location Weather Missing Authorization
1. Vulnerability Summary
The Location Weather plugin (versions <= 3.0.2) contains a missing authorization vulnerability in two AJAX functions: splw_update_block_options() and lwp_clean_weather_transients(). Both functions are registered via wp_ajax_ hooks in the ShapedPlugin\Weather\Admin\AdminDashboard\Splw_Blocks_Page_Wrapper class.
While these functions perform nonce verification, they fail to implement current_user_can() checks. Consequently, any authenticated user with Contributor-level permissions or higher—who can access the WordPress Block Editor—can obtain the necessary nonce and invoke these actions to modify global plugin settings (disabling blocks) or purge cached weather data.
2. Attack Vector Analysis
- Endpoints:
/wp-admin/admin-ajax.php - AJAX Actions:
splw_update_block_options(for setting modification)lwp_clean_weather_transients(for cache purging)
- Required Parameters:
action:splw_update_block_optionsorlwp_clean_weather_transientsnonce: A valid nonce for the actionsplw_block_api_nonceoptions: (Forsplw_update_block_options) An array or JSON object containing the block settings to modify.
- Authentication: Authenticated (Contributor+).
- Preconditions: The attacker must be able to load a page where the plugin enqueues its block editor scripts to retrieve the nonce.
3. Code Flow
- Entry Point: The constructor of
Splw_Blocks_Page_Wrapperregisters the hooks:add_action( 'wp_ajax_splw_update_block_options', array( $this, 'splw_update_block_options' ) );add_action( 'wp_ajax_lwp_clean_weather_transients', array( $this, 'lwp_clean_weather_transients' ) );
- Nonce Exposure: In
includes/Blocks/Blocks.php, thesplw_scripts_enqueue()function (hooked toenqueue_block_assets) callswp_localize_script():wp_localize_script( 'spl_weather_editor_js', 'splWeatherBlockLocalize', array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'blockApiNonce' => wp_create_nonce( 'splw_block_api_nonce' ), 'blockOptions' => get_option( 'splw_blocks_visibility_options' ), // ... ) ); - Execution Path:
- The user sends an AJAX request with
action=splw_update_block_options. - The function (in
Splw_Blocks_Page_Wrapper.php) callscheck_ajax_referer( 'splw_block_api_nonce', 'nonce' ). - It proceeds to call
update_option( 'splw_blocks_visibility_options', ... )using user-supplied data without verifying the user hasmanage_optionsor thelocation_weather_access_capability.
- The user sends an AJAX request with
4. Nonce Acquisition Strategy
The nonce is localized specifically for the block editor environment. Since Contributors can create/edit posts, they can load the Gutenberg editor.
- Access Editor: Navigate to the "Add New Post" page (
/wp-admin/post-new.php). - Locate Script: The plugin enqueues
spl_weather_editor_js. - Extract Variable: Use
browser_evalto extract the nonce from thesplWeatherBlockLocalizeglobal object.- Target Variable:
window.splWeatherBlockLocalize.blockApiNonce
- Target Variable:
5. Exploitation Strategy
Phase 1: Disable All Weather Blocks
- Authenticate as a Contributor user.
- Retrieve Nonce:
- Navigate to
wp-admin/post-new.php. - Extract nonce:
browser_eval("window.splWeatherBlockLocalize?.blockApiNonce").
- Navigate to
- Send Malicious Update:
- URL:
http://[target]/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body:
(Note: Parameter names foraction=splw_update_block_options&nonce=[NONCE]&options[location_weather_block]=false&options[weather_forecast_block]=falseoptionsare inferred based on standard plugin patterns; if the request expects JSON, the payload should be adjusted accordingly.)
- URL:
Phase 2: Purge Weather Transients
- Send Purge Request:
- URL:
http://[target]/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body:
action=lwp_clean_weather_transients&nonce=[NONCE]
- URL:
6. Test Data Setup
- Plugin Configuration: Install "Location Weather" 3.0.2. Ensure at least one weather block visibility option is currently
true. - User Creation: Create a user with the
contributorrole. - Cache Generation: Populate some transients by viewing a weather block on the frontend.
- Run
wp transient set sp_open_weather_test "cache_data" 3600.
- Run
7. Expected Results
- Block Modification: The HTTP response should be a success (likely
wp_send_json_successor1). The WordPress optionsplw_blocks_visibility_optionswill be updated with the provided (disabled) values. - Cache Purge: The HTTP response should be a success. Database queries will execute to delete transients matching
_transient_sp_open_weather_%.
8. Verification Steps
- Check Options:
wp option get splw_blocks_visibility_options- Verify that the values now reflect the "false" settings sent in the exploit.
- Check Transients:
wp db query "SELECT * FROM wp_options WHERE option_name LIKE '%_transient_sp_open_weather_%'"- Verify that the result set is empty.
9. Alternative Approaches
- Setting Modification via JSON: If the function uses
json_decodeon$_POST['options'], the request should be changed to:action=splw_update_block_options&nonce=[NONCE]&options={"location_weather_block":false} - Common Option Key: If the
optionsparameter is not used, check forsplw_update_setting_options(also registered in the source) which may allow broader configuration changes. - Nonce Discovery: If
post-new.phpdoesn't load the script, trywp-admin/edit.php?post_type=location_weather&page=splw_admin_dashboardif the Contributor has been granted filtered access to that page.
Summary
The Location Weather plugin for WordPress is vulnerable to unauthorized modification of data and cache purging due to missing capability checks on several AJAX functions, including splw_update_block_options and lwp_clean_weather_transients. Authenticated attackers with Contributor-level permissions or higher can obtain a required nonce via the Block Editor and use it to disable plugin features or flush weather transients.
Vulnerable Code
// includes/Admin/AdminDashboard/Splw_Blocks_Page_Wrapper.php L255 public function splw_update_block_options() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; if ( ! wp_verify_nonce( $nonce, 'splw_block_api_nonce' ) ) { wp_send_json_error( __( 'Invalid nonce.', 'location-weather' ) ); } $options = isset( $_POST['options'] ) ? (array) $_POST['options'] : array(); if ( ! empty( $options ) ) { update_option( 'splw_blocks_visibility_options', $options ); } wp_send_json_success(); } --- // includes/Admin/AdminDashboard/Splw_Blocks_Page_Wrapper.php L330 public function lwp_clean_weather_transients() { $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; if ( ! wp_verify_nonce( $nonce, 'splw_block_api_nonce' ) ) { wp_send_json_error( __( 'Invalid nonce.', 'location-weather' ) ); } // ... (logic to delete transients via $wpdb query) } --- // includes/Blocks/Blocks.php L154 wp_localize_script( 'spl_weather_editor_js', 'splWeatherBlockLocalize', array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'blockApiNonce' => wp_create_nonce( 'splw_block_api_nonce' ), 'pluginUrl' => LOCATION_WEATHER_URL, 'blockOptions' => get_option( 'splw_blocks_visibility_options' ), 'weather_api_info' => $weather_api_info, ) );
Security Fix
@@ -253,6 +253,9 @@ * Handle AJAX request to update block settings. */ public function splw_update_block_options() { + // Check user capabilities, current_user_can() is called internally. + location_weather_verify_capability(); + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; if ( ! wp_verify_nonce( $nonce, 'splw_admin_settings_nonce' ) ) { wp_send_json_error( __( 'Invalid nonce.', 'location-weather' ) ); @@ -328,6 +329,9 @@ * It performs nonce verification to ensure the request is legitimate. */ public function lwp_clean_weather_transients() { + // Check user capabilities, current_user_can() is called internally. + location_weather_verify_capability(); + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; if ( ! wp_verify_nonce( $nonce, 'splw_admin_settings_nonce' ) ) { wp_send_json_error( __( 'Invalid nonce.', 'location-weather' ) ); @@ -12,8 +12,18 @@ /** * Plugin dashboard access capability. * - * @return manage_options + * @return string */ function location_weather_dashboard_capability() { return apply_filters( 'location_weather_access_capability', 'manage_options' ); } + +/** + * Verifies the current user has the required capability for admin AJAX actions. + * Sends a 403 JSON error and halts execution if the check fails. + */ +function location_weather_verify_capability() { + if ( ! current_user_can( location_weather_dashboard_capability() ) ) { + wp_send_json_error( __( 'Unauthorized access.', 'location-weather' ), 403 ); + } +}
Exploit Outline
The exploit requires an authenticated user with at least Contributor-level access. 1. Login to the WordPress admin panel and navigate to a page that initializes the Gutenberg block editor (e.g., /wp-admin/post-new.php). 2. Extract the nonce from the global JavaScript object `splWeatherBlockLocalize.blockApiNonce`, which is enqueued for all users who can access the block editor. 3. Send a POST request to `/wp-admin/admin-ajax.php` with the action `splw_update_block_options`, the extracted nonce, and an `options` array parameter containing weather block visibility flags set to `false`. This disables the weather blocks site-wide. 4. Alternatively, send a POST request with the action `lwp_clean_weather_transients` and the nonce to flush the plugin's weather data cache.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.