CVE-2025-62108

Add Custom Codes <= 4.80 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
5.0
Patched in
77d
Time to patch

Description

The Add Custom Codes plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.80. This makes it possible for authenticated attackers, with subscriber-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<=4.80
PublishedDecember 31, 2025
Last updatedMarch 17, 2026
Affected pluginadd-custom-codes

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-62108 (Add Custom Codes Missing Authorization) ## 1. Vulnerability Summary The **Add Custom Codes** plugin (versions <= 4.80) contains a missing authorization vulnerability in its AJAX handlers. Specifically, functions responsible for administrative actions (l…

Show full research plan

Exploitation Research Plan: CVE-2025-62108 (Add Custom Codes Missing Authorization)

1. Vulnerability Summary

The Add Custom Codes plugin (versions <= 4.80) contains a missing authorization vulnerability in its AJAX handlers. Specifically, functions responsible for administrative actions (likely snippet deletion or status toggling) fail to verify the user's capabilities using current_user_can(). While these functions are registered using the wp_ajax_ hook (which requires the user to be authenticated), the lack of a capability check allows any logged-in user, including those with Subscriber privileges, to execute these sensitive actions.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • HTTP Method: POST
  • Action: acc_delete_snippet (inferred) or acc_update_status (inferred)
  • Authentication: Required (Subscriber-level or higher)
  • Parameters:
    • action: The vulnerable AJAX action name.
    • nonce: A security nonce (required for the request to pass check_ajax_referer).
    • id: The ID of the custom code snippet to manipulate.
  • Preconditions:
    • The attacker must have a valid Subscriber account.
    • At least one custom code snippet must exist in the system (created by an admin).

3. Code Flow (Inferred)

  1. Entry Point: A Subscriber sends a POST request to admin-ajax.php with action=acc_delete_snippet.
  2. Hook Execution: WordPress triggers the hook registered via add_action( 'wp_ajax_acc_delete_snippet', ... ).
  3. Nonce Validation: The handler calls check_ajax_referer( 'acc_nonce', 'nonce' ). Since nonces in WordPress are often available to all authenticated users in the admin dashboard, the Subscriber can provide a valid one.
  4. Vulnerable Logic: The handler proceeds to perform database operations (e.g., $wpdb->delete) using the provided id without calling current_user_can( 'manage_options' ).
  5. Sink: The snippet is removed from the {wp_prefix}_acc_codes table.

4. Nonce Acquisition Strategy

Even though Subscribers have limited permissions, they can access /wp-admin/profile.php. Plugins often enqueue their admin scripts and nonces globally or on all admin pages.

  1. Identify Script Localization: The plugin likely uses wp_localize_script to pass a nonce to the frontend.
  2. Setup: Ensure a snippet exists so the plugin's UI elements (and nonces) might be present.
  3. Execution:
    • Navigate the browser to /wp-admin/index.php or /wp-admin/profile.php as the Subscriber.
    • Use browser_eval to search for the nonce in the global window object.
  4. JavaScript Variable (Inferred):
    • window.acc_ajax_obj?.nonce
    • window.acc_vars?.nonce
    • window.acc_data?.nonce

5. Exploitation Strategy

Step 1: Authentication

Login as a Subscriber and capture the session cookies.

Step 2: Nonce Extraction

Navigate to the WordPress dashboard as the Subscriber and execute:

// Example browser_eval
return window.acc_ajax_obj ? window.acc_ajax_obj.nonce : "not_found";

Step 3: Identify Target ID

The attacker can guess IDs (starting from 1) or observe the ID if the plugin lists snippets in a way visible to subscribers (unlikely, so ID enumeration is the primary method).

Step 4: Unauthorized Deletion

Send the exploit request using http_request.

Request Details:

  • URL: http://[target-ip]/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=acc_delete_snippet&nonce=[EXTRACTED_NONCE]&id=[TARGET_ID]

6. Test Data Setup

  1. Admin Action: Install the plugin and create a "Test Snippet" (e.g., a simple PHP comment // Test).
  2. Admin Action: Create a Subscriber user.
  3. Verification: Use WP-CLI to find the ID of the newly created snippet:
    wp db query "SELECT id, title FROM wp_acc_codes;"
    

7. Expected Results

  • Success: The HTTP response should return 1, true, or a JSON success message (e.g., {"success":true}).
  • Impact: The custom code snippet with the specified ID is deleted from the database.
  • Unauthorized Access: The operation succeeds despite the user lacking manage_options or snippet management capabilities.

8. Verification Steps

After sending the POST request, verify the deletion via WP-CLI:

# This should return an empty result or indicate the ID no longer exists
wp db query "SELECT * FROM wp_acc_codes WHERE id = [TARGET_ID];"

9. Alternative Approaches

If acc_delete_snippet is not the correct action name, the agent should search the plugin's source code for wp_ajax_ hooks:

grep -rn "wp_ajax_" wp-content/plugins/add-custom-codes/

Once actions are found, check each corresponding function for the absence of current_user_can. Other possible targets include:

  • acc_update_status: Toggling snippets on/off.
  • acc_save_snippet: Potentially overwriting existing snippets if authorization is missing.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Add Custom Codes plugin for WordPress (versions 4.80 and below) is vulnerable to unauthorized access because it lacks capability checks in its AJAX handlers. This allow authenticated users with Subscriber-level permissions to perform administrative actions, such as deleting snippets or toggling their status, by sending unauthorized requests to the admin-ajax.php endpoint.

Vulnerable Code

// File: add-custom-codes.php (path inferred)
// The plugin registers AJAX hooks but fails to verify user capabilities within the handler function.

add_action( 'wp_ajax_acc_delete_snippet', 'acc_delete_snippet' );

function acc_delete_snippet() {
    // Nonce validation is present, but accessible to any logged-in user
    check_ajax_referer( 'acc_nonce', 'nonce' );

    // Vulnerability: Missing current_user_can( 'manage_options' ) check

    $id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : 0;
    global $wpdb;
    $table_name = $wpdb->prefix . 'acc_codes';
    $wpdb->delete( $table_name, array( 'id' => $id ) );
    wp_die();
}

Security Fix

--- a/add-custom-codes.php
+++ b/add-custom-codes.php
@@ -102,6 +102,10 @@
 function acc_delete_snippet() {
     check_ajax_referer( 'acc_nonce', 'nonce' );
 
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_die( -1 );
+    }
+
     $id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : 0;
     global $wpdb;
     $table_name = $wpdb->prefix . 'acc_codes';
     $wpdb->delete( $table_name, array( 'id' => $id ) );

Exploit Outline

The exploit requires an authenticated WordPress account with at least Subscriber-level privileges. The attacker first visits the WordPress admin dashboard (e.g., profile.php) to extract a valid security nonce (acc_nonce) from the localized scripts (typically found in window.acc_ajax_obj or similar objects). They then send a POST request to /wp-admin/admin-ajax.php with the action set to acc_delete_snippet, the extracted nonce, and the target snippet ID. Because the handler lacks a current_user_can() check, the plugin proceeds to delete the specified snippet regardless of the user's insufficient permissions.

Check if your site is affected.

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