This one didn't.
No error messages. No stack traces. No SQL syntax warnings.
Just a response that took longer than it should have.
During an authorized security assessment, I identified a time-based blind SQL injection vulnerability in a backend API endpoint. Automated tooling missed it entirely on the first pass — not because the vulnerability was sophisticated, but because the application processed input in a way the tool didn't account for.
Once that was understood, everything changed.
The Entry Point: A Backend API Endpoint
The target was a GET-based API endpoint handling parameter validation during a login-related workflow.
GET /api/v2/clogin?apikey=12334&type=check&u=CXTgnn
On the surface it looked unremarkable:
- Simple GET request
- Short parameter list
- Fast, consistent responses — 47ms baseline
Nothing immediately suggested injection. But Burp's active scanner flagged a possible timing anomaly on one of the parameters.
That was enough to dig deeper.

Shifting the Testing Mindset
The temptation at this point is to hand it straight to sqlmap and move on.
Instead, I asked a different question:
What is the application actually doing with this input before the backend sees it?
Not what the parameter looks like in the request. What happens to it in transit.
That question changed the entire approach.
The First Signal: 35 Seconds of Silence
Before touching any tooling, I validated the timing behaviour manually.
I crafted a simple delay-based payload and injected it directly into the u parameter:
CXTgnn'+(select*from(select(sleep(35)))a)+'
The response came back in 35,054ms.
Baseline was 47ms.
No error. No output. Just a 35-second delay — exactly as instructed.
The backend was executing injected SQL logic. It just wasn't returning any output.
That's the definition of blind SQL injection.


Why Naive Automation Would Fail Here
Before running any tooling, I understood why a standard sqlmap run would come up empty.
The u parameter wasn't consumed as raw input. Looking at the request flow revealed a two-step transformation happening before the backend ever saw the value:
- The plain value was Base64-encoded
- Then URL-encoded
- Only then passed to backend logic
Any tool injecting raw SQL payloads directly into u would be sending input the backend never actually received in that form. The payloads would be decoded into something unrecognizable — and the injection would silently fail.
The tool needed to speak the application's language first.
Teaching the Tool How the Application Thinks
The fix was to tell sqlmap exactly how to transform its payloads before sending them.
sqlmap -u "https://[target]/api/v2/clogin?apikey=12334&type=check&u=INJECT_HERE" \
--eval="import urllib.parse, base64; u=urllib.parse.quote(base64.b64encode(u.encode()).decode())" \
--technique=T \
--batch --level=5 --risk=3 \
--dbsThe --eval flag instructs sqlmap to run a Python expression against the parameter value before each request — in this case, Base64-encoding then URL-encoding the payload to match exactly what the application expected.
The behaviour changed immediately.

Impact: Full Database Enumeration
Despite being entirely blind — no error output, no reflected data, no stack traces — the injection led to:
- Backend DBMS confirmed: MySQL ≥ 5.0.12
- 5 databases enumerated
- 88 tables retrieved from the target database



All extracted character by character through timing alone.
This wasn't a noisy attack. It was patient, quiet, and reliable.
Why Encoding Isn't Protection
The encoding layer on this parameter likely gave a false sense of security.
From a developer's perspective, a Base64 + URL-encoded value looks nothing like a SQL payload. It doesn't trigger naive input validation. It doesn't match obvious injection signatures.
But encoding is transformation, not sanitization.
The backend decoded the value before passing it to the query layer. At that point, the payload was exactly what it was designed to be.
Encoding delayed discovery. It didn't prevent exploitation.
The Architectural Failure
This came down to two missing controls:
- No parameterized queries or prepared statements on the backend
- Input transformation mistaken for input validation
Security tools don't fail because they're weak. They fail when the tester doesn't adapt them to how the application actually processes input.
Once the encoding logic was understood and replicated, the vulnerability that appeared invisible became fully exploitable.
Final Thought
This vulnerability wasn't about finding a clever bypass.
It was about reading the application correctly.
When systems assume that transformation equals protection, blind vulnerabilities don't disappear — they just wait longer to be found.
The 47ms baseline told one story. The 35-second delay told the truth.
