wp-admin Β» What is πŸ’‰ SQL injection and How to prevent WordPress SQLi attacks

What is πŸ’‰ SQL injection and How to prevent WordPress SQLi attacks

SQL (Structured Query Language) is a language that allows code to interact with databases. Injecting SQL commands into a vulnerable user input section on your WordPress website such as a contact form or search box is considered an SQL Injection attack. Depending on the actual SQL command, this could purge the database, send the data to unauthorized party, inject additional malware in the database, etc.

wp sqli 1024x431 - What is 💉 SQL injection and How to prevent WordPress SQLi attacks

There are two main kinds of SQL injection:

  • classic SQL injection vulnerability where unfiltered user input lets an attacker send commands to the database and the output is sent back to the attacker.
  • blind SQL injection vulnerability is when the attacker can send commands to the database but don’t receive the database output.

These can further be divided into:

Out of band SQL injectionWhen an attacker uses SQL injection to gain access to a Web application, the database may send error messages, indicating that the SQL query syntax is incorrect. An attacker then runs SQL queries with a series of true or false questions.
Union-based attacksThe SQL UNION statement is used to send requests, and the results are returned as a partial HTTP response. Binding SQL injection is a type of SQL injection attack used by a UNION SQL operator to quickly retrieve required information from a connected database.
Error-Based SQL attacksError-Based SQL Injection is a technique that allows hackers to obtain information about the structure of the attacked server by exploiting error messages supplied by the server. In order to generate error messages and locate vulnerable information such as versions, paths, permissions, etc. hackers make invalid requests on purpose.

Boolean Blind SQL Injection
SQL requests are used to list the databases and based on the response hackers determine if the information was sent correctly. Instead of measuring request time like in Time-Based Blind SQL Injection, instead they combine the expressions TRUE and FALSE.
Time-Based Blind SQL InjectionBlind SQL Time Injection is a technique for calculating response times for various SQL calls to the database. The system will be forced to wait before returning a response, which will be TRUE or FALSE in this case. The hackers can determine whether the input was sent correctly based on the waiting time as well as the response itself.

🔴 CVE-2021-36916 The security vulnerabilities in the Hide My WP plugin up to version 6.2.3 allowed anyone to add get resent admin tokens because of how the IP address is retrieved and how it is used inside of a SQL query.

image 2 - What is 💉 SQL injection and How to prevent WordPress SQLi attacks

By supplying a malicious payload in one of the IP address headers, it would be directly inserted into the SQL query which makes SQL injection possible.

For technical details regarding the SQLi vulnerabilities in Hide My WP plugin by wpWave please visit Pathstack blog.

Q: How to check if your WordPress website is vulnerable to SQL injections?

A: The best way to check if your website is vulnerable to SQL injections is to test it, either manually by inserting code into forms and examining the results, or using tools such as sqlmap or Burp Suite.

Here are some basic stuff that you can manually insert into forms on your WordPress website to check if it is vulnerable to SQLi:

  • The single quote character ' and look for errors
  • Boolean conditions such as OR 1=1 and OR 1=2, and look for differences in the responses
  • Some SQL-specific syntax that evaluates to the base (original) value of the entry point, and to a different value
  • Payloads designed to trigger time delays when executed within an SQL query, and look for differences in the response time.
  • OAST payloads designed to trigger an out-of-band network interaction when executed within an SQL query, and monitor for errors

Use penetration testing tools such as sqlmap or Burp Suite’s web vulnerability scanner to check if your WordPress website is vulnerable to SQLi.

sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers.

931cc311b89df01194096c30176e3481 1024x691 - What is 💉 SQL injection and How to prevent WordPress SQLi attacks

Here are some guides on using sqlmap on WordPress:

See also  ⚠️ What is Cross-site scripting (XSS) and How to prevent WordPress XSS attacks

There are many WAVS (Web Application Vulnerability Scanners) tools such as OWASP ZAP, Wapiti, Arachni, etc.

But according to a study published by ICAICST the Burp Suite Professional had the best results.

maxresdefault 1024x576 - What is 💉 SQL injection and How to prevent WordPress SQLi attacks

Burp also has a BApp Store where you can get the Burp Extender tool and install additional applications such as WordPress Scanner.

Because the harm that SQLi attacks may cause is so great, it’s best to stay watchful and take steps to prevent such an attack from happening in the first place.

Update not just WordPress core, theme and plugin, but also make sure you are using latest PHP and MySQL versions.

WordPress Core, theme and Plugins can be updated from wp-admin dashboard. When a new version of WordPress core, a plugin or theme is available, an alert bubble is displayed in your WordPress Admin Menu and the corresponding theme or plugin is highlighted on Themes and Plugins Screens.

helphub updates bubbles - What is 💉 SQL injection and How to prevent WordPress SQLi attacks

Depending on the hosting panel of your choice (Plesk, cPanel, Aapanel, CWP..) there is an option inside the hosting panel to change PHP version.

To update MySQL you must ask your hosting provider to update it server-wide.

Website backups are critical for WordPress users who want to build a website on their own.
Backing up the site on a regular basis can help us not only save the prior data, but also restore it quickly in the event of technical issues, website attacks, and other problems.

In the past I’ve covered several WordPress backup plugins and methods:

If you are using a dedicated or virtual server I recommend hardening server security with proper mod_security rules, but if this is not a case and you use shared hosting then you can use the .htaccess files.

Add the following code inside your .htaccess file to block MySQL injections, RFI, base64, and other exploits from reaching the database.

<IfModule mod_rewrite.c>
# Enable rewrite engine
RewriteEngine On

RewriteCond %{HTTP_USER_AGENT} (libwww-perl|wget|python|nikto|curl|scan|java|winhttp|clshttp|loader) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (;|<|>|'|"|\)|\(|%0A|%0D|%22|%27|%28|%3C|%3E|%00).*(libwww-perl|wget|python|nikto|curl|scan|java|winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner) [NC,OR]
RewriteCond %{THE_REQUEST} \?\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} \/\*\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} etc/passwd [NC,OR]
RewriteCond %{THE_REQUEST} cgi-bin [NC,OR]
RewriteCond %{THE_REQUEST} (%0A|%0D) [NC,OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http:// [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http%3A%2F%2F [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC,OR]
RewriteCond %{QUERY_STRING} \=PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC,OR]
RewriteCond %{QUERY_STRING} (\.\./|\.\.) [OR]
RewriteCond %{QUERY_STRING} ftp\: [NC,OR]
RewriteCond %{QUERY_STRING} http\: [NC,OR]
RewriteCond %{QUERY_STRING} https\: [NC,OR]
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)/self/(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)cPath=http://(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*iframe.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^i]*i)+frame.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>).* [NC,OR]
RewriteCond %{QUERY_STRING} (\./|\../|\.../)+(motd|etc|bin) [NC,OR]
RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
RewriteCond %{QUERY_STRING} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{QUERY_STRING} concat[^\(]*\( [NC,OR]
RewriteCond %{QUERY_STRING} union([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} union([^a]*a)+ll([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode) [NC,OR]
RewriteCond %{QUERY_STRING} ^(%2d|\-)[^=]+$ [NC,OR]
RewriteCond %{QUERY_STRING} proc\/self\/environ [NC,OR]
RewriteCond %{QUERY_STRING} (sp_executesql) [NC]

RewriteRule ^(.*)$ - [F,L]

  • Avoid using the root user for WordPress database
  • Change table prefix from the default wp_
  • Limit accesses of the SQL user to sensitive directories
  • Block SQL keywords server-wide
  • Disable remote mysql access and block port 3306

Never use the MySQL root user as a database user for your WordPress website. Also, change the default WordPress table prefix from wp_ to something stronger like b223vvy_

During the mysql_install_db process a test database is created and can be fully accessed by all users by default, making it a common target for hackers. It should therefore be removed during post-installation hardening.

Remote access to the server should be disabled and the MySQL instance should be configured to only allow access to permitted hosts. This can be done by editing hosts.deny and hosts.allow files.

Inside the /etc/my.cnf file add a skip-networking entry under the [mysqld] section, MySQL can be configured to listen only to MySQL socket-based communications.

Make sure that my.cnf is only root writable and hat the default location for data at /usr/local/mysql/data is properly secured with the appropriate permissions.

Most instances of SQLi can be prevented by using parameterized queries (also known as prepared statements) instead of string concatenation within the query.

WordPress has a wpdb::prepare function that prepares a SQL query for safe execution.

The following code is vulnerable to SQL injection because the user input is put directly into the query:

if(isset($_POST['submit'])) {
global $wpdb;
$ordernumber = $_POST['ordernmbr'];
$orderfirstname = $_POST['firstname'];
$orderpostnumber = $_POST['postnmbr'];
$ordernumber = stripslashes_deep($ordernumber);
$orderfirstname = stripslashes_deep($orderfirstname);
$orderpostnumber = stripslashes_deep($orderpostnumber);
$result = $wpdb->get_results($wpdb->prepare( "SELECT * FROM         $wpdb->wp_postmeta
WHERE post_id = '$ordernumber' AND meta_value = '$orderfirstname'"));

This code can be easily rewritten in a way that prevents the user input from interfering with the query structure:

global $wpdb;
$tablename = $wpdb->prefix . "my_custom_table";
$sql = $wpdb->prepare( "SELECT * FROM %s ORDER BY date_created DESC",$tablename );
$results = $wpdb->get_results( $sql , ARRAY_A );

Q: What to do when a WordPress website is hacked using SQL Injection?

A: Perform a detailed analysis of the hack, clean files and database, then take further steps to increase security.

Was this post helpful?

Leave a Comment

I enjoy constructive responses and professional comments to my posts, and invite anyone to comment or link to my site.