TryHackMe SQL Injection Lab
This page will be divided into tasks , Each task will have it's own idea.
Last updated
This page will be divided into tasks , Each task will have it's own idea.
Last updated
We can see that there is a simple form that requires from us ID
and password
we need to bypass this authentication .
If we tried this simple query : 1' OR 1=1-- -;
we get this response :
This is because the ID
input is not string , hence we don't need to close the query using a quote , so by using this payload : 1 OR 1=1-- -;
We successfully bypass the authentication .
Now we have a string input box , so we need to use the single quote to bypass the authentication as follow : 1' OR 1=1-- -;
Now the parameters are in the URL , This will not make a big difference in our query except for the URL encoding
And this can easily bypass the authentication for us :
In this lab we cannot see our parameters in the URL because they are passed as POST parametes , so by intercepting the request we can manipulate the parameters to inject our payload
We can see that we are being redirected to the home, so we have ssuccessfully bypassed the authentication .
SQL Injection isn't meant only to bypass login panels , but also retrieve information. In this case the web application has a section for updating our info , due to improper validation on the updated info we can inject malicious SQL queries which will be executed within UPDATE
statement
We are given credentials to login 10
& toor
We can see the "Edit Profile" Section up there
Let's try to confirm the injection in the nickname field , This can done by using string concatenation , so if i provided the nickname as follow : Khalid'||'Emad
and we found that it got concatenated then it is an injection point
Now for further exploitation we can retrieve info , The very first basic thing we can try is to get the version , but since we don't know the DBMS we should use different functions for the version , eventually it was sqlite
and the function was sqlite_version()
, we can retrieve the version as follow : KhalidEmad'||(SELECT sqlite_version())||'
Now let;s try to dump the database tables, the following payload can be used to dump the tables :
But if we used it just like we would find that it only returns one table , this because the database returns more than one row in vertical way but we need it to return the results in horizontal way and this can be done using group_concat()
function , so the payload at the end is :
Now we can dump the columns of this "secrets" table using this payload :
We see that it has a column called secret which seems important , so let's select it :
A single login form and we need to bypass the authentication , let's start simple :
We can't see any messages , let's use another payload admin'--
so this simply will comment the rest of the query and login as admin without checking the password
The login page is still vulnerable to SQL injection , so we can easily login as admin however there is no valuable info . So we need to escalate further more .
We have the register page which we can test for it , First of all we need to determine the number of columns returned by the database .
Registering with => ' union select 1-- -;
gives us " Invalid username or password"
Registering with 'union select 1,2-- -;
gives us :
So we now know that there are 2 columns returned not just that but also column number 2 is displayed on the web app , so let's select the version for example => ' union select 1, sqlite_version()-- -;
:
The injection now is confirmed , so let's try to dump the tables considering the group_concat()
:
Let's try to dump the columns in it :
We can see that it has a column called password, so let's select it :
This time there are no output displayed on the page but still the login page is vulnerable to Blind SQL injection , We know that based on the web application response in the case of true and false conditions .
In this case if we asked the database a true condition the web application will respond with 302 status code (redirection) if not it will respond with 200 ok
Now we can abuse this behavior to dump the password from the database ( we know the column name which is "password" and the table name which is "users" ) [ Check portswigger lab #11 solution to understand more about blind sql injection] .
The only thing here is that the web app converts the letters to lower case so if the flag contains upper case letter we won't get it, but this can be solved using unicode()
function in sqlite which returns the ASCII code of the character .
This time the login page is not vulnerable any more to SQL injection , the developer has implemented new feature which is adding notes .
Put in mind that the register function might be still vulnerable to SQL injection , so let's start our analysis.
We can register as normal users using khalid:khalid
credentials
We can see that the parameters in the register form are being processed within SQL prepared statements , hence these fields are not vulnerable .
When we login and in the notes section , the notes are being retreived from the database as follow :
As you can notice that it selects the username within a normal sql statement .
Now what if we would make it retrieve the notes as follow :
So it would display all the notes for us , Can we ? ... let's try to register with a vulnerable username as follow khalid' or 1=1--
hence we will achieve the above query :
When we go to the notes section :
Nice , we got all the notes from other users , we even got an important one for the flag .
Now let's use UNION
attack to get the flag , we may be already know the table name which users and the column name which is password , so let's register as :
The developer patched the login page and the notes page so we can't exploit them any more, But he added another feature which is update password .
Let's try to take the normal user path to see what is hapenning , First we will create a normal user and attempt to change our password :
Notice how the password changed , the username parameter can be easily exploited if we forced the query to act as follow :
By this way all passwords of the users will be changed to our new password and we can login as admin easily .
When we logged in as test' or 1=1--
and changed the password the query worked as we want , now let's login as admin :
The developer add new feature to the web application which is searching for books using titles .
We can see a GET parameter called title and returns the result based on it's value .
And here is the query which is being executed , to escape this query we need to first provide a quote then )
to escape it , then --
to comment the rest of the query
Now we can confirm the injection , let's quickly see how may columns are returned :
So it returns 4 columns only the last 3 are displayed , let's select the password column from users table as follow :
Like the previous challenge we can search for book titles using the GET parameter title, but we realize that their are 2 queries executed , the result of the first is reflected into the second :
So basically the first query selects the id depending on the name of the title, this id then is used to select the books .
It would make sense to escape the first query and force the second one to select what we need
Here we can notice that when i escaped the first query and selected "1" it got reflected in the second query and the book was selected based on this value of the id .
Now to escalate further we need to perform another union attack , since the id is selected as a string not integer so we will enclose it between quotations as follow => '1'
and then to escape the id query we will add another quotation to it => '1''
and we can now perform the complete union attack as follow :
We can see that the query is perfectly escaped but nothing occurred , so maybe it needs more column numbers :
By increasing the number to 4 we found that it expects 4 columns and also the lat 3 are reflected on the web page . Flag now can be easily selected as follow :
And here are the secrets
A python script to solve it can be found here =>