An unlocked side door on the office bulletin board — anyone can rewrite the sticky notes, but they can't get into the building
CVE-2026-57339 is a missing authorization flaw (CWE-862) in the Business Directory Plugin – Easy Listing Directories for WordPress in all versions <= 6.4.23. The plugin exposes an AJAX entry point (the wpbdp_ajax family of actions, consistent with the prior CVE-2026-1656 pattern) that accepts a listing identifier but fails to verify that the caller owns the listing — or is even logged in. An unauthenticated remote attacker can craft a POST that flips listing titles, body content, contact emails, or category bindings on listings they do not own.
Patchstack/vendor-assigned MEDIUM (6.5, AV:N/AC:L/PR:N/UI:N/C:N/I:L/A:L) is *defensible but generous* for a real-world fleet. The score is driven entirely by unauth-network reach; impact is capped at integrity:LOW + availability:LOW with no confidentiality bleed and no path to RCE, SQLi, or auth-context escape. On a 10,000-host estate this is a content-tampering bug on a self-contained plugin, not a foothold-class issue. Downgrade is justified.
4 steps from start to impact.
Discover a WordPress site running Business Directory Plugin <= 6.4.23
/wp-content/plugins/business-directory-plugin/ asset paths, the [businessdirectory] shortcode output, or the BDP-specific wpbdp-* CSS classes in rendered pages. Tools like wpscan, WPSeku, or simple Google dorks (inurl:/business-directory/) identify candidates en masse.- Target site has BDP installed and active
- Plugin version is <= 6.4.23
- Site is reachable from the internet
- BDP is a niche plugin (~10–20k active installs per wordpress.org) — most WP estates do not run it
- Sites behind Cloudflare/Sucuri/Wordfence Managed WAF get plugin-specific virtual patches within hours of Patchstack disclosure
wpbdp_ajax parameter family within 24–72h of public PoC; nuclei templates land in projectdiscovery/nuclei-templates shortly after.Enumerate listing IDs
?listing_id=NNN or as the post slug. The attacker scrapes the public directory pages or queries the WP REST API (/wp-json/wp/v2/wpbdp_listing) to harvest a complete ID list. No auth is needed because directory listings are intentionally public.- Public directory view enabled (the default)
- Standard
curl/wgetaccess to the front-end
- None — this is by-design publication of IDs
Craft the unauthenticated AJAX call to mutate a listing
/wp-admin/admin-ajax.php with action=wpbdp_ajax (or the vulnerable sub-action) and the harvested listing_id, then supplies replacement fields — title, description, contact email, category. Because the handler lacks a current_user_can() / wp_verify_nonce() gate, the write goes through as if the listing owner had submitted it. PoCs typically use curl or a 10-line Python requests script; no specialized tooling required.- No WAF rule blocking unauth
wpbdp_ajaxwrites - Target listing exists
- Wordfence/Patchstack virtual patches block the parameter pattern
- Edge WAF rules on hosted WordPress (WP Engine, Kinsta, Pressable) tend to block unauth plugin-AJAX writes by default
- Some operators run BDP in *moderation* mode where edits queue for admin approval
admin-ajax.php POSTs with wpbdp_* actions from a single source IP are easy to alert on; Wordfence logs the modification with the *unauthenticated* user marker.Weaponize for SEO poisoning, phishing pivot, or brand damage
- Successful write from step 3
- Field is rendered to other visitors
- Listing owners typically notice mutations on their own listings quickly
- WordPress activity-log plugins (Simple History, WP Activity Log) record the diff
business-directory-plugin slug — Query your WP fleet management (ManageWP, MainWP, InfiniteWP) or grep wp-content/plugins/business-directory-plugin/ across managed hosts. You cannot prioritize what you cannot see. No mitigation SLA at LOW — but get the inventory done within the standard 30-day asset-management cadence.wpbdp_ajax unauth-write pattern automatically. This is the cheapest insurance against the next BDP bug too.wp_posts rows with post_type = wpbdp_listing plus the wp_postmeta rows for _wpbdp_* keys catches silent tampering. Pipe diffs to Slack/SIEM.- MFA on WordPress admin accounts — irrelevant; the bug is unauthenticated, no admin login is involved.
- Disabling XML-RPC — wrong endpoint; the vulnerable surface is
admin-ajax.php, which you cannot disable without breaking WordPress. - EDR on the web server — EDR sees a benign PHP-FPM process making legitimate DB writes; nothing crosses a syscall threshold an agent would flag.
- Network segmentation — the affected site is *intentionally* public; segmentation does not reduce the attack surface for a public directory.
- Patching WordPress core — core updates do not touch plugin code; only the plugin update closes this.
The supporting signals.
| CVE | CVE-2026-57339 |
|---|---|
| CWE | CWE-862 — Missing Authorization |
| Vendor severity | MEDIUM (6.5) — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L |
| Affected | Business Directory Plugin (business-directory-plugin) <= 6.4.23 |
| Fixed in | 6.4.24 (vendor-released patch following the 6.4.23 disclosure cycle — verify against the wordpress.org changelog) |
| In-the-wild | No KEV listing, no public reports of active exploitation as of 2026-06-30 |
| Public PoC | No standalone PoC published yet; the CVE-2026-1656 (versions <= 6.4.20) pattern is the public template — same wpbdp_ajax handler family |
| EPSS | Expected <1% based on prior BDP CVEs (CVE-2026-1656 sits at ~0.15%) — low forecasted exploitation |
| Exposure | ~10–20k active installs per wordpress.org plugin stats; a fraction of those expose admin-ajax to the public internet unfiltered |
| Disclosed | 2026-06-29 via Patchstack/wordfence advisory pipeline |
| Impact ceiling | Integrity:LOW + Availability:LOW, *no confidentiality impact* — listing mutation only, no DB exfil, no RCE |
Sources.
- Patchstack — Business Directory Plugin vulnerability database
- Patchstack — Broken Access Control in Business Directory Plugin (prior CVE pattern)
- Managed-WP — CVE-2026-1656 advisory (same plugin, prior version range)
- FreshySites — CVE-2026-1656 bulletin
- Wordfence Threat Intel — Business Directory Plugin
- WPScan — Business Directory Plugin advisories
- NVD — CVE-2026-57339 record (when published)
- CISA KEV catalog (verify not listed)
Why this verdict
- No confidentiality impact — CVSS vector explicitly says C:N. There is no database read, no PII egress, no credential disclosure. The bug only writes existing fields.
- Role multiplier — low-value role only. BDP runs on marketing/community/SMB sites as a *directory feature*. It is never deployed as an identity provider, hypervisor, CA, CI/CD node, backup admin, or kernel agent. No realistic deployment puts BDP on a high-value-role host, so the deployment-role floor does not apply.
- Population is narrow — ~10–20k WP installs run BDP versus ~810M WordPress sites globally (sub-0.003% of the WP fleet). On a 10,000-host enterprise estate, BDP typically appears on 0–3 marketing properties at most.
- Compensating controls already cover most exposure — Wordfence, Patchstack, Sucuri, and managed WP hosts (WP Engine, Kinsta) push virtual patches for plugin-AJAX authorization bypasses within hours of disclosure.
- No chain to RCE or auth-context escape — even with the write primitive, BDP fields are output-escaped, blocking stored-XSS uplift in the default templates.
Why not higher?
MEDIUM/HIGH would require either confidentiality impact (none here), an RCE/auth-bypass chain (none here), or a high-value-role deployment (BDP is never one). CVSS:N/AC:L/PR:N earns the network-reachable badge, but the I:L + A:L cap on a directory plugin caps real-world damage at SEO spam and listing defacement — that is LOW for an enterprise defender.
Why not lower?
IGNORE is wrong because the bug is unauthenticated, network-reachable, and trivially weaponizable — once a PoC lands the script-kiddie population will mass-scan for it, and brand-damage / phishing-pivot scenarios are real. It belongs on the patch backlog, not in the dustbin.
Crowdsourced verification payload.
Run on each WordPress host as the web user (or root) from the WP install root. Invoke as ./check-bdp.sh /var/www/html — pass the path to your WordPress installation. Requires read access to the plugin directory; no DB credentials needed.
#!/usr/bin/env bash
# noisgate verification: CVE-2026-57339 — Business Directory Plugin <= 6.4.23
# Usage: ./check-bdp.sh /path/to/wordpress
set -u
WP_ROOT="${1:-/var/www/html}"
PLUGIN_DIR="$WP_ROOT/wp-content/plugins/business-directory-plugin"
FIXED="6.4.24"
if [ ! -d "$WP_ROOT" ]; then
echo "UNKNOWN: $WP_ROOT is not a directory"
exit 2
fi
if [ ! -d "$PLUGIN_DIR" ]; then
echo "PATCHED: business-directory-plugin not installed at $WP_ROOT"
exit 0
fi
# Parse plugin header for Version: line
HEADER_FILE="$PLUGIN_DIR/business-directory-plugin.php"
if [ ! -f "$HEADER_FILE" ]; then
# Some forks rename the entry file; fall back to readme
HEADER_FILE="$PLUGIN_DIR/readme.txt"
fi
VERSION=$(grep -m1 -iE '^[[:space:]]*(Stable tag|Version):' "$HEADER_FILE" 2>/dev/null \
| sed -E 's/.*[: ]+([0-9]+\.[0-9]+(\.[0-9]+)?).*/\1/')
if [ -z "$VERSION" ]; then
echo "UNKNOWN: could not parse plugin version from $HEADER_FILE"
exit 2
fi
# version_compare: returns 0 if $1 < $2
vlt() {
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ] && [ "$1" != "$2" ]
}
if vlt "$VERSION" "$FIXED"; then
echo "VULNERABLE: business-directory-plugin $VERSION (<= 6.4.23, fix is $FIXED) at $PLUGIN_DIR"
exit 1
else
echo "PATCHED: business-directory-plugin $VERSION (>= $FIXED) at $PLUGIN_DIR"
exit 0
fi