From 7d3561f6e76fa0be4cd513c04b56f1b5ca636e72 Mon Sep 17 00:00:00 2001 From: Jan Rude Date: Sat, 12 Jul 2014 21:09:53 +0200 Subject: [PATCH] Update typoenum.py --- typoenum.py | 167 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 100 insertions(+), 67 deletions(-) diff --git a/typoenum.py b/typoenum.py index e8da02f..41e927c 100644 --- a/typoenum.py +++ b/typoenum.py @@ -9,10 +9,11 @@ ## v0.5 Added support for Typo v6.X ## ## v0.6 Added extension search ## ## v0.7 Added version search for extensions ## +## v0.8 Added support for TOR Service ## ############################################### ############ Version information ############## -__version__ = "0.7" +__version__ = "0.8" __program__ = "Typo-Enumerator v" + __version__ __description__ = 'Find out the Typo3 Version, Login-URL and Extensions' __author__ = "Jan Rude" @@ -30,7 +31,6 @@ import urllib import urllib2 import argparse import datetime -import requests from Queue import Queue from colorama import Fore from os.path import isfile @@ -49,8 +49,9 @@ verbosity = False # Checks the Typo version def check_typo_version_ChangeLog(domain): global verbosity + global user_agent try: - url = 'http://' + domain + '/typo3_src/ChangeLog' + url = urllib2.Request('http://' + domain + '/typo3_src/ChangeLog', None, user_agent) f = urllib2.urlopen(url, timeout = 3.0) changelog = f.read(200) f.close() @@ -66,8 +67,9 @@ def check_typo_version_ChangeLog(domain): def check_typo_version_NEWS_TXT(domain): global verbosity + global user_agent try: - url = 'http://' + domain + '/typo3_src/NEWS.txt' + url = urllib2.Request('http://' + domain + '/typo3_src/NEWS.txt', None, user_agent) f = urllib2.urlopen(url, timeout = 3.0) changelog = f.read(500) f.close() @@ -82,8 +84,9 @@ def check_typo_version_NEWS_TXT(domain): check_typo_version_NEWS_MD(domain) def check_typo_version_NEWS_MD(domain): + global user_agent try: - url = 'http://' + domain + '/typo3_src/NEWS.md' + url = urllib2.Request('http://' + domain + '/typo3_src/NEWS.md', None, user_agent) f = urllib2.urlopen(url, timeout = 3.0) changelog = f.read(80) f.close() @@ -99,38 +102,22 @@ def check_typo_version_NEWS_MD(domain): def check_typo_login(domain): global user_agent try: - r = requests.get('http://' + domain + '/typo3/index.php', allow_redirects=False, timeout=3.0, headers=user_agent) - statusCode = r.status_code - httpResponse = r.text - r.close() - if statusCode == 200: - return check_title(httpResponse, r.url) - - elif (statusCode == 301) or (statusCode == 302): - location = r.headers['location'] - if verbosity: - print "Redirect to:".ljust(32) + location - if ("http://") in location: - new = location.split("//") - new2 = new[1].split("/") - check_typo_login(new2[0]) - elif ("https://") in location: - r = requests.get(location, timeout=3.0, headers=user_agent, verify=False) - statusCode = r.status_code - httpResponse = r.text - return check_title(httpResponse, r.url) - elif statusCode == 404: + req = urllib2.Request('http://' + domain + '/typo3/index.php', None, user_agent) + connection = urllib2.urlopen(req) + response = connection.read() + return check_title(response, connection.geturl()) + connection.close() + except urllib2.HTTPError, e: + if e.code == 403: + return check_title(response, connection.geturl()) + elif e.code == 404: print "Typo3 Login:".ljust(32) + Fore.RED + "Typo3 is not used on this domain" + Fore.RESET + except urllib2.URLError, e: + print str(e.reason) + except Exception, e: + import traceback + print ('generic exception: ', traceback.format_exc()) - else: - print "Oops! Got:".ljust(32) + str(statusCode) + ": " + str(r.raise_for_status()) - - except requests.exceptions.Timeout: - print Fore.RED + "Connection timed out" + Fore.RESET - except requests.exceptions.TooManyRedirects: - print Fore.RED + "Too many redirects" + Fore.RESET - except requests.exceptions.RequestException as e: - print Fore.RED + str(e) + Fore.RESET # Checks, if URL is a Typo-Login def check_title(httpResponse, url): @@ -151,38 +138,48 @@ def check_extensions(domain, input_queue, output_queue): while True: extension = input_queue.get() try: - r = requests.get('http://' + domain + '/typo3conf/ext/' + extension + "/", allow_redirects=False, timeout=8.0, headers=user_agent) - statusCode = r.status_code - r.close() - if (statusCode == 200) or (statusCode == 403): - check_extension_version(domain, extension, output_queue) - elif statusCode == 404: + req = urllib2.Request('http://' + domain + '/typo3conf/ext/' + extension + "/", None, user_agent) + connection = urllib2.urlopen(req) + connection.close() + check_extension_version(domain, extension, output_queue) + except urllib2.HTTPError, e: + if e.code == 403: + check_extension_version(domain, extension, output_queue) + elif e.code == 404: if verbosity: output_queue.put(extension.ljust(32) + Fore.RED + "not installed" + Fore.RESET) pass - else: - print "Oops! Got:".ljust(32) + str(statusCode) + ": " + str(r.raise_for_status()) + except urllib2.URLError, e: + print str(e.reason) except Exception, e: - print "Oops! Got:".ljust(32), e + import traceback + print ('generic exception: ', traceback.format_exc()) input_queue.task_done() # Searches for version of installed extension def check_extension_version(domain, extension, output_queue): global verbosity + global user_agent try: - url = 'http://' + domain + '/typo3conf/ext/' + extension + '/ChangeLog' - f = urllib2.urlopen(url, timeout = 3.0) - changelog = f.read(500) - f.close() - regex = re.compile("\* (.*)") + url = urllib2.Request('http://' + domain + '/typo3conf/ext/' + extension + '/ChangeLog', None, user_agent) + connection = urllib2.urlopen(url, timeout = 15.0) + changelog = connection.read(1500) + connection.close() + regex = re.compile("(\d{1,2}\.\d{1,2}\.[0-9][0-9]?[' '\n])") searchVersion = regex.search(changelog) version = searchVersion.groups() - output_queue.put(extension.ljust(32) + Fore.GREEN + "installed (" + version[0] + ")" + Fore.RESET) + output_queue.put(extension.ljust(32) + Fore.GREEN + "installed (v" + version[0].split()[0] + ")" + Fore.RESET) except: - if verbosity: - output_queue.put(extension.ljust(32) + Fore.GREEN + "installed" + Fore.RESET + " (could not find version)") - else: - output_queue.put(extension.ljust(32) + Fore.GREEN + "installed" + Fore.RESET) + try: + regex = re.compile("(\d{2,4}[\.\-]\d{1,2}[\.\-]\d{1,4})") + searchVersion = regex.search(changelog) + version = searchVersion.groups() + output_queue.put(extension.ljust(32) + Fore.GREEN + "installed (last entry from " + version[0] + ")" + Fore.RESET) + except: + if verbosity: + output_queue.put(extension.ljust(32) + Fore.GREEN + "installed" + Fore.RESET + " (could not find version)") + else: + output_queue.put(extension.ljust(32) + Fore.GREEN + "installed" + Fore.RESET) # Output def output_thread(q): @@ -201,7 +198,7 @@ def output_thread(q): def generate_extensions_list(top): global extension_list extension = 'extensions.xml' - print "Loading extensions..." + print "\nLoading extensions..." if not isfile(extension): print(Fore.RED + "File not found: " + extension + "\nAborting..." + Fore.RESET) sys.exit(-2) @@ -213,14 +210,13 @@ def generate_extensions_list(top): for extensions in tag_dict.getchildren(): ext = {extensions.get('extensionkey'):extensions[0].text} exten_Dict.update(ext) - print 'Loaded ' , len(exten_Dict), ' extensions' + print 'Loaded ' , len(exten_Dict), ' extensions\n' if top is not None: sorted_dict = sorted(exten_Dict.iteritems(), key=lambda x: int(x[1]), reverse=True) for i in xrange(0,top): extension_list.append(sorted_dict[i][0]) - else: for extension_name in tag_dict: extension_list.append(extension_name.get('extensionkey')) @@ -231,7 +227,7 @@ def copy_extensions(input_queue): for ext in extension_list: input_queue.put(ext) -# Processbar +# Progressbar def dlProgress(count, blockSize, totalSize): percent = int(count*blockSize*100/totalSize) sys.stdout.write("\rDownloading extentions: " + "%d%%" % percent) @@ -239,7 +235,6 @@ def dlProgress(count, blockSize, totalSize): # Update function def update(): - global user_agent try: urllib.urlretrieve('http://ter.sitedesign.dk/ter/extensions.xml.gz', 'extensions.gz', reporthook=dlProgress) inf = gzip.open('extensions.gz', 'rb') @@ -253,8 +248,36 @@ def update(): except Exception, e: print "Oops! Got:".ljust(32), e -#Starting checks -def start(domain): +# Using Privoxy and TOR for all connections +def setting_up_tor(): + try: + import socks + except: + print "The module 'SocksiPy' is not installed.\nPlease install it with: sudo apt-get install python-socksipy" + sys.exit(-2) + + print "Setting up proxy to Privoxy on Port 8118" + socks.setdefaultproxy(socks.PROXY_TYPE_HTTP, "127.0.0.1", 8118, True) + socket.socket = socks.socksocket + try: + url = urllib2.Request('https://check.torproject.org/') + torcheck = urllib2.urlopen(url) + response = torcheck.read() + torcheck.close() + except: + print "Failed to connect to Privoxy and/or TOR!\nPlease make sure they are running and configured!\nYou can start them with:\nservice privoxy start\nservice tor start\n" + sys.exit(-2) + try: + regex = re.compile('Congratulations. This browser is configured to use Tor.') + searchVersion = regex.search(response) + version = searchVersion.groups() + print "Connection to TOR established" + except: + print "It seems like TOR is not used.\nAborting...\n" + sys.exit(-2) + +# Starting checks +def start(domain, top, tor): in_queue = Queue() out_queue = Queue() regex = re.compile("(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})") @@ -267,10 +290,17 @@ def start(domain): print("\n\n[*] Check for " + domain) if check_typo_login(domain) is True: + if not extension_list: + generate_extensions_list(top) + check_typo_version_ChangeLog(domain) copy_extensions(in_queue) - print '\nChecking', in_queue.qsize(), 'Extensions:' - for i in xrange(0, 10): + print '\nChecking', in_queue.qsize(), 'Extensions:\nThis may take a while...' + if tor: + threads = 2 + else: + threads = 10 + for i in xrange(0, threads): t = Thread(target=check_extensions, args=(domain, in_queue, out_queue)) t.daemon = True t.start() @@ -285,7 +315,7 @@ def start(domain): def main(argv): global user_agent global verbosity - parser = argparse.ArgumentParser(add_help=False, usage='typoenum.py -d DOMAIN [DOMAIN ...] | -f FILE [--user_agent USER-AGENT] [--top VALUE] [-v]') + parser = argparse.ArgumentParser(add_help=False, usage='typoenum.py -d DOMAIN [DOMAIN ...] | -f FILE [--user_agent USER-AGENT] [--top VALUE] [-v] [--tor]') group = parser.add_mutually_exclusive_group() group.add_argument('-d', '--domain', dest='domain', type=str, nargs='+') group.add_argument('-f', '--file', dest='file', help='File with a list of domains') @@ -293,23 +323,26 @@ def main(argv): parser.add_argument('--user_agent', dest='user_agent', default='Mozilla/5.0', metavar='USER-AGENT (default: Mozilla/5.0)') parser.add_argument('--top', type=int, dest='top', metavar='VALUE', help='Check only most X downloaded extensions (default: all)', default=None) parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true") + parser.add_argument("--tor", help="using tor for connections", action="store_true") args = parser.parse_args() if not args.domain and not args.file and not args.update: parser.print_help() return True + if args.tor: + setting_up_tor() + if args.update: update() return True user_agent = {'User-Agent' : args.user_agent} - generate_extensions_list(args.top) verbosity = args.verbose if args.domain and not args.file: for dom in args.domain: - start(dom) + start(dom, args.top, args.tor) elif not args.domain and args.file: if not isfile(args.file): @@ -318,7 +351,7 @@ def main(argv): else: with open(args.file, 'r') as f: for line in f: - start(line.strip()) + start(line.strip(), args.top, args.tor) print '\n' now = datetime.datetime.now() print __program__ + ' finished at ' + now.strftime("%Y-%m-%d %H:%M:%S") + '\n'