Hey all! My first post in a long time. While this isn’t a super brainy one, reproducing it was surely fun.
While searching for fun CVEs in Wordpress Plugins, CVE-2023–2834 caught our eye. The plugin Bookit was vulnerable to an Authentication Bypass. As per Patchstack, this was a CVSS 9.8 issue, meaning it was quite impactful! Hence, me and Arpeet Rathi decided to take a look.
Wordpress Bookit Plugin provides the shortcode ‘[bookit]
‘ to embed an appointment booking calendar into your WordPress site. Users can register for a booking appointment by providing the date and time followed by name, email address, and password for registration.
Versions <2.3.6 of Wordpress Bookit Plugin allow unauthenticated attackers to log in as any existing user on the site, even an administrator, only with the added requirement of knowing their email address.
Credits to the original author Lana Codes. Wordfence already has a blog explaining the patch.
Lana Codes also has a detailed writeup on this, that we somehow missed out.
Reviewing the CVE-2023–2384 record, we are able to deduce the following :-
Wordpress itself provides a self-hosted feature at plugins.trac.wordpress.org
to view and track changes in plugin versions allowing us to patch diff easily.
Now, we need two versions, the vulnerable one (2.3.6) and the initial patch (2.3.7) each assigned their revision numbers, 2911433 (2.3.6) and 2919536 (2.3.7) on https://plugins.trac.wordpress.org/log/bookit/
Select the versions to Diff (From 2919536 (2.3.7) To 2911433(2.3.6)) and hit View Changes
The Changeset interface opens displaying an overview of all additions, edits, and deletions made to the included files.
Browsing through the edits made, we arrive at the get_customer function in /includes/classes/CustomerController.php
Going over the previous version’s code (highlighted in green) we are able to deduce that the code first checks if $data contains a `user_id and retrieves the customer’s ID using the Customers::get
method. However, if the user_id
field is not present, it retrieves the customer's ID using the email
parameter, which in-fact is user-supplied.
Now, it retrieves settings using the SettingsController::get_settings()
method. If the booking type here is set to "registered" and the user is not already logged in (!is_user_logged_in()
), the code proceeds to start the authentication process.
It first retrieves the user ID associated with the customer using the Customers::save_or_get_wp_user($data)
method. We already know the user_id
field is user-supplied and can easily be set to the administrator’s email. It now proceeds to clear the Auth Cookie and set the current user to the specified user_id
and then set the Auth Cookie corresponding to the same user_id,
effectively logging the user in.
The /database/Customers.php
responsible for creating the user, if not found in the database.
So, in theory, this application would let us specify an email while booking an appointment and if the email corresponds to a user ID, it switches the authentication from the current user to the one linked with the email, potentially allowing an admin takeover!
(Enough said let’s get to the exploit now!)
We create a sample website and host the Bookit Plugin via the shortcode [bookit]
/wp-admin/admin-ajax.php?action=bookit_book_appointment