PHP is probably one of the most vulnerable languages for SQL injection (SQLi), mainly because many developers build queries dynamically using strings. PHP has prepared statements in its native class named PHP Data Objects (PDO). Even with prepared statements available to WordPress plugin authors, it’s still common for plugin developers to work with dynamically built strings. This habit leads to many WordPress plugin vulnerabilities to SQL injection.

If you’re like me, I learn better with examples. This blog post uses a real-world example of SQL injection from CVE-2026-0683, a January 2026 SQLi vulnerability found in the plugin SupportCandy – Helpdesk & Customer Support Ticket System. The plugin author built SQL queries from user input and did not use prepared statements, which makes the code vulnerable to SQL injection attacks. It’s a great way to show examples of SQL injection in the wild for better understanding of the exploit.

SQL Injection Explained

Fully explaining SQL injection would take an entire novel, but we’ll go over a brief explanation to give you a background on how the attack works and what can happen if you don’t prevent SQL injection from affecting your site. WordPress plugin authors should also be aware of the right secure coding practices in PHP to avoid opening vulnerabilities on their customer sites. The following examples are limited in scope, but most attacks can be mitigated with prepared statements.

For a simple explanation, let’s say that you have a form where users can retrieve their information based on their name. On the form, you have a textbox that requires a user to enter their first name. Instead of entering their first name, a user enters the following text:

‘ or 1=1 --

Your SQL query (MySQL in the case of a WordPress plugin) is built in PHP code, and you construct the query to retrieve data using the syntax:

SELECT * FROM customers WHERE first_name = ‘ firstname ‘;

The firstname variable is retrieved from your site’s form. If a user enters the malicious SQLi code, the query turns into:

SELECT * FROM customers WHERE first_name = ‘ ‘ or 1=1 --‘;

The above query returns all columns where the first name is an empty string, or 1=1, which is always true. The double hyphens ( — ) comment out the ending tick character ( ‘ ) so that the malicious code does not cause a syntax error, but instead returns the entire table of customers. 

SQL injection can be further categorized into blind SQL injection and in-band SQL injection. Blind SQL injection means that errors or data are not returned directly to the attacker, so the attacker needs to infer a response to follow up with additional attacks. It usually involves additional attacks to complete a dump of a database table. Blind SQL injection is also called inferential SQL injection, because the attacker must infer database activity from results of malicious code. In-band SQL injection returns data directly to the attacker, so it’s a preferred method for its instant results. Our example is an in-band SQL injection since data is immediately returned.

The above example is a very simple explanation. SQL injection can be much more complex, and most SQL injection attacks are scripted. If you don’t prevent an SQL injection attack, entire databases can be dumped and stolen. Usually, the data is then sold on darknet markets. At worst, an attacker might be able to run administrative tasks on the database and take over the server. This consequence is usually from using a high-privilege user for your public application database queries.

PHP SQL Injection Examples Using SupportCandy Code

With a simple explanation of SQL injection, we can go into a real-world example using the SupportCandy plugin vulnerability. The SupportCandy plugin is used as a help desk and customer support ticketing system. It has over 10,000 installs, so the vulnerability puts at least 10,000 sites at risk of being exploited. We’re going to look at snippets of code to explain how and why the plugin is vulnerable to SQL injection attacks.

The vulnerability was originally reported by a Wordfence researcher in January 2026. The report indicates that the plugin has the same SQLi vulnerability in several of its  functions, but we’ll cover one function to illustrate the way PHP code introduces exploit opportunities for attackers. Note that the plugin developer hasn’t uploaded a security patch as of this writing, so if you have this plugin, you should likely disable it until a fix is published.

The function we’ll look at is set_add_saved_filter found on line 1265. If you look at the function code, you can see that the function is used to apply a filter to a query that retrieves a list of tickets for administrators to review. The function is too long to copy and paste here, but the security bug can be seen in the following code located at line 1288 in the function:

$filters = isset( $_POST['filters']['filters'] ) ? 
     sanitize_text_field( wp_unslash( $_POST['filters']['filters'] ) ) : '';

Notice that the plugin author used the function sanitize_text_field. This function protects the site from Cross-Site Scripting (XSS), which is another high-risk vulnerability. It does not, however, protect from SQL injection. The coder also uses the function wp_unslash. The wp_unslash function removes backslashes ( \ ) from a string. It prevents some SQL injection where the backslash is used to send malicious code to the database, but as you can see from our example, not every SQL injection attack uses backslashes. 

The backslash tells databases to use a literal character instead of using it as code. An example is if you have the name “O’Reilly” stored in the database, the backslash tells the database to use the tick mark as a string character and not the ending of query syntax. Some SQL injection attacks might send “O\\\’Reilly” to the database, which can be dangerous depending on how the code strips and processes the string. For example, MySQL has a NO_BACKSLASH_ESCAPES setting which causes the database to use backslashes as a literal part of the query string. This could cause issues if you have backslashes in queries.

Going back to the PHP statement, you can see that none of the two safety functions help with SQL injection. The $filters variable is then used later in the function starting at line 1307 to build the SQL query:

$saved_filters[ $index ] = array(
       'label'         => $label,
       'parent-filter' => $parent_filter,
       'filters'       => $filters,
       'sort-by'       => $sort_by,
       'sort-order'    => $sort_order
);

The filters part of the query could contain malicious code since it’s a user-generated value, and none of the sanitization functions handle SQL injection attacks. If you are a WordPress developer, you should avoid building SQL queries using this strategy.

How to Prevent a SQL Injection Attack

For PHP and WordPress plugin developers, the best way to avoid SQL injection is to use prepared statements. Prepared statements are similar to SQL Server stored procedures where tick marks and other malicious code will be interpreted as literals instead of a part of the SQL query syntax. It does eliminate the possibility of SQL injection entirely, but it does limit your risk of introducing database vulnerabilities in your code.

In addition to practicing safe coding habits, site owners can use CloudFlare as a web application firewall (WAF). CloudFlare detects malicious code, mainly XSS, SQL injection, and other possible exploits and blocks the request. For WordPress users, Wordfence is another layer of defense specific for WordPress sites.

To stay up to date with the latest vulnerabilities, CVEs, and WordPress secure coding, sign up to my newsletter for monthly updates.

Join Our Newsletter
get weekly access to the latest hacks, tricks, and updates