Store Locator WordPress < 1.6.6 - Authenticated (Administrator+) Stored Cross-Site Scripting
Description
The Store Locator WordPress plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to 1.6.6 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:NTechnical Details
<1.6.6What Changed in the Fix
Changes introduced in v1.6.6
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-9060 ## 1. Vulnerability Summary The **Store Locator WordPress (agile-store-locator)** plugin is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)** in versions up to 1.6.6. The vulnerability exists in the `save_setting` method within `includes/…
Show full research plan
Exploitation Research Plan - CVE-2026-9060
1. Vulnerability Summary
The Store Locator WordPress (agile-store-locator) plugin is vulnerable to Authenticated Stored Cross-Site Scripting (XSS) in versions up to 1.6.6. The vulnerability exists in the save_setting method within includes/admin/setting.php, which handles the saving of plugin configurations.
User input from $_POST['data'] and $_POST['map_style'] is processed using stripslashes_deep or stripslashes but is not passed through WordPress sanitization functions (like sanitize_text_field or wp_kses). These values are stored directly in the database (asl_configs table and asl_settings table). When these settings are later retrieved and rendered on the frontend (via wp_localize_script or direct output in templates), the injected scripts execute.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
asl_save_setting(Inferred from the method namesave_settinginSettingclass) - Vulnerable Parameters:
map_style: Stored and rendered as part of the Google Maps initialization.data[api_key]: Stored and rendered in admin and frontend contexts.slug_attr_ddl: Processed viaHelper::set_setting.
- Authentication Level: Administrator (or users with the
administratorcapability as defined by theASL_PERMISSIONconstant). - Preconditions:
- The attacker must have Administrator-level access.
- The vulnerability is particularly relevant in Multisite environments or environments where
unfiltered_htmlhas been disabled for Administrators.
3. Code Flow
- Entry Point: An authenticated administrator sends a POST request to
admin-ajax.phpwith the actionasl_save_setting. - Processing: The request is routed to
AgileStoreLocator\Admin\Setting::save_setting(). - Sink (Input):
- In
includes/admin/setting.php, the function retrieves$_POST['data']and$_POST['map_style']. - It uses
stripslashes_deep($_POST['data'])andstripslashes($_POST['map_style']). - It performs a loop:
foreach ($keys as $key) { $wpdb->update(ASL_PREFIX . 'configs', ['value' => $data_[$key]], ['key' => $key]); }. - It calls
\AgileStoreLocator\Helper::set_setting(...)formap_style.
- In
- Storage: The unsanitized payload is stored in the
wp_asl_configstable (or similar prefix). - Output (Frontend):
includes/frontend/app.phpcallsget_public_config(), which executesSELECT * FROM ... ASL_PREFIX configs.- The configuration is passed to the frontend via
wp_localize_scriptunder the object nameasl_configs. - Alternatively,
map_stylemay be rendered raw within a<script>block to initialize the map.
4. Nonce Acquisition Strategy
The plugin uses the asl_admin_conf JavaScript object to store configuration data and nonces in the admin interface.
- Navigate: Move the browser to the Store Locator settings page:
/wp-admin/admin.php?page=asl-settings. - Extract: Use
browser_evalto retrieve the nonce from the localized script:window.asl_admin_conf?.asl_nonce - Action String: The nonce is likely generated with the action
asl_nonceor similar, used to authorize theasl_save_settingAJAX call.
5. Exploitation Strategy
Step 1: Authentication and Nonce Extraction
- Authenticate as an Administrator.
- Navigate to
/wp-admin/admin.php?page=asl-settings. - Execute
browser_eval("asl_admin_conf.asl_nonce")to get the nonce.
Step 2: Inject Stored XSS Payload
- Method: POST
- URL:
http://[target]/wp-admin/admin-ajax.php - Content-Type:
application/x-www-form-urlencoded - Payload (injecting into
map_style):
Note: Theaction=asl_save_setting &asl_nonce=[EXTRACTED_NONCE] &map_style=[]});alert(document.domain);// &data[api_key]=AIzaSy... (a valid-looking key) &data[default_lat]=0 &data[default_lng]=0map_styleis often injected into a JS object. The]});part of the payload is designed to break out of the JSON/Array structure in the resulting frontend script.
Step 3: Trigger Execution
- Create or view a page containing the shortcode
[ASL_STORELOCATOR]. - The script will execute when the Google Map attempts to load the custom style.
6. Test Data Setup
- Install and activate Agile Store Locator version 1.6.5.
- Create a WordPress Page with the following content:
[ASL_STORELOCATOR] - Ensure the user used for the exploit has the
administratorrole. - (Optional) If testing for the
unfiltered_htmlbypass specifically, definedefine( 'DISALLOW_UNFILTERED_HTML', true );inwp-config.php.
7. Expected Results
- The
admin-ajax.phpresponse should return{"success":true,"msg":"Setting has been updated successfully."}. - When visiting the page with the
[ASL_STORELOCATOR]shortcode, a JavaScriptalert(document.domain)(or similar payload) should trigger. - Checking the database will show the payload in the
valuecolumn of theasl_configstable wherekey = 'map_style'.
8. Verification Steps
- Verify Storage via WP-CLI:
Check if the output contains the rawwp db query "SELECT value FROM wp_asl_configs WHERE \`key\` = 'map_style';"<script>or breakout payload. - Verify Frontend Render:
Usehttp_requestto fetch the frontend page and grep for the payload:# Search for the breakout in the localized JS grep "alert(document.domain)"
9. Alternative Approaches
If map_style is not rendered directly, target data[api_key]:
- Inject
<img src=x onerror=alert(1)>intodata[api_key]. - Check the Admin Settings page itself (
/wp-admin/admin.php?page=asl-settings). If theapi_keyinput field value is rendered as<input value="<img src=x onerror=alert(1)>" ...>, the XSS will trigger in the admin context when the administrator revisits the settings page.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.