SQL injection vulnerability in WHERE clause allowing retrieval of hidden data

SQL injection vulnerability in WHERE clause allowing retrieval of hidden data

This is a writeup for a challenge from PortSwigger's Web Security Academy. In this one, we will learn how an SQL injection can be discovered and exploited to display hidden products or similar.

Objective

This lab contains an SQL injection vulnerability in the product category filter. When the user selects a category, the application carries out an SQL query like the following:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

To solve the lab, perform an SQL injection attack that causes the application to display details of all products in any category, both released and unreleased.

Solving the challenge

In this challenge, we will exploit the basic version of the SQL injection vulnerability.

We have a lab site:

When we are trying to search by a category, the following SQL query is being executed:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

Our goal is to somehow break into that query, to disclose some hidden information.

The query above will get all items that belong to the Gifts category AND released. We, on the other hand, would like to get all items, regardless of filters.

Our link at this point is something like this:

https://acf31fda1e559c26c0ef0859003200ac.web-security-academy.net/filter?category=Corporate+gifts

As this is the simplest example, we would just need to add some additional arguments to the URL to make it work.

We will use the following query to solve this challenge:

https://acf31fda1e559c26c0ef0859003200ac.web-security-academy.net/filter?category=Corporate+gifts%27+OR+1=1--

Why did that work? We are using a single quote symbol at the beginning of our request to add another parameter to the initial query. The modified query will look like that:

SELECT * FROM products WHERE category = 'Corporate gifts' AND released = 1 OR 1=1

So, we are introducing a logic issue here. The 1=1 equation returns a TRUE value, and when the backend is going through every single item in the database, it's executing the following check:

A given item belonging to the Corporate gifts group and released, OR exist.

We are flipping the initial request, and the backend will return the content of every item in the database as if they exist.