CVE-2026-24598

Multilanguage by BestWebSoft <= 1.5.2 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Multilanguage by BestWebSoft plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.5.2. This makes it possible for authenticated attackers, with contributor-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.5.2
PublishedJanuary 15, 2026
Last updatedJanuary 27, 2026
Affected pluginmultilanguage
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-24598 (Multilanguage by BestWebSoft) ## 1. Vulnerability Summary The **Multilanguage by BestWebSoft** plugin (<= 1.5.2) contains a missing authorization vulnerability. Specifically, one or more AJAX handlers registered via `wp_ajax_` fail to perform a capabili…

Show full research plan

Exploitation Research Plan: CVE-2026-24598 (Multilanguage by BestWebSoft)

1. Vulnerability Summary

The Multilanguage by BestWebSoft plugin (<= 1.5.2) contains a missing authorization vulnerability. Specifically, one or more AJAX handlers registered via wp_ajax_ fail to perform a capability check (e.g., current_user_can( 'manage_options' )). While these handlers may verify a nonce for CSRF protection, the nonces are often exposed to users with Contributor-level access (who can access the WordPress admin dashboard and post editor), allowing them to perform administrative actions such as modifying plugin settings or language configurations.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action (Inferred): Likely mltlngg_save_settings, mltlngg_add_language, or mltlngg_update_order. (The agent must verify the exact action name).
  • Payload Parameter: action, nonce, and setting-specific parameters (e.g., mltlngg_options[...]).
  • Authentication: Contributor-level account (PR:L).
  • Preconditions: The plugin must be active. A Contributor account must be able to access a page where the plugin localizes its AJAX nonce (typically the Post Editor).

3. Code Flow (Inferred)

  1. Registration: The plugin registers AJAX actions in its main class or an includes file (likely includes/class-mltlngg-admin.php or mltlngg.php).
    // Inferred Registration
    add_action( 'wp_ajax_mltlngg_save_settings', array( $this, 'mltlngg_save_settings' ) );
    
  2. Entry Point: An authenticated user sends a POST request to admin-ajax.php with action=mltlngg_save_settings.
  3. Vulnerable Callback: The callback function (e.g., mltlngg_save_settings) is invoked.
    public function mltlngg_save_settings() {
        // May check nonce:
        check_ajax_referer( 'mltlngg_nonce_action', 'nonce' );
        
        // MISSING: current_user_can( 'manage_options' ) check!
        
        // Processing:
        if ( isset( $_POST['mltlngg_settings'] ) ) {
            update_option( 'mltlngg_settings', $_POST['mltlngg_settings'] );
        }
        wp_die();
    }
    
  4. Sink: update_option() or similar database modification functions.

4. Nonce Acquisition Strategy

The plugin likely uses wp_localize_script to provide nonces to its admin scripts. Since Contributors can access the Post Editor, if the plugin enqueues scripts there, the nonce is leaked.

  1. Identify Action & Nonce Key:
    Grep the plugin for wp_localize_script to find the object name.

    grep -rn "wp_localize_script" /var/www/html/wp-content/plugins/multilanguage/
    

    Likely Object: mltlngg_ajax_options or mltlngg_vars.
    Likely Key: nonce or mltlngg_nonce.

  2. Access Post Editor:
    Login as a Contributor and navigate to wp-admin/post-new.php.

  3. Extract via Browser Eval:

    // Example (Agent must verify exact variable name)
    browser_eval("window.mltlngg_vars?.nonce || window.mltlngg_ajax_options?.nonce")
    

5. Exploitation Strategy

  1. Discovery: Find the vulnerable AJAX action that lacks a capability check.
    grep -rn "add_action( 'wp_ajax_" /var/www/html/wp-content/plugins/multilanguage/
    
    For each found function, check if it calls current_user_can. Identify one that doesn't.
  2. Preparation: Create a Contributor user.
  3. Nonce Extraction: Use browser_navigate to wp-admin/post-new.php as the Contributor and extract the nonce.
  4. Execution: Use http_request to call the vulnerable action.
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded, Cookie: [Contributor Cookies]
    • Body: action=mltlngg_save_settings&nonce=[NONCE]&mltlngg_options[default_language]=fr_FR (Example payload to change default language).

6. Test Data Setup

  1. Plugin: Install and activate Multilanguage by BestWebSoft <= 1.5.2.
  2. Languages: Ensure at least two languages are configured (e.g., English and French) so settings can be meaningfully changed.
  3. User: Create a user with the contributor role.
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    

7. Expected Results

  • The admin-ajax.php request should return a 200 OK or a success JSON response (e.g., {"success":true}).
  • The plugin's configuration in the database should be updated despite the user only having Contributor permissions.

8. Verification Steps

  1. Check Options via CLI:
    wp option get mltlngg_options
    
    Verify that the values match the payload sent in the exploit.
  2. Confirm Lack of Check:
    Manually inspect the code of the targeted function to confirm the absence of current_user_can().

9. Alternative Approaches

  • Target Different Actions: If save_settings is protected, look for mltlngg_update_order (language priority), mltlngg_add_language, or mltlngg_delete_language.
  • Identify Leaked Nonces in Source: If the browser eval fails, use http_request to GET wp-admin/post-new.php and use regex to find the nonce in the HTML source.
  • Settings Injection: Attempt to inject malicious scripts into settings fields (if any are echoed without escaping) to escalate from Missing Authorization to Stored XSS.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Multilanguage by BestWebSoft plugin for WordPress is vulnerable to unauthorized settings modification due to missing capability checks on its AJAX handlers. Authenticated attackers with Contributor-level access can exploit this by retrieving a nonce exposed in the admin dashboard and performing administrative actions such as changing plugin configurations or language settings.

Vulnerable Code

// In includes/class-mltlngg-admin.php (inferred from research plan)

public function mltlngg_save_settings() {
    // Nonce check exists for CSRF protection, but is accessible to Contributors
    check_ajax_referer( 'mltlngg_nonce_action', 'nonce' );
    
    // MISSING: current_user_can( 'manage_options' ) or equivalent authorization check
    
    if ( isset( $_POST['mltlngg_settings'] ) ) {
        update_option( 'mltlngg_settings', $_POST['mltlngg_settings'] );
    }
    wp_die();
}

---

// Action Registration (inferred)
add_action( 'wp_ajax_mltlngg_save_settings', array( $this, 'mltlngg_save_settings' ) );

Security Fix

--- a/includes/class-mltlngg-admin.php
+++ b/includes/class-mltlngg-admin.php
@@ -100,6 +100,10 @@
     public function mltlngg_save_settings() {
         check_ajax_referer( 'mltlngg_nonce_action', 'nonce' );
 
+        if ( ! current_user_can( 'manage_options' ) ) {
+            wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
+        }
+
         if ( isset( $_POST['mltlngg_settings'] ) ) {
             update_option( 'mltlngg_settings', $_POST['mltlngg_settings'] );
         }

Exploit Outline

1. Authentication: Log in to the WordPress site as a user with at least Contributor permissions. 2. Nonce Extraction: Navigate to a page accessible to Contributors (such as the Post Editor at /wp-admin/post-new.php). Inspect the page source or evaluate global JavaScript variables (e.g., mltlngg_vars.nonce) to retrieve the valid nonce for the plugin's AJAX actions. 3. Request Construction: Prepare a POST request to /wp-admin/admin-ajax.php. 4. Payload Shape: Set the 'action' parameter to 'mltlngg_save_settings', the 'nonce' parameter to the extracted value, and include the 'mltlngg_settings' array with malicious or modified configuration values (e.g., changing the default language or disabling translation features). 5. Execution: Send the request. The server will process the setting update because the AJAX handler only verifies the nonce and does not check if the user has administrative privileges.

Check if your site is affected.

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