CVE-2025-13374

Kalrav AI Agent <= 2.3.3 - Unauthenticated Arbitrary File Upload via kalrav_upload_file AJAX Action

criticalUnrestricted Upload of File with Dangerous Type
9.8
CVSS Score
9.8
CVSS Score
critical
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Kalrav AI Agent plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in the kalrav_upload_file AJAX action in all versions up to, and including, 2.3.3. This makes it possible for unauthenticated attackers to upload arbitrary files on the affected site's server which may make remote code execution possible.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.3.3
PublishedJanuary 23, 2026
Last updatedMay 4, 2026
Affected pluginkalrav-ai-agent
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-13374 ## 1. Vulnerability Summary The **Kalrav AI Agent** plugin (versions <= 2.3.3) is vulnerable to an **Unauthenticated Arbitrary File Upload** vulnerability. The flaw exists in the `kalrav_upload_file` AJAX action, which fails to implement any file type v…

Show full research plan

Exploitation Research Plan - CVE-2025-13374

1. Vulnerability Summary

The Kalrav AI Agent plugin (versions <= 2.3.3) is vulnerable to an Unauthenticated Arbitrary File Upload vulnerability. The flaw exists in the kalrav_upload_file AJAX action, which fails to implement any file type validation or sufficient authentication/authorization checks. This allows an unauthenticated attacker to upload malicious PHP files to the server, leading to Remote Code Execution (RCE).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: kalrav_upload_file
  • Hook: wp_ajax_nopriv_kalrav_upload_file (unauthenticated) and wp_ajax_kalrav_upload_file (authenticated).
  • Vulnerable Parameter: $_FILES (specifically the file uploaded via the multipart request).
  • Authentication: None required (unauthenticated).
  • Preconditions: The plugin must be active. A nonce may be required if check_ajax_referer is present in the handler.

3. Code Flow (Inferred from standard WordPress AJAX patterns)

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with action=kalrav_upload_file.
  2. Hook Execution: WordPress triggers the function associated with wp_ajax_nopriv_kalrav_upload_file.
  3. Handler Function: The function (likely named kalrav_upload_file) starts processing.
  4. Nonce Check (Potential): The function might call check_ajax_referer('kalrav_nonce', 'security') or similar.
  5. File Processing: The function accesses $_FILES['file'] (or a similar key).
  6. Vulnerable Sink: The function calls move_uploaded_file() or wp_handle_upload() without checking the file extension against a whitelist of safe types (like images) or explicitly forbidding .php files.
  7. Storage: The file is saved to the WordPress uploads directory, often within a subfolder like /wp-content/uploads/kalrav-ai-agent/.

4. Nonce Acquisition Strategy

If the kalrav_upload_file function enforces a nonce check, it must be retrieved from the frontend where the Kalrav AI Agent is rendered.

  1. Identify the Shortcode: Search the plugin code for add_shortcode. It is likely [kalrav_ai_agent] or similar.
  2. Create a Trigger Page:
    wp post create --post_type=page --post_status=publish --post_title="AI Agent" --post_content='[kalrav_ai_agent]'
    
  3. Identify JS Localization: Search for wp_localize_script in the plugin source to find the object name and nonce key.
    • Likely Variable Name (Inferred): kalrav_ajax_obj or kalrav_vars.
    • Likely Nonce Key (Inferred): nonce or security.
  4. Extract Nonce via Browser:
    • Navigate to the newly created page using browser_navigate.
    • Execute browser_eval("window.kalrav_ajax_obj?.nonce") (replace with actual identifiers found in source).

5. Exploitation Strategy

The exploit involves sending a multipart POST request to the AJAX endpoint containing a PHP shell.

Step 1: Preparation

  • Create a file named shell.php:
    <?php echo "CVE-2025-13374_OK: " . phpinfo(); ?>
    

Step 2: Payload Delivery

Send the request using the http_request tool:

  • Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php
  • Headers: Content-Type: multipart/form-data
  • Body Parameters:
    • action: kalrav_upload_file
    • security: [EXTRACTED_NONCE] (if required)
    • file: shell.php (The binary content of the shell)

Step 3: Identify Upload Path

The response from admin-ajax.php often returns the URL of the uploaded file in JSON format.

  • Expected Response JSON: {"success": true, "data": {"url": "http://.../wp-content/uploads/kalrav/shell.php"}}
  • If no URL is returned: Guess common paths like /wp-content/uploads/kalrav-ai-agent/shell.php or check the plugin's upload logic in the source.

6. Test Data Setup

  1. Activate Plugin: Ensure kalrav-ai-agent is installed and active.
  2. Shortcode Page: Create a page containing the plugin's primary shortcode to ensure scripts and nonces are loaded.
    • Action: wp post create --post_type=page --post_status=publish --post_content='[kalrav_ai_agent]' (Inferred shortcode).

7. Expected Results

  • The server responds with 200 OK and a JSON body indicating success.
  • The JSON contains a URL or path to the uploaded file.
  • Navigating to the uploaded .php file location executes the PHP code, displaying the phpinfo() output.

8. Verification Steps

  1. Verify via HTTP:
    # Use http_request to fetch the uploaded shell
    # Check if response contains "CVE-2025-13374_OK"
    
  2. Verify via WP-CLI:
    # Check if the file exists in the filesystem
    find /var/www/html/wp-content/uploads/ -name "shell.php"
    

9. Alternative Approaches

  • Filename Bypass: If the plugin appends a random string, look for the exact filename in the JSON response.
  • Path Traversal: If the filename parameter is user-controllable, attempt to upload to the root directory or wp-content/plugins/kalrav-ai-agent/ using ../../ sequences.
  • Mime-Type Spoofing: If there is basic client-side validation, ensure the request includes Content-Type: image/png for the file part while maintaining the .php extension.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Kalrav AI Agent plugin for WordPress is vulnerable to unauthenticated arbitrary file uploads via the kalrav_upload_file AJAX action. Due to a lack of file type validation and authorization checks, an attacker can upload malicious PHP scripts to the server and achieve remote code execution.

Vulnerable Code

/* Inferred from vulnerability description and research plan */

add_action('wp_ajax_nopriv_kalrav_upload_file', 'kalrav_upload_file');
add_action('wp_ajax_kalrav_upload_file', 'kalrav_upload_file');

function kalrav_upload_file() {
    if (isset($_FILES['file'])) {
        $uploaded_file = $_FILES['file'];
        $upload_overrides = array('test_form' => false);
        $movefile = wp_handle_upload($uploaded_file, $upload_overrides);
        if ($movefile && !isset($movefile['error'])) {
            echo json_encode(array('success' => true, 'url' => $movefile['url']));
        }
    }
    wp_die();
}

Security Fix

--- a/kalrav-ai-agent.php
+++ b/kalrav-ai-agent.php
@@ -10,6 +10,17 @@
 function kalrav_upload_file() {
+    // Check nonce for security
+    check_ajax_referer('kalrav_nonce', 'security');
+
+    // Ensure user has permissions or restrict unauthenticated usage
+    if (!current_user_can('upload_files')) {
+        wp_send_json_error('Unauthorized');
+    }
+
     if (isset($_FILES['file'])) {
-        $uploaded_file = $_FILES['file'];
+        $file = $_FILES['file'];
+        $allowed = array('jpg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif');
+        $file_type = wp_check_filetype($file['name'], $allowed);
+
+        if (!$file_type['ext']) {
+            wp_send_json_error('Invalid file type.');
+        }
+
         $upload_overrides = array('test_form' => false);
-        $movefile = wp_handle_upload($uploaded_file, $upload_overrides);
+        $movefile = wp_handle_upload($file, $upload_overrides);

Exploit Outline

The exploit targets the kalrav_upload_file AJAX action which is registered for unauthenticated users. An attacker first navigates to a public page containing the Kalrav AI Agent (e.g., via a shortcode) to extract a security nonce if required by the implementation. They then send a multipart/form-data POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'kalrav_upload_file', the 'security' parameter containing the nonce, and a 'file' parameter containing a malicious PHP script. If successful, the server responds with a JSON object containing the URL of the uploaded file. The attacker then visits this URL to execute the PHP code on the server.

Check if your site is affected.

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