WordPress is a great example of how open-source software can fuel content creation. As a project of the open-source community, it uses MySQL for its database management. It seamlessly works in the background managing all the data. MySQL is a robust DBMS. It works great with the Apache web server, PHP, and Linux operating system, etc too. However, a WordPress SQL injection can destroy the entire database of your site. According to the book SQL Injection Attacks and Defense by Justin Clarke,
SQL injection is one of the most devastating vulnerabilities to impact a business, as it can lead to exposure of all of the sensitive information stored in an application’s database, including handy information such as usernames, passwords, names, addresses, phone numbers, and credit card details.
An Overview of WordPress SQL Injection
Often, poor coding standards can be blamed for SQLi. Certain parts of the WP installations are more likely to suffer from SQLi. These include:
- Login/Signup forms.
- Contact forms.
- Feedback forms.
- Search parameters.
- Carts.
So basically, all the fields accepting user input are more susceptible. As the unsanitized input can lead to SQL command execution. Successful exploitation of SQLi can lead to:
- Reading contents of the database.
- Modifying or deletion of these contents.
- Accessing sensitive data like login details or credit card info.
- With the right permissions obtaining a reverse shell in some cases.
However, multiple SQLi have been unearthed this year. And all the exploits to exploit them are freely available on Exploit-DB. This can be further clarified from the picture given below.
1) WordPress SQL Injection: Executing Commands
An unsanitized user input can lead to SQLi vulnerability in WordPress. It could be some buggy plugin with the vulnerable parameter. For instance look at the URL:
www.yoursite.com/index.php?vulnerable_parameter=1
As the following parameter is vulnerable, it can be used to perform database operations. Since WordPress uses MySQL as DBMS, some specific commands are used. In case the parameter is ‘Error Based And’ injectable. Then, to enumerate the users and their privileges, the following code is appended.
1' and SELECT user FROM mysql.user; — priv
. This code enumerates the WordPress users and their roles. The next step would be to get user passwords. The following code can do the trick.
1' and SELECT host, user, password FROM mysql.user; — priv
. This code can reveal the WordPress user password hashes. However, the hashes would still need a brute force attack to get plain text. After gaining the credentials successfully, they could be used to connect to the database. Simply by accessing the URL
mysql://USERNAME:[email protected]:3306/testdb
. MySQL uses the port 3306 for TCP/IP connections to the internet. However, if the database connection is limited to localhost only, then the credentials are useless. In that case, the databases could be listed by the following code.
1' and SELECT distinct(db) FROM mysql.db — priv
. Similarly, the attacker can proceed to further modify and manipulate the database. However, it can only be accomplished if the database is running with admin privileges on the system.
2) WordPress SQL Injection: Bypassing Logins
WordPress in the past has suffered from login bypass vulnerabilities. Simply appending a string like' or 1=1--
, ' and 1=1--
etc can allow unauthorized access. As was the case of CVE-2018-3810. The issue lied within the Oturia Smart Google Code Inserter plugin. The versions before 3.5 were affected. The vulnerability allowed unauthenticated attackers to insert arbitrary code. The code could be JavaScript or HTML visible on all the pages of the WordPress site. The parameter vulnerable was sgcgoogleanalytic. Moreover, the saveGoogleCode()
function in smartgooglecode.php failed to check for user authorization. So this allowed any arbitrary user to inject code. Also, prepared statements were not used by the saveGoogleAdWords()
function of smartgooglecode.php. Neither was the user input sanitized in$_POST["oId"]
variable. This unsanitized input could execute SQL queries.
curl -k -i --raw -X POST -d "action=saveadwords&delconf=1&oId[]=1 OR
1=1--&ppccap[]=ex:mywplead&ppcpageid[]=1&ppccode[]=bb&nchkdel1=on" "
http://localhost/wp-admin/options-general.php?page=smartcode" -H "Host:
localhost" -H "Content-Type: application/x-www-form-urlencoded"
1 or 1=1--
helps in bypassing the authentication. However, this is just one example. So, at times login panels could be suffering from login bypass vulnerabilities.3) WordPress SQL Injection: Going Blind
A blind SQL injection evaluates boolean queries(true or false). So, it then guesses the data based on the response. This makes data retrieval slow. Moreover, the data retrieval becomes noisy due to multiple requests generated for a small amount of data. At times the blind injection could be time-based. For instance look at the code below.
http://www.site.com/vulnerable.php?id=1' waitfor delay '00:00:10'--
Here, the server shall wait for 1o minutes before sending results. So, for instance, say if the first letter of the table is ‘D‘, the server will wait for 10 seconds before confirming. This makes attacks considerably slow. But it still leaks sensitive data. However, attackers often obtain output via DNS Queries to speed up this type of attack.
The recent findings of a blind SQLi were in the WordPress Plugin Gift Voucher 1.0.5. The vulnerability lied in the template_id parameter. To exploit it, the attacker could give could inject the tempelate_id parameter like this.
www.yoursite.com/wp-admin/admin-ajax.php?action=wpgv_doajax_front_template&template_id=1 AND 4448=4448
As evident from the code above, it suffers from the boolean-based blind SQLi. Similar issues were found in Plugin Arigato Autoresponder and Newsletter v2.5. However, this attack needs admin privileges to exploit.
4) WordPress SQL Injection: Cookie Gone Wrong
At times, the cookie parameter can execute SQL commands which could lead to WordPress SQL injection attack. As was in the case of WordPress Plugin Survey & Poll 1.5.7.3. It worked something like this
Step1: Look out for poll or survey asking for answers.
Step2: Wp_sap will be assigned to a value while answering these questions.
Step3: Open the cookie manager and add the following code.
["1650149780')) OR 1=2 UNION ALL SELECT 1,2,3,4,5,6,7,8,9,@@version,11#"]
. Here it is noteworthy that the or statement should always evaluate to false. As the application is reflecting the result of the first query.
Step4: So, now finally open thesss_params
from source code. It shall display the database version. Similarly, it can be used to get more results. Thus improper handling of parameters can lead to a WordPress SQL injection attack.
5) WordPress SQL Injection: Automatic Exploitation
When it comes to automation nothing beats Sqlmap. This tool integrates with the database to make exploitation easy. All the above-given issues can be exploited hassle-free using Sqlmap. However, some special features of Sqlmap are:
- Retrieval of data within a specific range.
- The output of blind injection via DNS Queries.
- WAF fingerprinting.
- Customized tamper scripts to evade detection for multiple firewalls.
- Great support for various reverse shells.
- Integration with the Metasploit framework.
As seen in the image, theleauge_id
parameter of the WordPress site is exploited. The user just needs to add minimum info and Sqlmap takes care of the rest. Moreover, the threads option can be explicitly set to control the number of requests made. It also gives the option to route requests through the TOR network. This makes it difficult for web admins the determine the real IP of an attacker.
Look through your site logs to determine if Sqlmap has been run against your site. Typically you would notice multiple SQL requests through parameters. Also, a new tool called Atlas has been released. This tool can customize the tamper scripts for each site. Thus making SQLi stealthy and deadlier!
6) Secure Coding Practices
Often, WordPress SQL injection is the result of poor coding practices. Always usewpdb->prepare
to sanitize the user input.
$query = array_shift($args);
$query = str_replace("'%s'", '%s', $query);
$query = str_replace('"%s"', '%s', $query);
$query = str_replace('%s', "'%s'", $query); // quote the strings
array_walk($args, array(&$this, 'escape_by_ref'));
return @vsprintf($query, $args);
.
In this code snippet, this function here is creating a non-prepared query. It is basically sanitizing the input. So calling it prepared may be misleading at times. However, all the inputs are treated as a string because of the placeholder ‘%s‘. So, always usewpdb->prepare
while creating new input parameters. For example.
$wpdb->prepare( "SELECT * FROM {$wpdb->prefix}_votes WHERE post_id = %d AND username = %s", $post_id, $username );
. Here, the %d is a placeholder for an integer. Similarly, %s is a placeholder for a string. Thus it eliminates the possibility of a WordPress SQL injection attack. Because it would be finally treated as a string and integer.
WordPress SQL Injection Protection
1) WordPress SQL Injection Protection: Damage Control
- Disable admin privileges to the database. This would make it read-only for the attacker.
- Now proceed to clean the UDF files used by the attacker to obtain OS shell.
- Then, change the encrypted passwords to strong values.
- Check for port 3306. If it is open on the internet block it.
2) WordPress SQL Injection Protection: Database Cleanup
Step1: See all your tables using the commandshow tables;
. Check for a table titled Sqlmap.
Step2: If present, that means Sqlmap has been used against your site. Delete the table usingDrop table Sqlmap;
.
Step3: Now, look out for new users if any using the following code.
Select * from users as u
AND u.created > UNIX_TIMESTAMP(STR_TO_DATE('Oct 15 2018', '%M %d %Y '));
. Manipulate the date string to see when the rogue user was created.
Step4: Delete the rogue user using the following command. DROP USER 'malicious'@'localhost';
.
Step5: Change your passwords to a secure one. Use the following code for it.
update users set pass = concat('ZZZ', sha(concat(pass, md5(rand()))));
.
3) WordPress SQL Injection Protection: Updates
Updates are a vital part of the security routine. Multiple vulnerabilities are discovered each day. So your best defense against them is to stay updated. Moreover, use reputed plugins. Avoid using null themes. Keep your plugins updated too along with core files!
4) WordPress SQL Injection Protection: Firewall
A firewall can detect and block the WordPress SQL injection attacks. Some great security solutions are available on the internet. Like the one at Astra protects your site against SQLi and 80+ other attacks. This great tool is economical and user-friendly. It can give you one-stop info about SQLi attacks blocked daily. Try Astra and say goodbye to WordPress SQL injection attacks!
5) WordPress SQL Injection Protection: WordPress Security Audit or Pentesting
SQL Injection or SQLi is one of the most common attacks seen against WordPress sites. When a website is vulnerable to SQL Injection, an attacker can execute SQL commands by inserting malicious code in the input fields on the said website. With a steady rise in such attacks, security audits have become essential in keeping the WordPress websites safe, as even the WordPress security plugins promising better security has been compromised in the past. The best way to secure a WordPress website is to have regular Security Audits which comprise of simulated attacks including SQLi attacks can make sure that there are no stones left unturned and thus, identify any existing SQL injection vulnerabilities before an attacker can find it and use it.
Astra provides a comprehensive security audit for your WordPress website with 80+ active tests, a right mix of automated & manual testing.
[…] Plugin is prone to an SQL injection vulnerability because it fails to sufficiently sanitize user-supplied data before using it in an SQL query. This […]