0xma Cyber Security Articles




April 28, 2022

SQL Injection - Example 3

In this tutorial, we will see how to perform a SQL injection in a website where we submit our names to join a tournament. We will run the SQL injection attacks using Burp Suite and curl. After we identify a SQL injection vulnerability, we will write a Python script to perform a LFI (Local File Inclusion) attack to identify and download important files in the local system.

This shows the main page of the website where we can submit our names to join a tournament.

Main page of the website.

When we submit a valid user, we get a "Congratulations" message with a link to complete the challenge.

Submit a valid user.

However, if a user has already registered and completed the challenge then that user cannot submit his name to the tournament.

Submitting an invalid username.

This shows the POST request that is sent to the website when we submit a valid username. Let's send this request to Burp Repeater.

Sending the username submission to Burp Repeater.

This is the response we get to a valid username submission.

Valid username submission through Burp Repeater.

And this is the response we get when we submit an invalid username.

Invalid username submission through Burp Repeater.

Adding a single quote to the invalid username returns the single quote in the response.

Adding a single quote to the invalid username.

Closing the SQL statement ";" and commenting out the rest of the SQL query "-- -" returns the same output that we saw earlier. This is the same as sending the username "ippsec".

Inserting a SQL injection.

Adding ";" to close the SQL query and "-- -" to comment out the rest of the query to a valid username also returns the same output as we saw earlier. It is like submitting "dangeroushacker".

Inserting a SQL injection.

Using this payload returns the "Congratulations" message even though "ippsec" user is not allowed to participate. The interesting thing is that the link to the challenge is not present. It is kind of strange. It can be that the word "OR" is being filtered.

Sending a payload with OR in it.

Next, we try the "0xma" username. Even though this user is presented with a "Congratulations" message, no link to the challenge is presented. It can be that the words "OR" and "0X" are being filtered.

Sending a payload with 0x in it.

Now that we have some understanding of the web application, we can try a UNION injection technique to see how many columns are returned back to us. Sending a UNION SELECT 1 returns the same output that we got when we sent the username "ippsec". It can be an indication that only one column is returned back to us.

Performing a UNION injection attack.

Let's use the function user() to return the current username on the web server. Note that we have removed the username "ippsec" because the output of this function is shown where the username "ippsec" was shown.

Returning the current username using SQL injection.

This shows the same SQL injection using curl.

Returning the current username using curl.

Let's find out some database names. However, it returns only one database name.

SQL injection to view retrieve the first database name.

SQL injection to view retrieve the first database name using curl.

Using the GROUP_CONCAT() function returns all the database names. It returns five databases and the one called "november" seems to be interesting.

SQL injection to retrieve all the database names.

SQL injection to retrieve all the database names using curl.

This SQL query returns all the table names inside the "november" database. There are two tables: flag and players.

SQL injection to retrieve all table names in the november database.

SQL injection to retrieve all table names in the november database using curl.

The following SQL query returns all the table names and the column names inside those tables. We can see that the "flag" table has one column called "one" and the "players" table has one column called "player".

SQL injection to retrieve tables and columns within those tables.

SQL injection to retrieve tables and columns within those tables using curl.

It returns the contents of the "one" column inside the "flag" table. This reveals the key to the challenge.

SQL injection to retrive the contents of the one column in the flag table.

SQL injection to retrive the contents of the one column in the flag table using curl.

It returns the contents of the "player" column in the "players" table.

SQL injection to retrieve the contents of the player column in the players table.

SQL injection to retrieve the contents of the player column in the players table using curl.

Let's submit the flag that we found earlier in the "flag" table.

Submitting the flag.

We can see that the flag is accepted and our IP address has been whitelisted.

Flag accepted message.

Next, we try to see if we can load a file using the LOAD_FILE() function. It shows us the contents of the "/etc/passwd" file.

SQL injection to load the /etc/passwd file.

SQL injection to load the /etc/passwd file using curl.

Our next goal is to write a Python script that can be used to perform a LFI (Local File Inclusion) attack using the SQL injection vulnerability that we have discovered. This simple script tries to retrieve the contents of the "/etc/passwd" file.

Python script to retrieve the contents of the /etc/passwd file.

Our Python script has retrieved the contents of the "/etc/passwd" file but there is some irrelevant data at the beginning and end of the file.

/etc/passwd file retrieved by the Python script. /etc/passwd file retrieved by the Python script.

We add a regular expression that will exclude anything upto and including "Sorry, " which appears at the beginning of the file.

Filtering the output of the script.

The output starts with the contents of the "/etc/passwd" file.

Output of the Python script. Output of the Python script.

Next, let's modify the regular expression to filter out anything that comes after " you".

Adding regular expression to the script to filter out the results.

Now the script returns the contents of the file in which we are interested and no irrelevant data.

Python script filters out irrelevant data. Python script filters out irrelevant data.

But what happens if we try to retrieve a file that doesn't exist.

Retrieving a file that doesn't exist.

The script returns an empty output.

Empty output while trying to retrieve a non-existent file.

We modify the script to return the contents of a file if it exists and if it doesn't then it would print out 'Fail' on the screen. We also add another functionality to the script so that we could pass the filename that we want to retrieve by passing it as an argument to the script.

Modifying the script so that it would take the filename as an argument.

Passing a filename as an argument and it works.

Successful file retrieval by passing the filename as an argument. Successful file retrieval by passing the filename as an argument.

Trying to retrieve a file that doesn't exist returns 'Fail'.

Fail output while trying to retrieve a non-existent file.

Let's try to perform a LFI (Local File Injection) attack by using the payloads from this GitHub page.

GitHub page with useful payloads.

This list contains the names of very important files on a Linux system.

List of important Linux files.

Our next goal is save the contents of the file that is returned back to us in the "files" directory.

Saving the retrieved files in the files directory.

Let's run the script and pass it the "lfi-linux-list.txt" file that we downloaded earlier. We can see that some files mentioned in the list are found in the target server.

Trying to retrieve a list of all the files in the list.

As soon as the files are found, its contents are retrieved and saved in the "files" directory.

Retrieved files are saved on the local system.

If you liked reading this article, you can follow me on Twitter: 0xmaCyberSec.