Unpatched Privilege Escalation in Service Finder Bookings Plugin

Published 3 September 2025
Table of Contents

This blog post is about an unauthenticated Privilege Escalation vulnerability in the Service Finder Bookings plugin. If you're a Service Finder Bookings plugin user, since there is currently no available patch, we recommend deactivating and deleting the plugin.

The vulnerabilities mentioned here were discovered and reported by Patchstack Alliance community member Bonds.

✌️ Our users are protected from this vulnerability. Are yours?

Web developers

Mitigate vulnerabilities in real-time without changing code.

See pricing
Plugin developers

Identify vulnerabilities in your plugins and get recommendations for fixes.

Request audit
Hosting companies

Protect your users, improve server health and earn additional revenue.

Patchstack for hosts

About the Service Finder Bookings plugin

The plugin is a required plugin pre-packaged from the premium Service Finder theme, which has over 6,000 sales. The theme is a directory and job board WordPress theme, and the plugin itself handles all of the related booking process for the service finder.

The security vulnerability

In versions 6.1 (latest) and below, the plugin is vulnerable to a Privilege Escalation, which allows any unauthenticated attacker to escalate their privilege to administrator or even log in as any user on the site. The vulnerability doesn't have a patched version for now and is tracked with CVE-2025-23970.

First, let's take a look at the service_finder_submit_user_form function:

function service_finder_submit_user_form(){
	if (isset($_GET['switch_user']) && is_numeric($_GET['switch_user'])) {
		$user_id = intval(sanitize_text_field($_GET['switch_user']));
		service_finder_switch_user($user_id);
	}
	
	if (isset($_GET['switch_back'])) {
		service_finder_switch_back();
	}
}		
add_action('init', 'service_finder_submit_user_form');	

Since the function is added with an init hook, any unauthenticated users can trigger the function. There are two scenarios, where the user specifies $_GET['switch_user'] or $_GET['switch_back']. Let's first try to check the service_finder_switch_back function:

function service_finder_switch_back() {
    if (isset($_COOKIE['original_user_id'])) {
        $original_user_id = intval($_COOKIE['original_user_id']);
        if (get_userdata($original_user_id)) {
            // Switch back to the original user
            wp_set_current_user($original_user_id);
            wp_set_auth_cookie($original_user_id);
            do_action('wp_login', get_userdata($original_user_id)->user_login, get_userdata($original_user_id));
            
            // Clear the cookie
            setcookie('original_user_id', '', time() - 3600, '/');
            
            // Redirect to the current page or desired URL
            $accounturl = admin_url( 'admin.php?page=candidates' );
            wp_redirect($accounturl);
            exit;
        } else {
            wp_die('Original user not found.');
        }
    } else {
        wp_die('No original user found to switch back to.');
    }
}

In this function, any user can just specify any user ID via $_COOKIE['original_user_id'] value, and he/she can log in as any user, including users with the Administrator role, since the code will set the authentication cookie with the wp_set_auth_cookie function without proper check.

Let's also take a look at the service_finder_switch_user function:

function service_finder_switch_user($user_id) {
	global $current_user;
    if(service_finder_getUserRole($current_user->ID) == "administrator" || service_finder_getUserRole($current_user->ID) == "candidate") {
        if (get_userdata($user_id)) {
            // Store the original user ID in session or a cookie
            setcookie('original_user_id', get_current_user_id(), time() + 3600, '/');
            
            // Switch to the user
            wp_set_current_user($user_id);
            wp_set_auth_cookie($user_id);
            do_action('wp_login', get_userdata($user_id)->user_login, get_userdata($user_id));
            
            // Redirect to the current page or desired URL
			$accounturl = service_finder_get_url_by_shortcode('[service_finder_my_account]');
            wp_redirect($accounturl);
            exit;
        } else {
            wp_die('Invalid user ID.');
        }
    } else {
        wp_die('You do not have permission to switch users.');
    }

The patch

At the time this article was published, we were not aware of a patched version being released.

Conclusion

It is necessary to ensure that there is maximum caution when it comes to handling sessions and authentication cookies. Proper authentication/authorization checks should be implemented whenever user sessions are being assigned.

Want to learn more about finding and fixing vulnerabilities?

Explore our Academy to master the art of finding and patching vulnerabilities within the WordPress ecosystem. Dive deep into detailed guides on various vulnerability types, from discovery tactics for researchers to robust fixes for developers. Join us and contribute to our growing knowledge base.

Timeline

31 May, 2025We received the vulnerability report and notified the vendor.
2 June, 2025We notified the vendor regarding the vulnerability.
3 July, 2025We published the vulnerability entry to the Pachstack database (no response from vendor).
3 September, 2025Security advisory article publicly released.

🤝 You can help us make the Internet a safer place

Plugin developer?

Streamline your disclosure process to fix vulnerabilities faster and comply with CRA.

Get started for free
Hosting company?

Protect your users too! Improve server health and earn added revenue with proactive security.

Patchstack for hosts
Security researcher?

Report vulnerabilities to our gamified bug bounty program to earn monthly cash rewards.

Learn more

The latest in Security Advisories

Looks like your browser is blocking our support chat widget. Turn off adblockers and reload the page.
crossmenu