October 19, 2026
PortSwigger Lab: SQL Injection Attack, Querying the Database Type and Version on Oracle
Difficulty: Practitioner
By Muhammad Raza
3 min read
Target: PortSwigger Web Security Academy
Objective
The goal of this lab is to exploit a SQL injection vulnerability in the product category filter to retrieve and display the Oracle database version string.
The Vulnerability Concept
The application concatenates user input directly into the SQL query used to filter products by category. Because the backend database is Oracle, standard SQL injection payloads must be slightly modified. Specifically, Oracle databases require all SELECT statements to include a FROM clause. If we are injecting a payload that does not query a specific table, we must use the built-in dummy table dual. Furthermore, Oracle database version information is stored in the v$version table.
Step-by-Step Exploitation
1. Reconnaissance
I navigated to the main lab page and clicked on the "Clothing, shoes and accessories" category to observe the application's routing.
2. Determining the Number of Columns
I intercepted the traffic using Burp Suite and located the GET /filter?category=... request in the Proxy HTTP history.
I then sent this request to Repeater for testing.
Before I could extract data, I needed to determine how many columns the original query returned. I used the ORDER BY technique, injecting payloads into the category parameter.
- Testing 1 column:
'+order+by+1+--resulted in a200 OK.
- Testing 2 columns:
'+order+by+2+--resulted in a200 OK.
- Testing 3 columns:
'+order+by+3+--resulted in a500 Internal Server Error.
The error on the 3rd column confirmed that the original query returns exactly two columns.
3. Determining Column Data Types
Next, I needed to verify which of the two columns could hold string data, as the database version is a string. Because this is an Oracle database, I had to query the dual table.
I injected the following UNION payload to test both columns for string compatibility: '+UNION+SELECT+'abc','def'+FROM+dual--
The server responded with a 200 OK, and the strings abc and def were rendered in the HTML table on the response page. This confirmed both columns accept string data.
4. Extracting the Database Version
With the structure mapped out, I replaced my dummy strings with a query to the v$version table. The payload used was:'+UNION+SELECT+banner,+NULL+FROM+v$version--
Note: I queried the banner column from v$version into the first column and passed NULL into the second column.
The request was successful, and the HTTP response leaked the Oracle database version strings directly into the HTML (e.g., Oracle Database 11g Express Edition...).
5. Verification
Applying the payload or viewing the rendered response in the browser triggered the success state for the lab.
Remediation
To prevent this vulnerability, the application must use parameterized queries (prepared statements) instead of dynamically concatenating the category input string. This ensures the database driver treats the user's input safely as data rather than executable SQL syntax, neutralizing the UNION attack regardless of the underlying database engine.
This write-up is part of my ongoing PortSwigger Web Security Academy lab series. You can find the raw markdown files, payloads, and my full progress tracker in my Github Repository.