Another quick writeup of a CTF hacking challenge, hosted by PicoCTF. This challenge Web Gauntlet 3, is an injection attack.
I believe the payload for this challenge actually works for the previous two challenges as well, Web Gauntlet 1 and Web Gauntlet 2.
The hacking challenge
Last time, I promise! Only 25 characters this time. Log in as admin
So we’re trying to gain access as admin
Following the PicoCTF challenge link, you get a simple ‘login’ window titled “Filtered SQLite Injection Challenge #3”:
Importantly we’re also provided with a filter.php, which includes the following symbols/lexigrams as blacklisted terms:
Filters: or and true false union like = > < ; -- /* */ admin
So it looks like fairly common SQL injection terms are locked out. With the main exception being single & double quotes, as well as parenthesis (brackets), none of which are explicitly listed in the filters script. Excellent.
Building the injection payload
Trying “adm in” (with a space, to avoid the filter) in both username and password, returns the following at the top of the screen:
SELECT username, password FROM users WHERE username='adm in' AND password='adm in'
So spaces aren’t stripped out.
Then it dawned on my, were using SQLite (my brain had defaulted to MySQL). This revelation (it’s in the title!) means we can use a quirk of SQLite, the fact it uses the double pipe, ” || ” as a string concatenation function.
Dropping that in, with some carefully placed singles quotes, we can bypass the “admin” word in the filter.
Use the following payload for username field:
admi' || 'n
(note the two single quotes inside the string)
Unfortunately we can’t use the same method on the password field, and we can’t escape the quotes to drop in the column name either…
' || password || '
As password contains the filtered blacklist word, ‘or‘.
Previously you could also use some SQLi like:
' | 1 IS NOT 2 | '
However that falls foul of Web Gauntlet 3’s other criteria, max combined character length. Its got to be under 25.
Thankfully you can get around this by comparing single character strings.
Final Challenge Payload
admi' || 'n
0' IS NOT '1
This will result in the final query of:
SELECT username, password FROM users WHERE username='adm'||'n' AND password='0'is not'1'
You’ll then need to told to navigate to filter.php page, which is now rendered in plaintext, leaving the flag visible
Note; I did get into some weird cookie session weirdness, where the challenge would say to check the filter page but the page wouldn’t change. It continued to show the filter blacklist and not the flag. I got round that by closing the browser down and doing everything in a new private session.