We covered a scenario of blind SQL Injection where the web application accepts user input without sanitization or filtering. We used a blind SQL query to guess the password by guessing the characters and their order. We finally wrapped this up with a simple python script that does the job.. This was part of OverTheWire War Games Natas Level 15
Challenge Overview
The challenge presents a username input box to check if a username exists. Examining the source code reveals a table named users
with usernames
and passwords
columns, both with a maximum of 64 characters. The password for each challenge is typically a maximum of 32 characters. The username input is taken as a GET request and passed directly into an SQL query without filtering. The query is select from users where username = '[user_input]'
. A debug parameter in the URL can reveal the executed query. My goal is to find the password for the user natas16
. This is a blind SQL injection because there’s no direct way to see the password; I can only check if a username exists.
Exploitation Strategy – Using the LIKE
statement
I will use the SQL LIKE
statement to guess the password character by character. The LIKE
statement helps determine if a character exists within a column. For example:
database LIKE 'S%'
checks if the database name starts with ‘S’.table_name LIKE '%A'
checks if the table name ends with ‘A’.
Manually guessing each character is tedious, so I will use a Python script.
Python Script Breakdown
- Initialization:
- I define authentication parameters (username and password for the previous level).
- I generate a character set including letters and digits, as passwords can contain uppercase, lowercase, and numbers.
- I initialize an empty dictionary to store valid password characters.
- I define a string
user_exists_string = "This user exists."
to check against the application’s response.
- Finding Valid Characters:
- The script sends an SQL query like:
username=natas16" AND password LIKE BINARY "%<char>%" --
natas16"
: Closes the initial double quote and specifies the target user.AND password LIKE BINARY "%<char>%"
: Checks if the character<char>
exists anywhere in the password.BINARY
is used because the column’s collation is unknown.- The two percentage signs (
%
) mean the character can be anywhere in the password.
- If the application responds with “This user exists,” it means the character is part of the password.
- The script iterates through the generated character set, and if a character is valid, it’s added to the
password_dictionary
.
- The script sends an SQL query like:
- Determining Character Order:
- I initialize an empty list for the ordered password.
- I iterate 32 times (assuming max password length).
- For each position, I try appending each valid character (from
password_dictionary
) to the currently known part of the password. - The query will be like:
username=natas16" AND password LIKE BINARY "<known_password_part><test_char>%" --
- This checks if the password starts with the
known_password_part
followed by thetest_char
.
- This checks if the password starts with the
- If “This user exists” is returned, the
test_char
is correct for the current position, and it’s added to the password being built. - The script prints its attempts, showing how it builds the password character by character.
Manual Example
I can manually test this by inputting a query like: natas16" AND password LIKE BINARY "%t%" --
. If this returns “This user exists,” then ‘t’ is in the password. To check if the password ends with ‘t’, the query would be: natas16" AND password LIKE BINARY "%t" --
.
Result
The script successfully retrieves the password for Natas Level 16.
Natas Level 16 Password:
TRD7iZrd5gATjj9OkPEuaOlfEjHqj32V
Technical Commands/Queries
While there are no traditional “terminal commands” in this video, the following SQL injection payloads were used or discussed:
- SQL query structure shown in source code:SQL
select from users where username = "[user_input]"
- Example of
LIKE
statement for database name:SQLdatabase LIKE 'S%'
- Example of
LIKE
statement for table name:SQLtable_name LIKE 'A'
- Python script’s SQL query to find valid characters:SQL
username=natas16" AND password LIKE BINARY "%<char>%" --
- Python script’s SQL query to determine character order:SQL
username=natas16" AND password LIKE BINARY "<known_password_part><test_char>%" --
- Manual test query example from the video:SQL
natas16" AND password LIKE BINARY "%t" --
The video also mentions using the ?debug
parameter in the URL to view the SQL query.