This is a sharp knife locked inside a room that only members can enter
CVE-2026-5074 is an authenticated SQL injection in ARMember Premium for WordPress affecting versions up to and including 7.3.1, fixed in 7.3.2. The bug sits in the get_private_content_data AJAX action, where the sSortDir_0 parameter is used in an ORDER BY clause without a proper whitelist check. A logged-in attacker with at least Subscriber rights can abuse that to read database content.
The vendor's 6.5 / MEDIUM label is basically fair, but still a bit generous for enterprise patch triage because two frictions materially narrow the exposed population: it requires an authenticated account, and exploitation only works when the User Private Content addon is enabled, which ARMember documents as disabled by default. The risk rises on internet-facing membership sites with self-registration, but this is still not in the same class as the companion unauthenticated SQLi CVE-2026-5073.
4 steps from start to impact.
Get a low-privilege member session
Burp Suite or a browser session; there is no exploit magic yet.- Target runs ARMember Premium
- Attacker can obtain Subscriber+ access
- Site allows public signup or attacker already has valid creds
- No anonymous exploitation path
- Private B2B or staff-only portals dramatically cut reachable population
- MFA, email verification, anti-abuse controls, and moderation slow bulk account creation
Reach the vulnerable private-content AJAX action
get_private_content_data handler, typically via WordPress admin-ajax.php, and supplies a malicious sSortDir_0 value. Wordfence notes the bug is only exploitable when the User Private Content addon is enabled, so the feature gate matters as much as the code bug.- User Private Content addon is enabled
- The vulnerable AJAX action is reachable for the authenticated user
- Addon is documented by ARMember as disabled by default
- Many deployments buy ARMember for paywalls or subscriptions and never turn on per-user private content
Extract data with SQLi
sqlmap to turn the ORDER BY injection into database reads. The practical outcome is data disclosure: users, emails, password hashes, membership data, and potentially plugin-specific secrets sitting in WordPress tables.- SQL injection payload survives request parsing
- Database responses can be observed directly or inferred
- This is a read-focused SQLi, not an instant RCE
- Time-based extraction can be noisy and slow on production systems
- DB account permissions and schema knowledge affect how useful the dump becomes
admin-ajax.php often blends into normal plugin noise; app logs and DB slow-query spikes are better signals.Turn disclosure into account takeover if chained
wp_usermeta. If an attacker can read those rows through SQLi, they can reset arbitrary accounts, including admins.- Same site is also vulnerable to CVE-2026-5076
- Reset keys exist in the database for target users
- This is a chain, not the native impact of CVE-2026-5074 alone
- Keys may not be present for every target at every time
The supporting signals.
| In-the-wild status | No public evidence of active exploitation found in reviewed sources as of 2026-06-02. |
|---|---|
| KEV status | Not listed in CISA KEV as of assessment time; the user-supplied intel matches current public catalog checks. |
| Proof-of-concept availability | No public GitHub or vendor-linked PoC for CVE-2026-5074 was found in reviewed indexed results. That lowers immediate mass-exploitation pressure. |
| EPSS | No CVE-specific public FIRST EPSS datapoint was located during this assessment. *Inference:* the record is very new and may not yet have surfaced in indexed EPSS lookups. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N — the key limiter is PR:L, not exploit complexity. |
| Affected versions | ARMember Premium <= 7.3.1. |
| Fixed version | 7.3.2 per Wordfence and ARMember changelog. No distro/backport packaging model is relevant here. |
| Feature gate | Exploitability depends on the User Private Content addon being enabled; ARMember documents that addon activation is a separate admin action and the vulnerable feature is disabled by default. |
| Exposure/population | This is not fringe software: CodeCanyon search results show roughly 12.6K sales for ARMember. Still, only a subset of those sites will expose this exact path because of the addon requirement. |
| Researcher / disclosure | Published 2026-06-02 by h0xilo via Wordfence. |
noisgate verdict.
The decisive factor is not the SQLi primitive itself but the compounded reachability friction: an attacker needs a valid low-privilege account and a specific ARMember addon that is documented as disabled by default. That sharply narrows the exposed population compared with commodity unauthenticated WordPress SQL injection bugs.
Why this verdict
- Requires authenticated access: starting from the vendor's 6.5 baseline, the need for a real Subscriber+ session is meaningful downward pressure because this is not internet-spray unauth SQLi.
- Feature-gated and off by default: Wordfence says exploitation only works if the User Private Content addon is enabled, and ARMember docs show that addon must be explicitly activated. That is the biggest practical reducer.
- Impact is data exposure, not direct code exec: high confidentiality impact is real, but there is no native integrity or availability hit in the published CVSS, which keeps this out of higher buckets absent a chain.
Why not higher?
This is not broadly reachable across the internet in the way defenders should fear most. No KEV listing, no public exploitation evidence, no indexed PoC, and the attack path assumes both a login barrier and a specific addon state.
Why not lower?
On ARMember membership sites, Subscriber accounts can be cheap or self-provisioned, so PR:L is not the same as a hard internal-only control. And because the bug discloses database content, it can become a serious stepping stone when paired with CVE-2026-5076 on the same plugin family.
What to do — in priority order.
- Disable the User Private Content addon where unused — If the business does not actually use this feature, turning it off removes the vulnerable path entirely. For a MEDIUM verdict there is no mitigation SLA, so apply this opportunistically while you work the normal remediation window.
- Tighten signup and member creation — Require email verification, anti-bot controls, approval workflows, and stronger abuse monitoring on public registration to make Subscriber acquisition expensive. There is no mitigation SLA for MEDIUM, but this is worthwhile on internet-facing membership properties.
- Inspect pages for
[arm_user_private_content]usage — That shortcode is a strong signal that the feature is actively in play. Use it to separate likely-exploitable sites from simple version-only exposure during the remediation window. - Monitor authenticated
admin-ajax.phptraffic — Baseline and alert on unusual request volumes, strange sort-direction values, repeated database-delay patterns, and member-originated requests touching private-content actions. This is detective coverage, not a substitute for patching.
- A perimeter WAF alone is not enough; authenticated plugin AJAX traffic often reaches
admin-ajax.phpwith parameters that look application-specific and may evade generic signatures. - Hiding wp-admin does not solve this; the issue is in an AJAX action, not in an admin-only page flow.
- Assuming Subscriber is harmless is a bad control model on membership sites, because public signup often makes Subscriber the attacker's easiest foothold.
Crowdsourced verification payload.
Run this on the target WordPress host where the site files and database are accessible. Invoke it as bash verify-cve-2026-5074.sh /var/www/html with a user that can read the WordPress files; wp-cli is optional but strongly recommended for higher-confidence results.
#!/usr/bin/env bash
# verify-cve-2026-5074.sh
# Checks ARMember Premium version and looks for likely exposure of the User Private Content feature.
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
set -u
WP_PATH="${1:-}"
if [ -z "$WP_PATH" ] || [ ! -d "$WP_PATH" ]; then
echo "UNKNOWN - usage: $0 /path/to/wordpress"
exit 2
fi
PLUGIN_DIR="$WP_PATH/wp-content/plugins/armember"
MAIN_FILE=""
for f in "$PLUGIN_DIR"/*.php; do
[ -f "$f" ] || continue
if grep -qi '^\s*Version:' "$f"; then
MAIN_FILE="$f"
break
fi
done
if [ ! -d "$PLUGIN_DIR" ]; then
echo "PATCHED - ARMember plugin directory not found on this host"
exit 0
fi
version_ge() {
[ "$(printf '%s\n' "$1" "$2" | sort -V | tail -n1)" = "$1" ]
}
VERSION=""
if command -v wp >/dev/null 2>&1; then
VERSION=$(wp plugin get armember --field=version --path="$WP_PATH" --allow-root 2>/dev/null)
fi
if [ -z "$VERSION" ] && [ -n "$MAIN_FILE" ]; then
VERSION=$(awk -F': ' 'BEGIN{IGNORECASE=1} /^Version:/ {print $2; exit}' "$MAIN_FILE" 2>/dev/null)
fi
if [ -z "$VERSION" ]; then
echo "UNKNOWN - could not determine ARMember version"
exit 2
fi
if version_ge "$VERSION" "7.3.2"; then
echo "PATCHED - ARMember version $VERSION"
exit 0
fi
# Vulnerable version range here: <= 7.3.1
# Try to determine if the User Private Content feature is actually in use.
if ! command -v wp >/dev/null 2>&1; then
echo "UNKNOWN - vulnerable version $VERSION found, but wp-cli unavailable to assess feature usage"
exit 2
fi
PREFIX=$(wp db prefix --path="$WP_PATH" --allow-root 2>/dev/null)
if [ -z "$PREFIX" ]; then
echo "UNKNOWN - vulnerable version $VERSION found, but could not read WordPress DB prefix"
exit 2
fi
SHORTCODE_COUNT=$(wp db query "SELECT COUNT(*) FROM ${PREFIX}posts WHERE post_content LIKE '%[arm_user_private_content]%' AND post_status IN ('publish','private','draft');" --skip-column-names --path="$WP_PATH" --allow-root 2>/dev/null | tail -n1 | tr -d '[:space:]')
OPTION_HINTS=$(wp db query "SELECT COUNT(*) FROM ${PREFIX}options WHERE option_name LIKE '%private_content%' OR option_value LIKE '%arm_user_private_content%' OR option_value LIKE '%private_content%';" --skip-column-names --path="$WP_PATH" --allow-root 2>/dev/null | tail -n1 | tr -d '[:space:]')
SHORTCODE_COUNT=${SHORTCODE_COUNT:-0}
OPTION_HINTS=${OPTION_HINTS:-0}
if [[ "$SHORTCODE_COUNT" =~ ^[0-9]+$ ]] && [ "$SHORTCODE_COUNT" -gt 0 ]; then
echo "VULNERABLE - ARMember version $VERSION and private-content shortcode detected ($SHORTCODE_COUNT match(es))"
exit 1
fi
if [[ "$OPTION_HINTS" =~ ^[0-9]+$ ]] && [ "$OPTION_HINTS" -gt 0 ]; then
echo "VULNERABLE - ARMember version $VERSION with private-content configuration indicators present"
exit 1
fi
echo "UNKNOWN - ARMember version $VERSION is vulnerable, but no strong evidence of active User Private Content usage was found"
exit 2
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.