SQL injection attack, listing the database contents on Oracle

In this post we will walk step by step on how to solve SQL injection attack, listing the database contents on Oracle on PortSwigger Academy. This lab’s difficulty is Practitioner and it is the sixth lab in the SQL Injection labs on Portswigger. Our objective is to login as the administrator user.

Link to lab: https://portswigger.net/web-security/sql-injection/examining-the-database/lab-listing-database-contents-oracle

To begin the lab we need to click the Access the Lab button. Burp Suite Community Edition is all we need to solve this lab.

As we begin the lab we encounter a shop page showcasing various categories. It’s worth noting that the categories may differ from the screenshot as PortSwigger Labs can vary the content with each lab session.

When we click on the ‘Accessories’ page we’re greeted with two distinct sections of text. The first section serves as the header, while the second section constitutes the body of the content.

Using Burp Suite we can send this Accessories GET request to Repeater to analyze. This will allow us to send one request at a time to analyze HTTP Responses.

Given our objective of identifying SQL Injection vulnerabilities it is important to examine all areas where user input may be present.

To begin testing we can insert a single quote into the ‘category’ parameter. The server responds with a 500 Internal Server Error.

When we insert a second quote into the ‘category’ parameter the application responds with a 200 OK Response. This strongly suggests that we have identified a potential injection point for SQL Injection.

Our next step involves identifying the number of columns within the database table. We can achieve this by carefully analyzing the HTTP Responses and using an ‘order by’ clause. This technique entails crafting payloads with ‘order by <number>’ and incrementing the number to determine the exact count of columns in the database table.

When an ‘order by’ statement returns a result less than or equal to the actual number of columns we should observe a 200 HTTP response code. If the ‘order by’ statement exceeds the number of columns the response will typically be a 500 Internal Server Error. This process will help us determine the correct number of columns to proceed with our SQL Injection.

With the server returning a 500 with order by 3 we can determine the correct number of columns in the table is 2.

GET /filter?category=Accessories'+order+by+2--+-

Similar to previous SQLi Lab walkthroughs we will now use a union statement to obtain data from the database.

Attempting to use a Union Select Query we are presented with a 500 Internal Server Error.

This is because to query from an Oracle database we must include a table. In this case we can include the dummy table dual.

Adding from dual results in the query running successfully and we receive a 200 OK response, meaning we are able to continue our attack.

GET /filter?category=Accessories'+union+select+null,+null+from+dual--+-

Let’s breakdown what we have so far.

  1. The single quote serves to disrupt the normal SQL statement flow.
  2. The ‘union’ clause enables us to combine SQL statements, granting us the ability to construct our own SQL statement to extract information from the database.
  3. The ‘null, null’ segments serve as placeholders for our union clause and plays a vital role in reflecting data retrieved from the database. We use two ‘null’ values here because they align with the number of columns present in the database table.
  4. The from dual is needed for Oracle databases because Oracle requires a table to be part of the query.

To confirm our SQL Injection is working we can attempt to obtain the version of Oracle on the system.

Here is the PortSwigger SQL Injection Cheatsheet. We can use this to help us select the function needed to obtain the database version. Because we are targeting Oracle we can use version FROM v$instance.

GET /filter?category=Accessories'+union+select+null,+banner+from+v$version--+-

We can see in the Response the version of Oracle along with other system information.

Next we can attempt to get the listing of all the tables. We need to select table_name from all_tables in Oracle to list out the tables.

GET /filter?category=Accessories'+union+select+null,+table_name+from+all_tables--+-

We can see in the response the users table is named USER_RJJMRD.

Now we need to get the column names. We can accomplish this by selecting column_name from USER_TAB_COLUMNS where the table_name equals ‘USERS_RJJMRD’.

GET /filter?category=Accessories'+union+select+null,+column_name+from+USER_TAB_COLUMNS+where+table_name+=+'USERS_RJJMRD'--+-

We can see in the response the PASSWORD_FQNSMP column and USERNAME_KVLMMA column for the table USERS_RJJMRD.

Now that we have the column names and the table name we can collect the usernames and passwords from the Oracle Database.

GET /filter?category=Accessories'+union+select+USERNAME_KVLMMA,+PASSWORD_FQNSMP+from+USERS_RJJMRD--+-

With the administrator credentials displayed in the response we are able to authenticate into the portal as the administrator.

Having successfully retrieved the administrator credentials from the database and logged in as the administrator we have accomplished our goal and solved the lab!

That completes the lab! Well done! If you found this helpful, please send me a tweet and tell me what you thought! Feedback is always appreciated!

Jarrod