sync-basalam <= 3.0.2 - Authenticated (Administrator+) SQL Injection
Description
The گرویتی فرم فارسی plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 3.0.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 authenticated attackers, with administrator-level access and above, 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:H/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=3.0.2What Changed in the Fix
Changes introduced in v3.0.3
Source Code
WordPress.org SVNI cannot fulfill your request to create a detailed exploitation research plan or provide actionable payloads for this vulnerability. My purpose is to be helpful while ensuring safety, and generating functional exploit instructions for specific software vulnerabilities poses significant security risk…
Show full research plan
I cannot fulfill your request to create a detailed exploitation research plan or provide actionable payloads for this vulnerability. My purpose is to be helpful while ensuring safety, and generating functional exploit instructions for specific software vulnerabilities poses significant security risks.
Instead, I can explain the technical mechanics of the vulnerability mentioned and how developers can prevent such issues.
Understanding the Vulnerability: Authenticated SQL Injection
The vulnerability in the "گرویتی فرم فارسی" (Persian Gravity Forms) plugin (CVE-2026-61955) is classified as an Authenticated SQL Injection. Based on the provided source code for version 3.0.2, the issue stems from improper handling of user-supplied input when constructing database queries.
Vulnerable Code Patterns
In includes/sms/class-sent-list.php, functions like record_count() and get_items() use the $_REQUEST['id'] and $_REQUEST['s'] parameters within SQL LIKE clauses without sufficient protection.
For example:
if ( isset( $_REQUEST['id'] ) ) {
$sql .= ' WHERE `form_id` LIKE "%%' . $wpdb->esc_like( $_REQUEST['id'] ) . '%%"';
}
While $wpdb->esc_like() is used, it is designed only to escape special characters used in LIKE patterns (such as % and _). It does not escape SQL metacharacters like single quotes (') or backslashes (\). Because the resulting query is not processed through $wpdb->prepare(), an authenticated user with high privileges (Administrator) could potentially inject malicious SQL syntax by including a single quote in the id parameter.
The Role of $wpdb->prepare()
In WordPress, the standard defense against SQL injection is the use of the $wpdb->prepare() method. This method uses placeholders (%s for strings, %d for integers, %f for floats) to ensure that data is properly escaped and quoted before the query is executed by the database.
A secure implementation of the code above would look like this:
if ( isset( $_REQUEST['id'] ) ) {
$search = '%' . $wpdb->esc_like( $_REQUEST['id'] ) . '%';
$sql = $wpdb->prepare( "SELECT COUNT(*) FROM {$sent_table_name} WHERE `form_id` LIKE %s", $search );
}
Defensive Recommendations for Developers
- Always use
$wpdb->prepare(): Never concatenate user input or even sanitized variables directly into SQL strings. Always use placeholders. - Validate and Whitelist: For structural parts of a query that cannot be parameterized (like
ORDER BYcolumns orASC/DESCdirections), use a strict whitelist of allowed values. - Sanitize Early, Prepare Late: Use functions like
sanitize_text_field()to clean input for general use, but always rely on$wpdb->prepare()for the final database interaction. - Follow the Principle of Least Privilege: Ensure that database users and application roles have only the minimum necessary permissions.
For more information on secure WordPress development, I recommend reviewing the WordPress Plugin Handbook section on Security and the OWASP SQL Injection Prevention Cheat Sheet.
Summary
The Persian Gravity Forms plugin is vulnerable to authenticated SQL injection because user-supplied parameters in the 'Sent SMS' admin list table are concatenated directly into SQL queries. While the plugin uses esc_like() for search values, it fails to use $wpdb->prepare(), allowing an Administrator to break out of the string literal and execute arbitrary SQL commands to extract data from the database.
Vulnerable Code
// includes/sms/class-sent-list.php:124 public function record_count() { global $wpdb; $sent_table_name = GFPersian_SMS_DB::$sms_table; $sql = "SELECT COUNT(*) FROM {$sent_table_name}"; if ( isset( $_REQUEST['id'] ) ) { $sql .= ' WHERE `form_id` LIKE "%%' . $wpdb->esc_like( $_REQUEST['id'] ) . '%%"'; } return $wpdb->get_var( $sql ); } --- // includes/sms/class-sent-list.php:174 public function get_items( $per_page = 20, $page_number = 1 ) { global $wpdb; $sent_table_name = GFPersian_SMS_DB::$sms_table; $sql = "SELECT * FROM {$sent_table_name}"; if ( isset( $_REQUEST['s'] ) ) { $sql .= ' WHERE `message` LIKE "%%' . $wpdb->esc_like( $_REQUEST['s'] ) . '%%" OR `reciever` LIKE "%%' . $wpdb->esc_like( $_REQUEST['s'] ) . '%%" OR `sender` LIKE "%%' . $wpdb->esc_like( $_REQUEST['s'] ) . '%%"'; } elseif ( isset( $_REQUEST['id'] ) ) { $sql .= ' WHERE `form_id` LIKE "%%' . $wpdb->esc_like( $_REQUEST['id'] ) . '%%"'; }
Security Fix
@@ -126,7 +126,7 @@ $sql = "SELECT COUNT(*) FROM {$sent_table_name}"; if ( isset( $_REQUEST['id'] ) ) { - $sql .= ' WHERE `form_id` LIKE "%%' . $wpdb->esc_like( $_REQUEST['id'] ) . '%%"'; + $sql = $wpdb->prepare( "SELECT COUNT(*) FROM {$sent_table_name} WHERE `form_id` LIKE %s", '%' . $wpdb->esc_like( $_REQUEST['id'] ) . '%' ); } return $wpdb->get_var( $sql ); @@ -176,9 +176,11 @@ $sql = "SELECT * FROM {$sent_table_name}"; if ( isset( $_REQUEST['s'] ) ) { - $sql .= ' WHERE `message` LIKE "%%' . $wpdb->esc_like( $_REQUEST['s'] ) . '%%" OR `reciever` LIKE "%%' . $wpdb->esc_like( $_REQUEST['s'] ) . '%%" OR `sender` LIKE "%%' . $wpdb->esc_like( $_REQUEST['s'] ) . '%%"'; + $search = '%' . $wpdb->esc_like( $_REQUEST['s'] ) . '%'; + $sql = $wpdb->prepare( "SELECT * FROM {$sent_table_name} WHERE `message` LIKE %s OR `reciever` LIKE %s OR `sender` LIKE %s", $search, $search, $search ); } elseif ( isset( $_REQUEST['id'] ) ) { - $sql .= ' WHERE `form_id` LIKE "%%' . $wpdb->esc_like( $_REQUEST['id'] ) . '%%"'; + $search = '%' . $wpdb->esc_like( $_REQUEST['id'] ) . '%'; + $sql = $wpdb->prepare( "SELECT * FROM {$sent_table_name} WHERE `form_id` LIKE %s", $search ); } if ( ! empty( $_REQUEST['orderby'] ) ) {
Exploit Outline
To exploit this vulnerability, an attacker must have Administrator-level privileges. The vulnerability exists within the SMS 'Sent List' administrative page. 1. Log in to the WordPress dashboard as an Administrator. 2. Navigate to the Sent SMS list page, typically accessible via the Persian Gravity Forms submenu (e.g., `/wp-admin/admin.php?page=gfpersian_sent_table`). 3. Identify the search box or the 'id' parameter in the URL. 4. Craft a payload that escapes the double-quoted LIKE clause. Since the vulnerable code is: `WHERE form_id LIKE "%%input%%"`, a payload such as `1" AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND "1"="1` can be injected via the `id` or `s` parameter. 5. Observe the response delay to confirm a successful time-based injection, which can then be adapted to exfiltrate table data or user credentials.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.