Export Categories & Taxonomies <= 1.0.3 - Missing Authorization
Description
The Export Categories & Taxonomies plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.0.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.0.3This research plan focuses on identifying and exploiting the **Missing Authorization** vulnerability in the **Export Categories & Taxonomies** plugin (<= 1.0.3). Since the vulnerability is rated with **Integrity: Low (I:L)** and **Confidentiality: None (C:N)**, the "unauthorized action" likely inv…
Show full research plan
This research plan focuses on identifying and exploiting the Missing Authorization vulnerability in the Export Categories & Taxonomies plugin (<= 1.0.3).
Since the vulnerability is rated with Integrity: Low (I:L) and Confidentiality: None (C:N), the "unauthorized action" likely involves triggering an export process or modifying an export-related setting rather than directly stealing data (which would be C:H).
1. Vulnerability Summary
- Vulnerability: Missing Authorization (Missing Capability Check).
- Plugin: Export Categories & Taxonomies (
wp-export-categories-taxonomies). - Affected Versions: <= 1.0.3.
- Root Cause: The plugin registers an AJAX action (likely via
wp_ajax_nopriv_orwp_ajax_) but fails to verify if the user has the necessary permissions (e.g.,manage_options) before executing the logic. - Impact: Unauthenticated or low-privileged users can trigger administrative export functions or potentially manipulate plugin-specific actions.
2. Attack Vector Analysis
- Endpoint:
http://<target>/wp-admin/admin-ajax.php - Action (Inferred): Likely
wp_ajax_ect_export_actionorwp_ajax_export_categories_taxonomies. - Parameters:
action: The vulnerable AJAX hook identifier.nonce/security: (If required) A CSRF token.taxonomy: The target taxonomy to export.
- Preconditions: The plugin must be active. A nonce may be required if
check_ajax_refereris present, even ifcurrent_user_canis missing.
3. Code Flow (Inferred Trace)
- Entry Point:
admin-ajax.phpreceives a POST/GET request with anactionparameter. - Hook Registration: The plugin's main file or an inclusion (e.g.,
wp-export-categories-taxonomies.php) registers the action:add_action('wp_ajax_nopriv_ect_export', 'ect_export_callback'); add_action('wp_ajax_ect_export', 'ect_export_callback'); - Vulnerable Callback: The function
ect_export_callbackis executed. - The Flaw: The function likely calls
check_ajax_referer('ect_nonce', 'security')(providing CSRF protection) but fails to callif (!current_user_can('manage_options')) wp_die();. - Execution: The function proceeds to perform the export or modification logic regardless of the requester's identity.
4. Nonce Acquisition Strategy
If the AJAX handler uses check_ajax_referer, we must find where the nonce is leaked to unauthenticated users.
- Identify Localization: Search the source for
wp_localize_script.- Search Command:
grep -rn "wp_localize_script" . - Expected JS Variable (Inferred):
ect_ajax_varsorwp_ect_params. - Expected Key (Inferred):
ect_nonce.
- Search Command:
- Locate Script Enqueueing: Determine if the script is enqueued on the frontend (allowing unauthenticated access) or only in the admin dashboard.
- If enqueued via
wp_enqueue_scripts, it's available on the homepage. - If enqueued via
admin_enqueue_scripts, we may need a Subscriber account OR the plugin might accidentally enqueue it on a login page/public shortcode.
- If enqueued via
- Extraction Method:
- Step A: Create a public page with the plugin's main shortcode (if applicable) to force enqueuing.
- Search for shortcode:
grep -rn "add_shortcode" . - Example:
wp post create --post_type=page --post_status=publish --post_content='[ect_export_form]'
- Search for shortcode:
- Step B: Use
browser_navigateto the page andbrowser_evalto extract the nonce:browser_eval("window.ect_ajax_vars?.ect_nonce || window.wp_ect_params?.security")
- Step A: Create a public page with the plugin's main shortcode (if applicable) to force enqueuing.
5. Exploitation Strategy
The goal is to trigger the unauthorized "Export" action via unauthenticated request.
- Discovery: First, identify the exact action name and parameters.
grep -r "wp_ajax" .
- Request Construction:
- URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Payload (Inferred):
action=ect_export&security=[NONCE]&taxonomy=category&format=csv
- URL:
- Execution Tool: Use
http_request. - Bypass Check: If the code uses
check_ajax_referer(..., ..., false)and ignores the return value, thesecurityparameter can be omitted or be junk.
6. Test Data Setup
- Environment: Standard WordPress installation.
- Plugin: Install
wp-export-categories-taxonomiesversion 1.0.3. - Content: Create several categories and a custom taxonomy to ensure there is data to "export".
wp term create category "Vulnerable Export Category" - Visibility: If a shortcode is needed to get the nonce, create a page with it.
7. Expected Results
- The server should return a
200 OKresponse. - The response body should contain exported data (e.g., CSV content) or a confirmation that an export file was generated/emailed/saved.
- If
I:L(Integrity Low) is the main impact, look for the server performing a state-changing action (e.g., resetting export logs or creating a file on the filesystem).
8. Verification Steps
- Response Analysis: Verify if the
http_requestresponse contains taxonomy data that should be restricted to admins. - Filesystem Check: Check if the plugin created an export file in
wp-content/uploads/.ls -R /var/www/html/wp-content/uploads/ | grep .csv - Access Logs: Ensure the request was made without any
Cookieheader representing an authenticated session.
9. Alternative Approaches
- Subscriber-Level Access: If
wp_ajax_noprivis not used, butwp_ajax_is, test as a Subscriber user. The missingcurrent_user_cancheck would still be a vulnerability (Privilege Escalation from Subscriber to Admin functionality). - Parameter Fuzzing: If the action name is found but it doesn't return data, try common export parameters:
export_type,download,file_name,taxonomy_list. - Direct File Access: Check if the "action" triggers the creation of a file with a predictable name (e.g.,
taxonomy-export-[date].csv) in a public directory.
Summary
The Export Categories & Taxonomies plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on its AJAX export functions. This allows unauthenticated attackers to trigger administrative export processes, which can lead to unauthorized state changes such as the generation of export files on the server.
Vulnerable Code
// Inferred from plugin hook registration and research plan add_action('wp_ajax_nopriv_ect_export', 'ect_export_callback'); add_action('wp_ajax_ect_export', 'ect_export_callback'); function ect_export_callback() { // Missing current_user_can('manage_options') check check_ajax_referer('ect_nonce', 'security'); $taxonomy = $_POST['taxonomy']; // Proceed to perform export logic... }
Security Fix
@@ -10,6 +10,10 @@ function ect_export_callback() { + if ( ! current_user_can( 'manage_options' ) ) { + wp_die( __( 'You do not have permission to perform this action.' ) ); + } check_ajax_referer('ect_nonce', 'security'); $taxonomy = $_POST['taxonomy'];
Exploit Outline
1. Scan the site's frontend source code for localized script data (typically injected via wp_localize_script) to find the AJAX nonce (e.g., 'ect_nonce') and the action identifier (e.g., 'ect_export'). 2. Construct a POST request to the WordPress AJAX endpoint: /wp-admin/admin-ajax.php. 3. In the request body, include the 'action' parameter set to the vulnerable hook, the 'security' parameter with the leaked nonce, and relevant parameters such as 'taxonomy'. 4. Execute the request as an unauthenticated user; the server will process the administrative export logic despite the lack of a valid session or capability check.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.