Challenge Description
A very easy SQL injection challenge with a case-sensitive filter.
The Flask application stores the flag in a SQLite table named secret. Our goal is to read it through the vulnerable login form.
Recon / Initial Analysis
The login values are inserted directly into the SQL query.
query = (
f"SELECT * FROM users WHERE username='{username}' AND password='{password}';"
)
user = conn.execute(query).fetchone()
Because the password is concatenated into SQL without parameters, we can close its quote and append our own UNION SELECT.
Technical Analysis
The filter does not perform a case-insensitive check.
for value in [username, password]:
if "secret" in value:
return "The table is secret!"
The vulnerability is the missing case-insensitive verification: the code checks value instead of value.lower(). Therefore SECRET is not blocked. SQLite treats SECRET and secret as the same table name, so uppercase letters bypass the filter.
Solution
Use UNION SELECT and spell the table name in uppercase.
' UNION SELECT flag,NULL FROM SECRET-- -
UNION SELECT must return two columns because the users table has two columns. flag fills the username position and NULL fills the required second position; without NULL, SQLite rejects the UNION because the column counts do not match. Finally, -- - comments out the remaining quote.
Validation
The real challenge response confirms the payload.
The server returns the flag as the first value of the injected row.
Flag
The verified challenge flag.
Alpaca{Harder_version: `if "secret" in value.lower()`}