diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index b9b86e1..8f81752 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -1,3 +1,10 @@ +## Version 0.4.5.2 + +* Fixed error on update +* Fixed version search +* Path to version file(s) is printed +* Support for HTTP Basic Auth is now added (--auth) + ## Version 0.4.5.1 * Fixed error on launch when launching from different directory diff --git a/doc/TODO.md b/doc/TODO.md index 978aeb8..df89371 100644 --- a/doc/TODO.md +++ b/doc/TODO.md @@ -1,5 +1,6 @@ # TODO * Newer Typo3 installations use /typo3/index.php?id=xxx -* Version search fix -* Stop extension enumeration with ctrl-c \ No newline at end of file +* Stop extension enumeration with ctrl-c +* maybe store extensions and findings in database +* code cleanup \ No newline at end of file diff --git a/lib/check_installation.py b/lib/check_installation.py index 2bf087d..50ef78e 100644 --- a/lib/check_installation.py +++ b/lib/check_installation.py @@ -131,7 +131,7 @@ class Typo3_Installation: if ('TYPO3 Backend access denied: The IP address of your client' in response[0]) or (response[3] == 403): login_text += (Fore.YELLOW + ' Forbidden (IP Address Restriction)' + Fore.RESET) - elif ('TYPO3 Login' in title): + elif (('TYPO3 Login' in title) or ('TYPO3 CMS Login') in title): login_text += Fore.GREEN + ' Yes' + Fore.RESET else: login_text = Fore.RED + 'Could not be found' + Fore.RESET diff --git a/lib/config.json b/lib/config.json index 8c14dd6..0589e18 100644 --- a/lib/config.json +++ b/lib/config.json @@ -1 +1 @@ -{"threads": 5, "agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", "timeout": 10} \ No newline at end of file +{"threads": 5, "pass": "ne", "user": "No", "timeout": 10, "agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0"} \ No newline at end of file diff --git a/lib/request.py b/lib/request.py index a6b5a1e..891ab40 100644 --- a/lib/request.py +++ b/lib/request.py @@ -42,7 +42,7 @@ class Request: """ try: config = json.load(open('lib/config.json')) - r = requests.get(domain_name + path, timeout=config['timeout'], headers={'User-Agent' : config['agent']}, verify=False) + r = requests.get(domain_name + path, timeout=config['timeout'], headers={'User-Agent' : config['agent']}, auth=(config['user'], config['pass']), verify=False) httpResponse = str((r.text).encode('utf-8')) headers = r.headers cookies = r.cookies @@ -50,8 +50,10 @@ class Request: response = [httpResponse, headers, cookies, status_code] return response except requests.exceptions.Timeout: + print(e) print(Fore.RED + '[x] Connection timed out' + Fore.RESET) except requests.exceptions.ConnectionError as e: + print(e) print(Fore.RED + '[x] Connection error\n | Please make sure you provided the right URL' + Fore.RESET) except requests.exceptions.RequestException as e: print(Fore.RED + str(e) + Fore.RESET) @@ -68,7 +70,7 @@ class Request: """ try: config = json.load(open('lib/config.json')) - r = requests.head(domain_name + path, timeout=config['timeout'], headers={'User-Agent' : config['agent']}, allow_redirects=False, verify=False) + r = requests.head(domain_name + path, timeout=config['timeout'], headers={'User-Agent' : config['agent']}, auth=(config['user'], config['pass']), allow_redirects=False, verify=False) status_code = str(r.status_code) if status_code == '405': print("WARNING, (HEAD) method not allowed!!") @@ -126,7 +128,7 @@ class Request: because usually the TYPO3 version is in the first few lines of the response. """ config = json.load(open('lib/config.json')) - r = requests.get(domain_name + path, stream=True, timeout=config['timeout'], headers={'User-Agent' : config['agent']}, verify=False) + r = requests.get(domain_name + path, stream=True, timeout=config['timeout'], headers={'User-Agent' : config['agent']}, auth=(config['user'], config['pass']), verify=False) if r.status_code == 200: try: for content in r.iter_content(chunk_size=400, decode_unicode=False): diff --git a/lib/version_information.py b/lib/version_information.py index dbff1dd..4bd73cd 100644 --- a/lib/version_information.py +++ b/lib/version_information.py @@ -42,8 +42,14 @@ class VersionInformation: version = 'could not be determined' for path, regex in files.items(): response = Request.version_information(domain.get_name(), path, regex) - if not (response is None) and (len(response) > len(domain.get_typo3_version())): - domain.set_typo3_version(response) - return True + + if not (response is None): + string = '[!] ' + 'Found version file:' + print(string.ljust(30) + path) + + if (version is 'could not be determined'): + version = response + elif (len(response) > len(version)): + version = response domain.set_typo3_version(version) \ No newline at end of file diff --git a/typo3_enumerator.py b/typo3_enumerator.py index 8106370..0f01289 100755 --- a/typo3_enumerator.py +++ b/typo3_enumerator.py @@ -18,7 +18,7 @@ # along with this program. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/) #------------------------------------------------------------------------------- -__version__ = '0.4.5.1' +__version__ = '0.4.5.2' __program__ = 'Typo-Enumerator' __description__ = 'Automatic Typo3 enumeration tool' __author__ = 'https://github.com/whoot' @@ -29,6 +29,7 @@ import datetime import argparse import json import inspect +import base64 from colorama import Fore, init, deinit, Style from lib.check_installation import Typo3_Installation from lib.version_information import VersionInformation @@ -69,6 +70,7 @@ Options: Default: 10 seconds --agent USER_AGENT The user-agent used for all requests Default: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0 + --auth USER:PASS Username and Password for HTTP Basic Authorization --threads THREADS The number of threads used for enumerating the extensions Default: 5 @@ -98,6 +100,7 @@ Options: parser.add_argument('-p', '--port', dest='port', type=int) parser.add_argument('--threads', dest='threads', type=int, default = 5) parser.add_argument('--agent', dest='agent', type=str, default = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0') + parser.add_argument('--auth', dest='auth', type=str, default = 'No:ne') parser.add_argument('--timeout', dest='timeout', type=int, default = 10) help.add_argument( '-h', '--help', action='store_true') args = parser.parse_args() @@ -132,7 +135,7 @@ Options: for line in f: self.__domain_list.append(Domain(line.strip('\n'), args.ext_state, args.top)) - config = {'threads':args.threads, 'agent':args.agent, 'timeout':args.timeout} + config = {'threads':args.threads, 'agent':args.agent, 'timeout':args.timeout, 'user': (args.auth).split(':')[0], 'pass': (args.auth).split(':')[1]} json.dump(config, open(os.path.join(self.__path, 'lib', 'config.json'), 'w')) for domain in self.__domain_list: