CVE-2024-1071 vulnerability and BitFire protection

How BitFire WAF Stops CVE-2024-1071 Ultimate Member SQL Injection

WordPress vulnerability research

Ultimate Member lets an unauthenticated visitor inject SQL through its member-directory sorting parameter, while BitFire WAF inspects that input and rejects SQL keywords and evasion signatures before the plugin builds the query.

Unauthenticated Critical Severity Sensitive Data Exposure SQL Injection
BitFire · Vulnerability advisoryResearch published
AdvisoryCVE-2024-1071
ComponentUltimate Member – User Profile, Registration, Login, Member Directory, Content Restriction & Membership Plugin
Relevant sourceincludes/core/class-member-directory-meta.php: Member_Directory_Meta::ajax_get_members() sorting and SQL-order construction
Executive summary

What WordPress administrators need to know

CVE-2024-1071 is a critical unauthenticated SQL injection vulnerability in Ultimate Member versions 2.1.3 through 2.8.2. The public member-directory AJAX request accepts a `sorting` POST parameter, applies text sanitization, and can interpolate an unrecognized value into an SQL `ORDER BY` clause as though it were a trusted `wp_users` column. An attacker can therefore alter the database query and may extract sensitive information without a WordPress account. BitFire's built-in WAF analyzes every input parameter for SQL keywords and SQL injection evasion signatures, rejecting the malicious request before Ultimate Member constructs the vulnerable query.

At a glance

Key facts

  • Ultimate Member versions 2.1.3 through 2.8.2 are affected
  • No WordPress account is required to reach the vulnerable member-directory request
  • The attacker controls the `sorting` POST parameter sent to the `um_get_members` AJAX action
  • Text sanitization does not make an input safe for use as an SQL identifier or expression
  • The vulnerable fallback interpolates an unknown sort value directly after `ORDER BY u.`
  • BitFire WAF rejects SQL keywords and SQL injection evasion signatures before the plugin receives the payload
01
Vulnerability overview

Understand the exposure

The affected component, attack path, and practical risk for WordPress websites.

Affected componentUltimate Member – User Profile, Registration, Login, Member Directory, Content Restriction & Membership Plugin
Potential reach200,000+ installations
Attack techniqueSQL injection
Published2024-02-23
BitFire WAF inspects the hostile sorting value at the request boundary and blocks the SQL keywords or evasion patterns before they can become part of Ultimate Member's ORDER BY clause.
02
Technical analysis

How the vulnerability works

Research details, affected versions, exploitation behavior, and remediation guidance.

CVE-2024-1071 Exposes Ultimate Member's Public Directory Query

Ultimate Member supplies profiles, registration, login, content restriction, and searchable member directories to more than 200,000 WordPress installations. CVE-2024-1071 affects versions 2.1.3 through 2.8.2 and carries a critical CVSS score of 9.8. An unauthenticated visitor can submit a crafted member-directory request containing a malicious `sorting` value. Vulnerable code incorporates that value into a database ordering clause, allowing the visitor to change the intended SQL statement and potentially extract sensitive database information. The exact information exposed depends on the payload, database behavior, and data available to the WordPress database account; extraction is a possible impact rather than a guaranteed disclosure of every record.

The Sorting Parameter Crosses Into SQL as an Identifier

The frontend member directory calls WordPress's AJAX endpoint with the `um_get_members` action, a directory identifier, a frontend nonce, and values that include the `sorting` POST parameter. `Member_Directory_Meta::ajax_get_members()` reads that parameter and passes it through `sanitize_text_field()`. It then handles known sort modes and configured user-metadata keys. In version 2.8.2, any value that reaches the final fallback is concatenated into `ORDER BY u.{$sortby} {$order}`. Because the fallback does not restrict `sortby` to real `wp_users` columns, attacker-selected SQL syntax can enter the statement before the completed query is passed to `$wpdb->get_col()`.

A Frontend Nonce and Text Sanitization Do Not Stop SQL Injection

The AJAX handler verifies Ultimate Member's frontend nonce, but the plugin creates that nonce for frontend scripts so ordinary visitors can use public member-directory features. Possession of this public workflow token does not authenticate the visitor or authorize arbitrary SQL ordering expressions. The call to `sanitize_text_field()` is also the wrong boundary for this risk: it removes or normalizes text-oriented content, but it is not SQL escaping and does not enforce a finite set of column names. SQL identifiers and order directions must come from trusted allowlists, while data values should be passed through prepared-query placeholders. Neither a public nonce nor generic text sanitization repairs missing SQL validation.

Version 2.8.3 Restricts Sorting to Known Database Fields

Ultimate Member 2.8.3 changes the vulnerable branch rather than relying on stronger text cleanup. The corrected code defines a finite `core_users_fields` list, uses strict `in_array()` checks, and emits a core-column `ORDER BY` clause only when `sortby` matches one of those approved fields. Configured metadata keys follow a separate branch where the join's `um_key` value is supplied through `$wpdb->prepare()`. The patch also constrains the order direction to `ASC` or `DESC` and escapes SQL fragments before interpolation. Unknown sorting values no longer fall through to a query containing an attacker-selected `u.<expression>`.

BitFire WAF Rejects the SQL Injection Before Ultimate Member Runs

Exploitation requires a POST request whose `sorting` parameter carries SQL keywords or an encoded or obfuscated SQL injection pattern. BitFire's built-in WAF analyzes all input parameters and applies its SQL injection protections before WordPress dispatches the request to Ultimate Member. When the WAF identifies the SQL syntax or an SQLi evasion signature, it rejects the request, so `ajax_get_members()` never receives the hostile sorting expression and the unsafe `ORDER BY` clause is never assembled. This is behavior-based protection rather than a virtual patch tied only to CVE-2024-1071: the SQLi rules are already active against malicious database syntax before a vulnerability-specific signature exists.

Conclusion: Database Inputs Need Independent Access Controls

Ultimate Member 2.8.3 records the corrected sorting behavior, and administrators can verify the installed release while reviewing web and BitFire events for unusual `um_get_members` requests or hostile `sorting` values. CVE-2024-1071 demonstrates why site administrators need a security solution with built-in access controls and zero-day protection when plugin code confuses sanitized text with trusted SQL structure. BitFire WAF supplies that independent request boundary by examining parameter behavior and denying SQL injection syntax before the dangerous database query can be created, even when no CVE-specific rule has yet been written.

03
Source review

Vulnerable and fixed code

The relevant source is located in includes/core/class-member-directory-meta.php: Member_Directory_Meta::ajax_get_members() sorting and SQL-order construction.

BeforeVulnerable behavior
// Vulnerable source, abridged from Ultimate Member 2.8.2.
$metakeys = get_option( 'um_usermeta_fields', array() );
if ( false !== array_search( $sortby, $metakeys ) ) {
    $this->joins[] = "LEFT JOIN {$wpdb->prefix}um_metadata umm_sort ON ( umm_sort.user_id = u.ID AND umm_sort.um_key = '{$sortby}' )";
    $this->sql_order = " ORDER BY CAST( umm_sort.um_value AS CHAR ) {$order} ";
} else {
    $this->sql_order = " ORDER BY u.{$sortby} {$order} ";
}
AfterCorrected behavior
// Patched source, abridged from Ultimate Member 2.8.3.
$metakeys = get_option( 'um_usermeta_fields', array() );
if ( in_array( $sortby, $this->core_users_fields, true ) ) {
    $sortby = esc_sql( $sortby );
    $order  = esc_sql( $order );
    $order  = in_array( strtoupper( $order ), array( 'ASC', 'DESC' ), true ) ? $order : 'ASC';
    $this->sql_order = " ORDER BY u.{$sortby} {$order} ";
} elseif ( in_array( $sortby, $metakeys, true ) ) {
    $this->joins[] = $wpdb->prepare(
        "LEFT JOIN {$wpdb->prefix}um_metadata umm_sort ON ( umm_sort.user_id = u.ID AND umm_sort.um_key = %s )",
        $sortby
    );
}
04
Zero-day protection

Protection from the first exploit request

BitFire protects WordPress servers on day zero—before a vulnerability is publicly known and before other vendors have time to develop signatures or patches.

01 · VerifyStop unknown clients

Bot controls and browser verification stop untrusted automated clients before previously unknown exploit code reaches WordPress.

02 · DetectBlock malicious behavior

General WAF protections identify dangerous request behavior and hostile payloads without waiting for a vulnerability-specific signature.

03 · PreventContain attacks at runtime

RASP follows execution inside PHP and prevents unauthorized changes to protected files, accounts, and database content.

BitFire · WordPress protectionZero-day ready
BitFire zero-day WordPress vulnerability protection
BitFire combines verified-client controls, behavior-based WAF detection, and runtime RASP enforcement to protect WordPress before an exploit has a name, CVE, signature, or vendor patch.
About the author

Cory Marsh

Cory has more than 20 years of internet security experience and is a lead developer on the BitFire project.

Read BitFire security research →
Protect your WordPress website

Add protection before the next exploit arrives.

BitFire combines bot controls, request inspection, malware detection, and runtime protection in one WordPress security platform.

Protect my site free →