October 24, 2026
PortSwigger Lab: SQL Injection Attack, Listing the Database Contents on Oracle
Difficulty: Practitioner

By Muhammad Raza
3 min read
Target: PortSwigger Web Security Academy
Objective
The objective of this lab is to exploit a SQL injection vulnerability in the product category filter to enumerate the backend Oracle database. We must locate a hidden user table, extract the column names, retrieve the administrator credentials, and log in.
The Vulnerability Concept
Unlike MySQL or Microsoft SQL Server, Oracle databases require a FROM clause in every SELECT statement. When crafting UNION SELECT payloads for Oracle, attackers must use the built-in dual dummy table (e.g., UNION SELECT NULL FROM dual). To enumerate database structure, attackers query Oracle's metadata tables: all_tables (to list tables) and all_tab_columns (to list columns).
Step-by-Step Exploitation
1. Interception and Column Enumeration
I started by navigating the application and selecting the "Toys & Games" category.
In Burp Suite, I intercepted the GET /filter?category=Toys+%26+Games request and sent it to Repeater.
To determine the number of columns returned by the query, I used the ORDER BY technique:
Toys+%26+Games'+order+by+1--returnedHTTP/2 200 OK.
Toys+%26+Games'+order+by+2--returnedHTTP/2 200 OK.
Toys+%26+Games'+order+by+3--returnedHTTP/2 500 Internal Server Error.
This confirms the underlying query returns exactly two columns.
2. Verifying String Data Types
Because this is an Oracle database, I verified that both columns can hold string data by querying the dual table. I used the payload: Toys+%26+Games'+UNION+SELECT+'abc','def'+FROM+dual--
The response reflected abc and def on the page, confirming both columns accept strings.
3. Enumerating the Table Name
To find the table containing user credentials, I queried Oracle's all_tables view. I injected the following payload: Toys+%26+Games'+UNION+SELECT+table_name,+NULL+FROM+all_tables--
Scanning the HTTP response, I located a dynamically generated table name that looked relevant: USERS_UVYXIP.
4. Enumerating the Column Names
With the target table identified, I queried all_tab_columns to find the exact column names for usernames and passwords within that specific table. The payload used was: Toys+%26+Games'+UNION+SELECT+column_name,+NULL+FROM+all_tab_columns+WHERE+table_name='USERS_UVYXIP'--
The response revealed two crucial, dynamically generated column names: USERNAME_ZLLYOZ and PASSWORD_UZGQJR.
5. Data Extraction
Armed with the exact table and column names, I crafted the final payload to extract the administrator's credentials. I placed the username column in the first output and the password column in the second: Toys+%26+Games'+UNION+SELECT+USERNAME_ZLLYOZ,+PASSWORD_UZGQJR+FROM+USERS_UVYXIP--
The query executed successfully, dumping the credentials into the HTML response. I copied the administrator's password: 5br1oiw25kvkp8452te6.
6. Authentication and Verification
I navigated to the /login endpoint on the frontend application. Using administrator and the extracted password, I successfully authenticated.
This granted access to the "My Account" dashboard and triggered the "Congratulations, you solved the lab!" banner.
Remediation
To defend against this systematic database enumeration and extraction, applications must implement parameterized queries (prepared statements) for all user-supplied input. Parameterization ensures that strings passed to the category filter are treated strictly as literal data rather than executable SQL commands, neutralizing UNION attacks entirely.
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.