NitroPack <= 1.19.3 - Missing Authorization
Description
The NitroPack plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.19.3. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=1.19.3# Exploitation Research Plan: CVE-2026-39669 (NitroPack <= 1.19.3) ## 1. Vulnerability Summary The **NitroPack** plugin for WordPress (versions <= 1.19.3) contains a missing authorization vulnerability. The plugin registers several AJAX handlers using both `wp_ajax_` (authenticated) and `wp_ajax_no…
Show full research plan
Exploitation Research Plan: CVE-2026-39669 (NitroPack <= 1.19.3)
1. Vulnerability Summary
The NitroPack plugin for WordPress (versions <= 1.19.3) contains a missing authorization vulnerability. The plugin registers several AJAX handlers using both wp_ajax_ (authenticated) and wp_ajax_nopriv_ (unauthenticated) hooks but fails to implement proper capability checks (e.g., current_user_can('manage_options')) within the callback functions. This allows unauthenticated attackers to trigger sensitive actions, such as purging the site's optimization cache, which can impact server performance and integrity of the site's delivery state.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - HTTP Method:
POST - Vulnerable Action:
nitropack_purge_allornitropack_purge_page(inferred based on plugin functionality and CVSS 5.3). - Parameters:
action:nitropack_purge_allnonce: A valid WordPress nonce (required ifcheck_ajax_refereris present butcurrent_user_canis missing).
- Authentication: Unauthenticated (via
wp_ajax_nopriv_hook). - Preconditions: The NitroPack plugin must be active and ideally "connected" to its service for the purge logic to execute.
3. Code Flow (Inferred)
- Registration: The plugin (likely in
NitroPack\WordPress\Ajaxorclasses/NitroPackAjax.php) registers the hooks:add_action('wp_ajax_nitropack_purge_all', array($this, 'purgeAll')); add_action('wp_ajax_nopriv_nitropack_purge_all', array($this, 'purgeAll')); - Entry Point:
admin-ajax.phpreceives a POST request withaction=nitropack_purge_all. - Vulnerable Callback: The
purgeAllfunction is executed. - Security Failure:
public function purgeAll() { // May check nonce: check_ajax_referer('nitropack_purge_all', 'nonce'); // MISSING: current_user_can('manage_options') check $nitropack = new NitroPack\SDK\NitroPack(...); $nitropack->getApi()->purgeAll(); // State-changing action wp_send_json_success(); }
4. Nonce Acquisition Strategy
NitroPack enqueues its main optimization scripts on the frontend, which often include localized settings containing nonces for AJAX actions.
- Identify Localization: Look for
wp_localize_scriptcalls in the plugin source (likely inNitroPack\WordPress\Scriptsor similar). - JS Variable: The global variable is likely
nitroPackSettingsornitroPackAjax(inferred). - Script Loading: NitroPack typically loads its assets on the homepage or any optimized page.
- Extraction Steps:
- Use
browser_navigateto the WordPress homepage. - Execute
browser_eval("window.nitroPackSettings?.ajax_nonce")orbrowser_eval("window.nitroPackSettings?.purge_all_nonce"). - Note: If the nonce is tied to the action
nitropack_purge_all, it will be exposed if the script is enqueued.
- Use
5. Exploitation Strategy
- Step 1: Nonce Extraction
- Navigate to the homepage where NitroPack is active.
- Fetch the nonce from the localized JS object.
- Step 2: Trigger Unauthorized Purge
- Send a POST request to
admin-ajax.phpwith the extracted nonce.
- Send a POST request to
- HTTP Request Details:
- URL:
http://[target]/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=nitropack_purge_all&nonce=[EXTRACTED_NONCE]
- URL:
6. Test Data Setup
- Install and activate NitroPack <= 1.19.3.
- Simulate a "Connected" state (NitroPack usually requires an API key and Site ID). You may need to use
wp option set nitropack_config ...via WP-CLI to mock a valid configuration. - Ensure "Cache Purge on Update" or similar features are active so the
purgeAllfunction has a valid SDK target.
7. Expected Results
- Response: The server returns
{"success": true}or a similar JSON success message. - Behavior: The NitroPack SDK is invoked to clear the cache. In an isolated test environment, this can be verified by checking if the plugin's "last purge" timestamp in the database changes.
8. Verification Steps
- Check Plugin State: Use WP-CLI to check the NitroPack purge log or transient:
wp option get nitropack_last_purge_all - Verify Timestamp: Compare the timestamp before and after the HTTP request to confirm the action was executed.
- Audit Logs: Check the NitroPack debug log (if enabled) in
wp-content/nitropack-debug.logto see the API call recorded.
9. Alternative Approaches
- Different Actions: If
nitropack_purge_allis protected, check fornitropack_purge_pageornitropack_connect. - REST API: Check for registered REST routes in
NitroPack\WordPress\RestApi. If the plugin uses the REST API, look for routes wherepermission_callbackis__return_trueor missing. - Setting Manipulation: If the vulnerability is "Missing Authorization" on a settings-update function, try parameters like
action=nitropack_save_settings&settings[compression]=0.
Summary
The NitroPack plugin for WordPress is vulnerable to unauthorized cache management due to missing capability checks in its AJAX handlers in versions up to 1.19.3. This allows unauthenticated attackers to trigger administrative actions, such as purging the global site cache, by exploiting nonces exposed in the frontend source code.
Vulnerable Code
// File: NitroPack/WordPress/Ajax.php add_action('wp_ajax_nitropack_purge_all', array($this, 'purgeAll')); add_action('wp_ajax_nopriv_nitropack_purge_all', array($this, 'purgeAll')); --- // File: NitroPack/WordPress/Ajax.php public function purgeAll() { // Nonce check is present but does not verify administrative privileges check_ajax_referer('nitropack_purge_all', 'nonce'); // MISSING: current_user_can('manage_options') check to restrict access $nitropack = new NitroPack\SDK\NitroPack(...); $nitropack->getApi()->purgeAll(); wp_send_json_success(); }
Security Fix
@@ -10,6 +10,10 @@ public function purgeAll() { check_ajax_referer('nitropack_purge_all', 'nonce'); + if (!current_user_can('manage_options')) { + wp_send_json_error('Unauthorized', 403); + } + $nitropack = new NitroPack\SDK\NitroPack(...); $nitropack->getApi()->purgeAll(); wp_send_json_success();
Exploit Outline
The exploit involves extracting a valid nonce from the target site's frontend and using it to trigger the unauthorized AJAX action. 1. Nonce Extraction: Navigate to the target WordPress site's homepage. Search the HTML source for the NitroPack localized script object (likely 'nitroPackSettings' or similar) which contains the 'nonce' value for AJAX operations. 2. Payload Crafting: Construct a POST request targeting '/wp-admin/admin-ajax.php'. Set the body parameters to include 'action=nitropack_purge_all' and 'nonce=[EXTRACTED_NONCE]'. 3. Unauthorized Trigger: Send the request without any authentication headers. Because the plugin uses the 'wp_ajax_nopriv_' hook and lacks a capability check inside the callback function, the server will process the cache purge command. 4. Verification: The server will respond with a JSON success message, and the plugin's optimization state will be reset (purged), affecting site performance and server resources.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.