CTF Writeup: LUST Fragment (SQL Injection & WAF Bypass)
This challenge was a solid demonstration of how blacklist-based WAFs fail under pressure. What initially appeared to be a straightforward login bypass quickly evolved into a nuanced exercise in SQLite-specific SQL injection under extreme filtering.
1. Initial Reconnaissance
The application exposed two authentication endpoints:
index.php– standard username/password loginfacebook_login.php– OAuth-style login integration
Basic testing (and source inspection) revealed that user-controlled input was directly concatenated into SQL queries—a textbook SQL injection vulnerability.
However, exploitation wasn’t trivial. The application was protected by an unusually aggressive Web Application Firewall (WAF) that blocked most conventional payloads outright.
2. Understanding the WAF Constraints
This wasn’t a simple ' OR 1=1 -- situation. The WAF employed regex-based filtering that aggressively blocked:
Core SQL keywords:
SELECT,UNION,INSERT,DROP,FROM,WHERE,GROUP BYCommon SQL functions:
hex(),load_extension(), and many others
The objective was not merely to bypass authentication, but to extract data from non-obvious tables—specifically one containing the real flag.
3. Bypass Strategy
When dealing with restrictive WAFs, the solution often lies in database engine quirks, not brute force. Since the backend was SQLite, the attack focused on edge cases the filters failed to anticipate.
The approach revolved around three core techniques:
Case Manipulation
Some WAF regexes fail to normalize case properly (e.g.,sElEcTvsSELECT).Inline Comment Injection
Breaking keywords using comments such as/**/:SEL/**/ECT FR/**/OMThis often defeats naïve pattern matching.
Encoding & Literal Abuse
Representing sensitive characters using encodings (HTML entities, numeric literals, etc.) to avoid keyword detection entirely.
4. Finding the Real Flag
The file fake.php was intentionally misleading and contained decoy data. A subtle hint in the README suggested the real flag lived elsewhere—specifically in a table named fragments.
Direct queries like:
SELECT * FROM fragments
were immediately blocked. The breakthrough came from recognizing that:
SQLite tolerates unusual syntax combinations
The stored flag fragment itself was encoded using HTML entities, preventing trivial string detection by server-side filters
This meant the WAF wasn’t just filtering input—it was also relying on encoded storage to obscure the output.
5. Extracting and Decoding the Flag
Using obfuscated SQLite-compatible syntax and encoding tricks, the following string was successfully leaked:
SkelerCTF{
LUST_FRAGMENT
_XXXXXXXXXXXX}
Decoding Process
Each HTML entity corresponds to an ASCII character:
| Entity | Char | Entity | Char |
|---|---|---|---|
S | S | L | L |
k | k | U | U |
e | e | S | S |
l | l | T | T |
Decoding the full sequence yields:
SkelerCTF{LUST_FRAGMENT_XXXXXXXXXXXX}
Key Takeaways
WAFs are not a substitute for secure queries
Blacklist-based filtering is brittle and almost always bypassable when SQL injection exists.Database-specific knowledge is a force multiplier
Understanding SQLite’s parsing behavior and quirks was essential to bypassing the filters.CTF challenges reward skepticism
Fake flags and decoy files are common—always look for what’s not immediately visible.
Comments
Post a Comment