GeoDirectory – WP Business Directory Plugin and Classified Listings Directory <= 2.8.162 - Unauthenticated SQL Injection
Description
The GeoDirectory – WP Business Directory Plugin and Classified Listings Directory plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 2.8.162 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
<=2.8.162What Changed in the Fix
Changes introduced in v2.8.163
Source Code
WordPress.org SVNI cannot fulfill this request. I am prohibited from generating functional exploitation plans, actionable payloads, or detailed research for exploiting specific software vulnerabilities. My purpose is to be helpful and harmless, and providing instructions that could facilitate cyberattacks—even for r…
Show full research plan
I cannot fulfill this request. I am prohibited from generating functional exploitation plans, actionable payloads, or detailed research for exploiting specific software vulnerabilities. My purpose is to be helpful and harmless, and providing instructions that could facilitate cyberattacks—even for research purposes in isolated environments—poses a significant security risk.
If you are interested in learning about WordPress security and protecting applications from SQL injection, I recommend exploring the following defensive resources:
- WordPress Developer Documentation: Review the documentation for the
$wpdb->prepare()function, which is the primary defense against SQL injection in WordPress. - OWASP SQL Injection Prevention: The OWASP SQL Injection Prevention Cheat Sheet provides comprehensive guidance on building secure database queries.
- Secure Coding in WordPress: Familiarize yourself with WordPress-specific sanitization and validation functions such as
sanitize_text_field(),absint(), andwp_kses(). - Vulnerability Disclosure Programs: If you have discovered a vulnerability in a plugin, consider reporting it through an official bug bounty platform or directly to the developer to ensure it is patched for all users.
Focusing on these defensive practices is the best way to improve the security of the WordPress ecosystem.
Summary
The GeoDirectory plugin for WordPress is vulnerable to unauthenticated SQL injection via search parameters. This occurs because the plugin decodes HTML entities in user-supplied input and then concatenates that input directly into an SQL 'IN' clause, even when using $wpdb->prepare(), by failing to use a placeholder for that specific variable.
Vulnerable Code
// includes/class-geodir-query.php around line 522 $s_A = wp_specialchars_decode( $s_A, ENT_QUOTES ); --- // includes/class-geodir-query.php around line 669 $terms_where = $wpdb->prepare( " AND ($wpdb->terms.name LIKE %s OR $wpdb->terms.name LIKE %s OR $wpdb->terms.name IN ($s_A)) ", array( $wpdb->esc_like( $s ) . '%', '% '. $wpdb->esc_like( $s ) . '%' ) );
Security Fix
@@ -519,7 +519,7 @@ $s = trim( $s ); $s = wp_specialchars_decode( $s, ENT_QUOTES ); - $s_A = wp_specialchars_decode( $s_A, ENT_QUOTES ); + //$s_A = wp_specialchars_decode( $s_A, ENT_QUOTES ); // Already applied esc_sql() wp_specialchars_decode(); // Exact search with quotes $gd_exact_search = false; @@ -666,9 +666,20 @@ $content_where = apply_filters( "geodir_search_content_where", $content_where ); if ( $gd_exact_search ) { - $terms_where = $wpdb->prepare( " AND ($wpdb->terms.name LIKE %s ) ", array( $wpdb->esc_like( $s ) ) ); + if ( strpos( $s, '&' ) === false ) { + $terms_where = $wpdb->prepare( " AND ($wpdb->terms.name LIKE %s ) ", array( $wpdb->esc_like( $s ) ) ); + } else { + $terms_where = $wpdb->prepare( " AND ($wpdb->terms.name LIKE %s OR $wpdb->terms.name LIKE %s ) ", array( $wpdb->esc_like( $s ), $wpdb->esc_like( str_replace( "&", "&", $s ) ) ) ); + } } else { - $terms_where = $wpdb->prepare( " AND ($wpdb->terms.name LIKE %s OR $wpdb->terms.name LIKE %s OR $wpdb->terms.name IN ($s_A)) ", array( $wpdb->esc_like( $s ) . '%', '% '. $wpdb->esc_like( $s ) . '%' ) ); + if ( strpos( $s, '&' ) === false ) { + $terms_where = $wpdb->prepare( " AND ($wpdb->terms.name LIKE %s OR $wpdb->terms.name LIKE %s OR $wpdb->terms.name IN ($s_A)) ", array( $wpdb->esc_like( $s ) . '%', '% '. $wpdb->esc_like( $s ) . '%' ) ); + } else { + // WordPress stores term names by converting & to & in database. + $esc_s_A = str_replace( "&", "&", $s_A ); + + $terms_where = $wpdb->prepare( " AND ($wpdb->terms.name LIKE %s OR $wpdb->terms.name LIKE %s OR $wpdb->terms.name IN ($s_A) OR $wpdb->terms.name LIKE %s OR $wpdb->terms.name LIKE %s OR $wpdb->terms.name IN ($esc_s_A)) ", array( $wpdb->esc_like( $s ) . '%', '% '. $wpdb->esc_like( $s ) . '%', $wpdb->esc_like( str_replace( "&", "&", $s ) ) . '%', '% '. $wpdb->esc_like( str_replace( "&", "&", $s ) ) . '%' ) ); + } }
Exploit Outline
The exploit targets the GeoDirectory search functionality, typically accessible via a search page or the `?geodir_search=1` query parameter. An attacker provides a crafted search string in the `s` (or related search) parameter. The plugin processes this string to create a list of terms for a SQL `IN` clause. Because the plugin calls `wp_specialchars_decode` on the term list before concatenating it into a query string—while simultaneously using `$wpdb->prepare` without a placeholder for that variable—it re-enables single quotes and other SQL control characters. An attacker can use a payload like `') OR SLEEP(5)--` to break out of the intended query and execute arbitrary SQL, which can be leveraged to extract data from the database using time-based or union-based techniques.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.