Skip to content
Field Value
Platform PortSwigger Web Security Academy
Difficulty Apprentice
Vulnerability SQL Injection — WHERE Clause Filter Bypass
Injection Point category URL parameter
Goal Return all products including unreleased ones

SQL Injection: WHERE Clause Filter Bypass

Information Gathering

The target was a shopping site displaying products by category.

Screenshot

Selecting a category changed the URL to reflect the chosen filter:

web-security-academy.net/filter?category=Gifts
Screenshot

Web Enumeration

I appended a single quote to the category parameter and the application broke:

web-security-academy.net/filter?category=Gifts'

The resulting malformed query made the injection point obvious:

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

Initial Access

With the injection point confirmed, I injected OR 1=1 -- - to collapse the WHERE clause:

web-security-academy.net/filter?category=Gifts' or 1=1 -- -
Screenshot

The application returned all products, including unreleased ones.

The reason the ' goes after Gifts and nowhere else is simple: that's where we are inside the query. The application builds the query by wrapping our input in quotes:

... WHERE category = '[OUR INPUT]' AND released = 1

Typing Gifts' closes the string with our own quote, leaving the application's hardcoded closing quote as a stray character that breaks syntax:

-- Our ' closes the string here ↓
WHERE category = 'Gifts'  ' AND released = 1
--                        ↑ this stray quote breaks the syntax

Adding OR 1=1 -- - then makes the condition always true and comments out everything after — including the stray quote and AND released = 1:

SELECT * FROM products WHERE category = 'Gifts' OR 1=1 -- -' AND released = 1
--                                                        ↑ everything after -- is ignored

The -- - form (double dash + space + dash) is used instead of bare -- because some servers strip trailing spaces. The extra - keeps the comment valid across configurations.

Conclusion

  1. The category parameter was directly interpolated into a SQL query with no sanitization.
  2. A single ' broke the query and confirmed injectable input — the error exposed the query structure.
  3. OR 1=1 -- - escaped the string context, injected an always-true condition, and commented out the released = 1 filter.
  4. The database returned every product row regardless of release status.

The filter bypass worked because the application never validated or escaped user input before embedding it in SQL — we didn't modify the end of the query, we escaped out of the string the application opened for us.