XSS Vulnerabilities Exploitation Case Study
Introduction
In the earlier articles about SQL Injection, we discussed how SQL Injection vulnerabilities can be identified and exploited. We also discussed what coding mistakes cause SQL Injection vulnerabilities. This article provides a case study of an SQL Injection vulnerability from discovery to exploitation. We will also review the source code to understand the root cause. A vulnerable shopping cart application is used to demonstrate this.
Learn Secure Coding
Searching for vulnerable apps
Even though SQL Injection is one of the oldest web application vulnerabilities, they are still seen in web applications. Searching for the keyword SQL Injection in exploit-db.com provides a long list of applications vulnerable to SQL Injection as follows.
This shows that SQL Injection vulnerabilities are not dead and developers may still make the same old mistakes that will lead to SQL Injection vulnerabilities.
SQL Injection case study
One can choose any application from the list shown in exploit-db. However, we will use a custom shopping cart in this article to demonstrate SQL Injection.
The target application is available at the following URL.
Accessing the application looks as follows.
As we can notice, this web page has Categories and Brands.
Burp proxy has been configured and clicking one of the Categories (Leafy Vegetables in this case) shows the following request.
Host: 192.168.1.74
Content-Length: 32
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.1.74
Referer: http://192.168.1.74/edss/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cookie: PHPSESSID=4n63m1seukeqjbgsp7c47oq2p1
Connection: close
get_selected_category=1&cat_id=3
As we can notice the request has two POST parameters, which can be tested for SQL Injection.
Let us save this request in a file called sqli.txt for later use and forward the request to the server. The response looks as follows.
Testing for SQL Injection
Now, our goal is to check if there is any SQL Injection vulnerability in the parameters identified in the preceding request. We can modify the request being sent to the server by adding a single quote at the end of the parameter value and observe the response.
Let us test the cat_id parameter by adding a single quote after it’s value 3, which looks as follows.
Following is the response we received.
There are no SQL errors in the response. In some instances we will only get a custom error page rather than a detailed error. In such cases, we need to go for other testing techniques instead of searching for errors in the response. Let us add another single quote and observe how the application behaves.
Following is the updated request.
Following is the response received from the application.
Clearly, the response is different from what we received in the first case. This is an indication that the application could be vulnerable to SQL Injection. We can confirm the vulnerability by adding another single quote. If we receive the same response that we got in the first case, that confirms SQL Injection vulnerability.
Following is the updated request.
Following is the response received.
This response confirms that the parameter is vulnerable to SQL Injection.
Using Logical operators
Another way to identify SQL Injection to pass logical expressions to the database along with the URL. This is to understand how the database is responding. So let us send a request with the payload shown below.
Following is the response.
The page is properly loaded. Let us update the payload as follows.
If this payload is executed by the database, the page should not load the content properly as the condition ‘1’=’2’ is going to result in a false condition.
Following is the response.
This confirms that the application is vulnerable to SQL Injection. We can also use time based injection techniques to confirm the vulnerability.
Exploiting SQL Injection
As discussed in earlier articles, we can use both manual as well as automated techniques to exploit SQL Injection vulnerabilities. The following payload retrieves the database name.
The response looks as follows.
As we can notice in the preceding figure, edss is the database name. Though we can manually extract the data from the database, using an automated tool like sqlmap will make exploitation a lot easier.
Automated exploitation using sqlmap
We have saved the POST request in a file named sqli.txt earlier. Let us launch a terminal in Kali Linux and run the following command.
The preceding command launches sqlmap and takes sqli.txt as input. We are using -p for specifying that cat_id is the place where sqlmap should inject its payloads. --dbs is the flag that tells sqlmap to get the databases available.
After running the command, you should see the following.
[*] edss
[*] information_schema
[*] mysql
[*] performance_schema
As we can notice, sqlmap found available databases and edss appears to be a custom database. So, we can use the edss database and ask sqlmap to extract tables from it using the following command.
After running the preceding command, we should be able to see the following table names from the database edss.
[9 tables]
+-----------------+
| flag |
| brands |
| cart |
| categories |
| customer_orders |
| payment |
| products |
| reviews |
| users |
+-----------------+
We can choose any of the extracted tables here to dump the data from. Let us pick the users table as it may contain credentials. The following command can be used to extract the column names from the table users.
Following is the output of the preceding command.
Table: users
[8 columns]
+------------+------------------+
| Column | Type |
+------------+------------------+
| password | varchar(100) |
| address1 | varchar(300) |
| address2 | varchar(300) |
| email | varchar(300) |
| first_name | varchar(300) |
| last_name | varchar(100) |
| mobile | varchar(20) |
| user_id | int(10) unsigned |
+------------+------------------+
As we can notice, we got eight different columns.
Finally, we need to dump all the data from the table users. We can do it using the following command.
The preceding command dumps all the data from the table users. We can explicitly mention the column names if we want to extract data only from some specific columns.
If sqlmap finds that the passwords are in hashed format, it will prompt the user and attempt to crack them as follows.
[06:12:42] [INFO] fetching entries for table 'users' in database 'edss'
[06:12:42] [INFO] recognized possible password hashes in column '`password`'
do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] N
do you want to crack them via a dictionary-based attack? [Y/n/q] Y
[06:13:07] [INFO] using hash method 'md5_generic_passwd'
what dictionary do you want to use?
[1] default dictionary file '/usr/share/sqlmap/data/txt/wordlist.tx_' (press Enter)
[2] custom dictionary file
[3] file with list of dictionary files
> 1
[06:13:10] [INFO] using default dictionary
do you want to use common password suffixes? (slow!) [y/N] N
[06:13:13] [INFO] starting dictionary-based cracking (md5_generic_passwd)
[06:13:13] [WARNING] multiprocessing hash cracking is currently not supported on this platform
[06:13:15] [INFO] cracked password '1q2w3e4r5t' for hash '97db1846570837fce6ff62a408f1c26a'
The following screenshot shows that the hashes are cracked and clear text passwords are shown alongside their hashes.
This shows how easy it is to exploit SQL Injection vulnerabilities using an automated tool like sqlmap.
Reviewing the source code
Following is the source code responsible for retrieving items selected by the user.
if(isset($_POST["get_selected_category"])){
$id = $_POST["cat_id"];
$query = "SELECT * from products where product_cat='$id'";
}
else if(isset($_POST["get_selected_brand"])){
$id = $_POST["bid"];
$query = "SELECT * from products where product_brand='$id'";
}
As highlighted, the application takes user input and concatenates it to the existing query to form the final query. If you notice, there is no sanitization performed on the user input thus leaving the application vulnerable to SQL Injection.
Learn Secure Coding
Conclusion
This article has provided a case study of SQL Injection vulnerability in a custom shopping cart application. We have also explored exploit-db.com to see if we can find any vulnerable applications. It is apparent that SQL Injection vulnerabilities are still real and they can cause severe impact if exploited. In the next article of this series, we will cover how developers can prevent SQL Injection vulnerabilities in their applications.