Training engagement · local lab, 2026
SQL injection to remote code execution, then closing every hole
The application was TravelBird, a mock travel booking site running on a local XAMPP server, chosen specifically so every exploit and every fix could be demonstrated end to end without touching a real system. A search parameter with no input sanitisation was the starting point, and the interesting part was never that single flaw. It was how many other weaknesses sat one step away from it once you started pulling the thread.
By the end there were four separate, independently scored findings, and every one of them had a fix that was implemented and then verified against the exact payload that had worked before. Finding the hole is the fast part of a test like this. Proving the fix holds is the part that actually takes the time.
Approach
Step 1
Confirm, then escalate
A seven-step manual UNION-based methodology took a single quote from a search parameter to a full customer table dump, cross-checked with sqlmap to confirm three independent injection types on the same parameter.
Step 2
Follow the entry point sideways
The same reflected column that leaked query results also rendered unescaped HTML, and the recovered plaintext passwords fed a working credential-stuffing attack. A separate upload handler with no file validation turned into remote code execution once authenticated.
Step 3
Fix at the exact point it broke
Prepared statements for the injection, extension whitelist plus real MIME-type validation for the upload, output encoding for the XSS, and account lockout plus bcrypt hashing for the credential attack.
Step 4
Verify the fix resists the original payload
Every one of the original exploit payloads was retested against the patched application and confirmed to fail, not just theoretically closed but practically blocked.
9.8
Peak CVSS score (Critical)
4
Vulnerability classes chained from one entry point
0
Original payloads still worked after the fix