| Plugin Name | OwnID Passwordless Login |
|---|---|
| Type of Vulnerability | Authentication bypass |
| CVE Number | CVE-2025-10294 |
| Urgency | Critical |
| CVE Publish Date | 2025-10-15 |
| Source URL | CVE-2025-10294 |
Urgent: OwnID Passwordless Login (<= 1.3.4) — Authentication Bypass (CVE-2025-10294)
Advisory and mitigation guidance — published 15 October 2025. Written from the perspective of a Hong Kong security expert: direct, practical, and focused on containment and recovery.
Affected versions: OwnID Passwordless Login plugin ≤ 1.3.4.
Fix status: No official vendor patch available at time of advisory.
Executive summary
- CVE-2025-10294 is an authentication bypass in OwnID Passwordless Login (≤ 1.3.4).
- Exploitable by unauthenticated attackers — no prior access required.
- Impact: impersonation of users (including administrators), full site takeover, persistent backdoors, data theft.
- No vendor patch available at the time of publication — immediate mitigations are required.
- Primary actions: disable the plugin or block its endpoints, apply virtual patches or server rules, rotate auth salts and sensitive credentials, audit accounts and files, and restore from clean backups if compromise is detected.
What is the issue (technical, simplified)
Passwordless login flows rely on careful server-side validation of authentication proofs (magic links, WebAuthn responses, signed callbacks). The vulnerability here is a logic/validation failure in OwnID’s authentication callback handlers: certain endpoints or code paths do not sufficiently verify the proof before creating a WordPress session. As a result, crafted requests can be accepted as legitimate and cause WordPress to treat the requester as the targeted user.
Key attributes:
- Attacker privilege: unauthenticated.
- Attack vector: HTTP requests to plugin REST/AJAX/callback endpoints.
- Impact: full account impersonation, potential administrator takeover, site compromise.
How attackers are likely to exploit this
- Discover sites running the vulnerable plugin via scanning for plugin assets, known REST namespaces, or characteristic headers.
- Probe OwnID-related endpoints to determine behavior.
- Send crafted payloads that trigger the flawed validation logic, causing session creation or cookie setting for a target user (often an administrator).
- Use access to create admin accounts, upload webshells, modify content, and exfiltrate data.
Exploitation is straightforward to automate; mass scanning and exploitation can result in rapid, widespread compromises.
Immediate risk to your site
If your public-facing WordPress site runs OwnID Passwordless Login ≤ 1.3.4, assume high risk. Automated attackers will target admin accounts first. Do not wait for an official plugin update — act now.
Detection — signs your site may already be compromised
Check these indicators immediately:
- New administrator accounts in the database. Example query:
SELECT ID, user_login, user_email, user_registered FROM wp_users WHERE ID IN ( SELECT user_id FROM wp_usermeta WHERE meta_key = 'wp_capabilities' AND meta_value LIKE '%administrator%' ) ORDER BY user_registered DESC; - Webserver logs showing repeated POSTs to ownid-related REST/AJAX endpoints or unusual query strings containing “ownid”, “passwordless”, “magic-link”, etc.
- Session or authorization cookies being set after requests to plugin endpoints.
- Unexpected modifications to wp_options, wp_posts, plugin or theme files.
- PHP files in uploads or other non-code directories.
- Outbound connections initiated by PHP processes to unfamiliar domains.
- Unexpected scheduled cron jobs in wp_options.
If you observe any of the above, treat the site as potentially compromised and proceed to containment and forensic steps urgently.
Immediate containment steps (prioritized)
- Disable the plugin immediately.
- If you have WP Admin access: deactivate OwnID Passwordless Login via the Plugins screen.
- If WP Admin is unavailable: rename or remove the plugin folder via SFTP/SSH (e.g., rename
wp-content/plugins/ownidtoownid.disabled), which prevents the vulnerable code from running.
- Block plugin endpoints at webserver level or via WAF.
If you cannot disable the plugin for availability reasons, immediately block HTTP access to the plugin’s REST/AJAX/callback endpoints. See rule examples below.
- Rotate authentication salts and keys.
Generate new AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY and NONCE_KEY values in
wp-config.php(use the WordPress.org secret-key generator). This invalidates existing cookies and forces re-authentication. - Force password reset and rotate critical credentials.
- Reset passwords for all administrator accounts.
- Rotate service credentials, API keys and OAuth tokens stored on the server.
- Audit and remove unknown accounts. Carefully review all user accounts and remove unauthorized administrators. Record user IDs and related artifacts for investigation.
- Scan for malware and backdoors. Use a file-integrity scanner and a reputable malware scanner to find modified core/plugin/theme files and PHP files in uploads.
- Take forensic snapshots. Where possible, snapshot filesystem and database before making destructive changes. If immediate action is required, prioritise containment and make notes of timestamps and logs for later analysis.
- If compromise is confirmed — restore from a clean backup. Restore from a backup taken before the compromise. After restore, re-apply containment steps and rotate secrets.
- Notify your host and increase logging. Enable verbose access logs and process monitoring. Inform your hosting provider so they can assist with blocking offending IPs and network-level containment.
Recommended virtual-patch / WAF rules (apply now)
Virtual patching (blocking vulnerable endpoints at the edge) is the fastest mitigation until an official plugin fix is released. Test rules in staging first to avoid breaking legitimate traffic.
Example Nginx rule to block the OwnID REST namespace:
# Deny requests to the OwnID REST namespace
location ~* ^/wp-json/(ownid|ownid-.*) {
return 403;
}
Example Apache/.htaccess rule:
# Block OwnID REST endpoints
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/wp-json/(ownid|ownid-.*) [NC]
RewriteRule .* - [F]
</IfModule>
Example ModSecurity (SecRule) snippet:
SecRule REQUEST_URI "@rx ^/wp-json/(ownid|ownid-.*)"
"id:1009001,phase:1,deny,status:403,log,msg:'Block OwnID REST endpoints (virtual patch) - authentication bypass mitigation' "
Block known AJAX actions (if plugin uses admin-ajax.php action parameters):
# Example: block admin-ajax requests that contain ownid actions
if ($request_method = POST) {
set $block_ajax 0;
if ($request_uri ~* "admin-ajax.php") {
if ($request_body ~* "(action=.*ownid|ownid_auth|ownid_callback)") {
set $block_ajax 1;
}
}
if ($block_ajax = 1) {
return 403;
}
}
Other protective measures to implement at the edge or server level:
- Rate-limit requests to plugin-specific endpoints and to admin login paths.
- Block requests that lack expected nonce or signature headers.
- Restrict POST access to plugin endpoints to known IP ranges where applicable.
- Deny requests with suspicious payloads (blank tokens, oversized parameters, or patterns consistent with exploit attempts).
- Monitor and alert on spikes in requests to ownid/passwordless-related paths.
Practical server-level countermeasures (quick rules you can add now)
- Restrict access to
wp-login.phpand/wp-adminby IP where feasible. - Add a webserver rule to deny requests containing strings related to the plugin’s REST namespace (ownid, passwordless, etc.).
- Temporarily disable unauthenticated REST API access using a lightweight mu-plugin that denies requests to suspected endpoints (test carefully to avoid breaking legitimate API consumers).
Example mu-plugin to block common ownid REST calls (temporary stop-gap):
<?php
// mu-plugin/block-ownid-rest.php
add_filter( 'rest_request_dispatch', function($result, $server, $request) {
$route = $request->get_route();
if (preg_match('#^/ownid#', $route) || preg_match('#ownid#', $route)) {
return new WP_Error('rest_forbidden', 'Forbidden', ['status' => 403]);
}
return $result;
}, 10, 3);
Note: test any mu-plugin in staging before production. Remove the mu-plugin once the official plugin is patched and you have validated behavior.
How to validate your site is clean (post-containment)
After disabling the plugin and applying edge/server blocks, run these checks:
- Search for unknown admin accounts and remove them.
- Confirm
wp-config.phpsalts/keys have been updated. - Scan filesystem for recently changed files (use
findwith appropriate-mtimeparameters). - Find PHP files in uploads:
find wp-content/uploads -type f -name "*.php" - Check for unexpected scheduled tasks (inspect WP Admin cron UI or
wp_optionscron entry). - Inspect database for suspicious options, rogue widgets, or injected content.
- Review webserver logs for continued POSTs or unusual user agents tied to ownid endpoints.
- Re-scan with a trusted malware scanner and run file integrity checks.
If you find backdoors or evidence of persistence, restoring from a known-clean backup is the most reliable recovery approach. After restoration, re-apply containment and rotate all secrets.
Recovery steps and long-term hardening
- Restore from a clean backup if compromise is confirmed.
- Immediately keep the vulnerable plugin disabled after recovery until a vendor patch is available and verified.
- Rotate all credentials and generate new auth salts in
wp-config.php. - Require two-factor authentication (2FA) for all administrator accounts.
- Enforce least-privilege admin policies and limit number of admin accounts.
- Enable file change monitoring and regular malware scans.
- Use automated offsite backups and validate backup integrity regularly.
- Monitor logs and user activity for at least 30 days post-incident for signs of re-infection.
Developer guidance (for plugin/theme authors and integrators)
- Always validate authentication proofs server-side; do not trust client-side assertions.
- Validate digital signatures, nonces, CSRF tokens and timestamps strictly.
- Ensure authentication cookies are only set after full cryptographic verification.
- Minimize custom endpoints that can set authentication state; where possible, reuse WordPress core login flows.
- Add comprehensive logging for authentication flows and rate-limit endpoints that can be abused.
Indicators of compromise checklist (quick scan)
- Unexpected admin-level users created within the last 30 days.
- Recent modification timestamps on active theme/plugin files you did not expect.
- PHP files in
wp-content/uploadsor other non-code directories. - Outbound network connections from PHP processes to unknown hosts.
- New scheduled cron jobs you did not configure.
- Spikes in requests to REST API endpoints matching ownid-related paths.
Final prioritized checklist
- If OwnID Passwordless Login is installed: disable or remove it immediately.
- If you cannot disable it: block its REST/AJAX endpoints via webserver or edge rules.
- Rotate WordPress keys/salts in
wp-config.phpto invalidate sessions. - Force password resets for administrators and rotate critical credentials.
- Audit users, plugins, themes and core files for tampering.
- Scan and, if necessary, restore from a known-clean backup.
- Deploy edge/server rules and enable continuous monitoring and file integrity checks.
- Harden admin access: 2FA, least privilege, routine backups and monitoring.
Closing thoughts
Authentication bypasses in plugins that rework login flows are among the most severe risks for WordPress sites — they convert authentication code into a direct access vector. In the current threat climate, rapid containment (disable or block) and forensic validation are essential. Prioritise high-value sites (eCommerce, high traffic) first. When in doubt, assume compromise and follow containment, cleanup, and recovery procedures.
If you require assistance implementing the containment steps above, engage incident response resources or your hosting provider for network-level blocks and forensic support.