From e9f5b82d0586766b9e2a177adefedee8f21c7943 Mon Sep 17 00:00:00 2001 From: ekultek Date: Wed, 11 Oct 2017 14:36:34 -0500 Subject: [PATCH] initial push for an issue (#58) where it would not auto start sqlmap, lots more work to be done so make sure you start the sqlmap server before the process --- .gitignore | 3 +- bin/unzip_gecko.py | 30 ++++++ lib/attacks/nmap_scan/__init__.py | 6 +- lib/attacks/sqlmap_scan/__init__.py | 141 ++++++++++++++++------------ lib/core/settings.py | 73 +++++--------- requirements.txt | 1 + zeus.py | 23 ++--- 7 files changed, 151 insertions(+), 126 deletions(-) diff --git a/.gitignore b/.gitignore index 6623d1f..0b8870f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ log/ geckodriver.log *.pyc .idea/ -bin/executed.txt \ No newline at end of file +bin/executed.txt +bin/paths \ No newline at end of file diff --git a/bin/unzip_gecko.py b/bin/unzip_gecko.py index 132f4f7..3c6674f 100644 --- a/bin/unzip_gecko.py +++ b/bin/unzip_gecko.py @@ -2,6 +2,7 @@ import platform import subprocess import tarfile +import ConfigParser import whichcraft @@ -28,6 +29,34 @@ def disclaimer(): return False +def find_tools(to_search=("sqlmap", "nmap"), directory="{}/bin/paths", filename="path_config.ini"): + lib.core.settings.create_dir(directory.format(os.getcwd())) + full_path = "{}/{}".format( + directory.format(os.getcwd()), + filename + ) + cfgfile = open(full_path, "a+") + parser = ConfigParser.ConfigParser() + path_schema = {} + for item in to_search: + path_obj = whichcraft.which(item) + if path_obj is not None: + path_schema[item] = path_obj + else: + path_schema[item] = None + for key, value in path_schema.iteritems(): + if value is None: + provided_path = lib.core.settings.prompt( + "what is the full path to {} on your system".format(key) + ) + path_schema[key] = provided_path + for program, path in path_schema.iteritems(): + parser.add_section(program) + parser.set(program, "path", path) + parser.write(cfgfile) + cfgfile.close() + + def check_os(current=platform.platform()): """ check the users operating system.. @@ -151,6 +180,7 @@ def main(rewrite="{}/bin/executed.txt", verbose=False): lib.core.settings.logger.debug(lib.core.settings.set_color( "checking if xvfb is on your system...", level=10 )) + find_tools() check_xvfb() untar_gecko(verbose=verbose) if ensure_placed(verbose=verbose): diff --git a/lib/attacks/nmap_scan/__init__.py b/lib/attacks/nmap_scan/__init__.py index c67d539..8bdb219 100644 --- a/lib/attacks/nmap_scan/__init__.py +++ b/lib/attacks/nmap_scan/__init__.py @@ -85,11 +85,11 @@ def show_open_ports(self, json_data, sep="-" * 30): print("{}".format(sep)) -def find_nmap(item_name="nmap", given_search_path=None, verbose=False): +def find_nmap(item_name="nmap", verbose=False): """ find nmap on the users system if they do not specify a path for it or it is not in their PATH """ - return find_application(item_name, given_search_path=given_search_path, verbose=verbose) + return find_application(item_name, verbose=verbose) def perform_port_scan(url, ports=None, scanner=NmapHook, verbose=False, opts=None, **kwargs): @@ -108,7 +108,7 @@ def perform_port_scan(url, ports=None, scanner=NmapHook, verbose=False, opts=Non logger.debug(set_color( "checking for nmap on your system...", level=10 )) - nmap_exists = find_nmap(verbose=verbose) + nmap_exists = "".join(find_nmap(verbose=verbose)) if nmap_exists: if verbose: logger.debug(set_color( diff --git a/lib/attacks/sqlmap_scan/__init__.py b/lib/attacks/sqlmap_scan/__init__.py index be07af6..d956578 100644 --- a/lib/attacks/sqlmap_scan/__init__.py +++ b/lib/attacks/sqlmap_scan/__init__.py @@ -1,11 +1,12 @@ import json +import os +import time import re try: import urllib2 # python 2 except ImportError: import urllib as urllib2 # python 3 -import subprocess import requests @@ -108,14 +109,15 @@ def show_sqlmap_log(self, api_id): already_displayed.add(log_json["log"][i]["message"]) -def find_sqlmap(given_search_path=None, to_find="sqlmapapi.py", verbose=False): +def find_sqlmap(to_find="sqlmap", verbose=False): """ find sqlmap on the users system """ - return lib.core.settings.find_application(to_find, verbose=verbose, given_search_path=given_search_path) + found_path = lib.core.settings.find_application(to_find, verbose=verbose) + return found_path -def sqlmap_scan_main(url, port=None, verbose=None, auto_search=False, opts=None, given_path=None, full_path=None): +def sqlmap_scan_main(url, port=None, verbose=None, opts=None, auto_start=False): """ the main function that will be called and initialize everything """ @@ -126,76 +128,97 @@ def ___dict_args(): """ return {key: value for key, value in opts} - if auto_search: + if auto_start: lib.core.settings.logger.info(lib.core.settings.set_color( "attempting to find sqlmap on your system..." )) - path = ''.join(find_sqlmap(verbose=verbose, given_search_path=given_path)) - if path: - subprocess.check_output(["python", path, "-s"]) - else: try: - sqlmap_scan = SqlmapHook(url, port=port) + path = "".join(find_sqlmap("sqlmap", verbose=verbose)) lib.core.settings.logger.info(lib.core.settings.set_color( - "initializing new sqlmap scan with given URL '{}'...".format(url) + "attempting to call sqlmap API..." )) - sqlmap_scan.init_new_scan() - if verbose: - lib.core.settings.logger.debug(lib.core.settings.set_color( - "scan initialized...", level=10 - )) + os.spawnl(os.P_NOWAIT, "python {} -s".format(os.path.join(path, "sqlmapapi.py"))) lib.core.settings.logger.info(lib.core.settings.set_color( - "gathering sqlmap API scan ID..." + "API started, continuing process..." + ) + ) + time.sleep(3) + except Exception as e: + print e + lib.core.settings.logger.error(lib.core.settings.set_color( + "ran into an error while trying to start the sqlmap API, please do it manually...", level=50 + )) + lib.core.settings.prompt( + "press enter when ready to start..." + ) + else: + is_started = lib.core.settings.search_for_process("sqlmapapi.py") + if not is_started: + lib.core.settings.prompt( + "sqlmap API is not started, start it and press enter to continue..." + ) + try: + sqlmap_scan = SqlmapHook(url, port=port) + lib.core.settings.logger.info(lib.core.settings.set_color( + "initializing new sqlmap scan with given URL '{}'...".format(url) + )) + sqlmap_scan.init_new_scan() + if verbose: + lib.core.settings.logger.debug(lib.core.settings.set_color( + "scan initialized...", level=10 )) - api_id = sqlmap_scan.get_scan_id() + lib.core.settings.logger.info(lib.core.settings.set_color( + "gathering sqlmap API scan ID..." + )) + api_id = sqlmap_scan.get_scan_id() + if verbose: + lib.core.settings.logger.debug(lib.core.settings.set_color( + "current sqlmap scan ID: '{}'...".format(api_id), level=10 + )) + lib.core.settings.logger.info(lib.core.settings.set_color( + "starting sqlmap scan on url: '{}'...".format(url) + )) + if opts: if verbose: lib.core.settings.logger.debug(lib.core.settings.set_color( - "current sqlmap scan ID: '{}'...".format(api_id), level=10 + "using arguments: '{}'...".format(___dict_args()), level=10 )) lib.core.settings.logger.info(lib.core.settings.set_color( - "starting sqlmap scan on url: '{}'...".format(url) + "adding arguments to sqlmap API..." )) - if opts: - if verbose: - lib.core.settings.logger.debug(lib.core.settings.set_color( - "using arguments: '{}'...".format(___dict_args()), level=10 - )) - lib.core.settings.logger.info(lib.core.settings.set_color( - "adding arguments to sqlmap API..." + else: + if verbose: + lib.core.settings.logger.debug(lib.core.settings.set_color( + "no arguments passed, skipping...", level=10 )) - else: - if verbose: - lib.core.settings.logger.debug(lib.core.settings.set_color( - "no arguments passed, skipping...", level=10 - )) - lib.core.settings.logger.warning(lib.core.settings.set_color( - "please keep in mind that this is the API, output will " - "not be saved to log file, it may take a little longer " - "to finish processing, launching sqlmap...", level=30 + lib.core.settings.logger.warning(lib.core.settings.set_color( + "please keep in mind that this is the API, output will " + "not be saved to log file, it may take a little longer " + "to finish processing, launching sqlmap...", level=30 + )) + sqlmap_scan.start_scan(api_id, opts=opts) + print("-" * 30) + sqlmap_scan.show_sqlmap_log(api_id) + print("-" * 30) + except requests.exceptions.HTTPError as e: + lib.core.settings.logger.exception(lib.core.settings.set_color( + "ran into error '{}', seems you didn't start the server, check " + "the server port and try again...".format(e), level=50 + )) + pass + except Exception as e: + if "HTTPConnectionPool(host='127.0.0.1'" in str(e): + lib.core.settings.logger.error(lib.core.settings.set_color( + "sqlmap API is not started, did you forget to start it? " + "You will need to open a new terminal, cd into sqlmap, and " + "run `python sqlmapapi.py -s` otherwise pass the correct flags " + "to auto start the API...", level=40 )) - sqlmap_scan.start_scan(api_id, opts=opts) - print("-" * 30) - sqlmap_scan.show_sqlmap_log(api_id) - print("-" * 30) - except requests.exceptions.HTTPError as e: + pass + else: lib.core.settings.logger.exception(lib.core.settings.set_color( - "ran into error '{}', seems you didn't start the server, check " - "the server port and try again...".format(e), level=50 + "ran into error '{}', seems something went wrong, error has " + "been saved to current log file.".format(e), level=50 )) + request_issue_creation() pass - except Exception as e: - if "HTTPConnectionPool(host='127.0.0.1'" in str(e): - lib.core.settings.logger.error(lib.core.settings.set_color( - "sqlmap API is not started, did you forget to start it? " - "You will need to open a new terminal, cd into sqlmap, and " - "run `python sqlmapapi.py -s` otherwise pass the correct flags " - "to auto start the API...", level=40 - )) - pass - else: - lib.core.settings.logger.exception(lib.core.settings.set_color( - "ran into error '{}', seems something went wrong, error has " - "been saved to current log file.".format(e), level=50 - )) - request_issue_creation() - pass diff --git a/lib/core/settings.py b/lib/core/settings.py index 59f3ca5..e9e33e5 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -1,15 +1,15 @@ import difflib import glob -import itertools import logging -import multiprocessing import os +import io import random import re import sys import time +import ConfigParser -import whichcraft +import psutil import bin.unzip_gecko import lib.core.errors @@ -22,7 +22,7 @@ # clone link CLONE = "https://github.com/ekultek/zeus-scanner.git" # current version -VERSION = "1.0.36.6a42" +VERSION = "1.0.37" # colors to output depending on the version VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30} # version string formatting @@ -51,6 +51,8 @@ URL_QUERY_REGEX = re.compile(r"(.*)[?|#](.*){1}\=(.*)") # regex to recognize a URL URL_REGEX = re.compile(r"((https?):((//)|(\\\\))+([\w\d:#@%/;$()~_?\+-=\\\.&](#!)?)*)") +# paths to sqlmap and nmap +TOOL_PATHS = "{}/bin/paths/path_config.ini".format(os.getcwd()) # URL's that are extracted from Google's ban URL EXTRACTED_URL_LOG = "{}/log/extracted-url-log".format(os.getcwd()) # log path for the URL's that are found @@ -299,49 +301,16 @@ def prompt(question, opts=None): ) -def worker(filename, item): - """ - worker for multiprocessing - """ - if item in filename or filename == item or filename is item: - return filename - - -def find_application(to_find, default_search_path="/", proc_num=25, given_search_path=None, verbose=False): - """ - find an application on the users system if it is not in their PATH or no path is given - """ - retval = set() - if whichcraft.which(to_find) is None: - logger.error(set_color( - "{} not in your PATH, what kind of hacker are you?! " - "defaulting to root search, this can take awhile...".format(to_find), level=40 - )) - - if verbose: - logger.debug(set_color( - "starting {} processes to search for '{}' starting at '{}'...".format( - proc_num, to_find, default_search_path if given_search_path is None else given_search_path - ), level=10 - )) - pool = multiprocessing.Pool(proc_num) - walker = os.walk(default_search_path) - file_data_gen = itertools.chain.from_iterable( - (os.path.join(root, f) for f in files) - for root, sub, files in walker - ) - results = pool.map(worker, file_data_gen) - for data in results: - if data is not None: - retval.add(data) - if len(retval) == 0: - raise lib.core.errors.ApplicationNotFound( - "unable to find '{}' on your system, install it first...".format(to_find) - ) - else: - return list(retval) - else: - return whichcraft.which(to_find) +def find_application(application, opt="path", verbose=False): + retval = [] + with open(TOOL_PATHS) as config: + read_conf = config.read() + conf_parser = ConfigParser.RawConfigParser(allow_no_value=True) + conf_parser.readfp(io.BytesIO(read_conf)) + for section in conf_parser.sections(): + if str(section).lower() == str(application).lower(): + retval.append(conf_parser.get(section, opt)) + return retval def get_random_dork(filename="{}/etc/dorks.txt"): @@ -412,3 +381,13 @@ def write_to_log_file(data_to_write, path, filename): "successfully wrote found items to '{}'...".format(full_file_path) )) return full_file_path + + +def search_for_process(name): + all_process_names = set() + for pid in psutil.pids(): + process = psutil.Process(pid) + all_process_names.add(" ".join(process.cmdline()).strip()) + if not any(name in proc for proc in list(all_process_names)): + return False + return True diff --git a/requirements.txt b/requirements.txt index 4deac3a..01fdf63 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,4 @@ pyvirtualdisplay==0.2.1 lxml==3.7.3 google-api-python-client==1.6.4 httplib2==0.10.3 +psutil==5.0.1 \ No newline at end of file diff --git a/zeus.py b/zeus.py index 8551137..610bbc3 100755 --- a/zeus.py +++ b/zeus.py @@ -90,10 +90,6 @@ attacks.add_option("--nmap-args", dest="nmapArguments", metavar="NMAP-ARGS", help="Pass the arguments to send to the nmap API within quotes & " "separated by a pipe. IE '-O|-p 445, 1080'") - attacks.add_option("--auto-start", dest="autoStartSqlmap", action="store_true", - help="Attempt to automatically find sqlmap on your system") - attacks.add_option("--search-here", dest="givenSearchPath", metavar="PATH-TO-START", - help="Start searching for sqlmap in this given path") attacks.add_option("--show-sqlmap", dest="showSqlmapArguments", action="store_true", help="Show the arguments that the sqlmap API understands") attacks.add_option("--show-nmap", dest="showNmapArgs", action="store_true", @@ -102,6 +98,8 @@ help="Show all connections made during the admin panel search") attacks.add_option("--tamper", dest="tamperXssPayloads", metavar="TAMPER-SCRIPT", help="Send the XSS payloads through tampering before sending to the target") + attacks.add_option("--auto", dest="autoStartSqlmap", action="store_true", + help="Attempt to automatically start sqlmap") # search engine options engines = optparse.OptionGroup(parser, "Search engine arguments", @@ -170,11 +168,6 @@ start_up() - if opt.runSqliScan: - prompt( - "make sure you have started the sqlmap API, press enter when ready to continue..." - ) - if opt.showSqlmapArguments: logger.info(set_color( "there are a total of {} arguments understood by sqlmap API, " @@ -381,7 +374,7 @@ def __create_arguments(sqlmap=False, nmap=False): def __run_attacks( url, sqlmap=False, nmap=False, intel=False, xss=False, - verbose=False, admin=False, given_path=None, auto=False, batch=False + verbose=False, admin=False, batch=False, auto_start=False ): """ run the attacks if any are requested @@ -417,7 +410,7 @@ def __run_attacks( if question.lower().startswith("y"): if sqlmap: return sqlmap_scan.sqlmap_scan_main(url.strip(), verbose=verbose, opts=__create_arguments(sqlmap=True), - auto_search=auto, given_path=given_path) + auto_start=auto_start) elif nmap: url_ip_address = replace_http(url.strip()) return nmap_scan.perform_port_scan(url_ip_address, verbose=verbose, opts=__create_arguments(nmap=True)) @@ -462,14 +455,13 @@ def __run_attacks_main(): __run_attacks( url.strip(), sqlmap=opt.runSqliScan, nmap=opt.runPortScan, intel=opt.intelCheck, xss=opt.runXssScan, - admin=opt.adminPanelFinder, given_path=opt.givenSearchPath, - auto=opt.autoStartSqlmap, verbose=opt.runInVerbose, batch=opt.runInBatch + admin=opt.adminPanelFinder, verbose=opt.runInVerbose, batch=opt.runInBatch, + auto_start=opt.autoStartSqlmap ) proxy_to_use, agent_to_use = __config_headers() search_engine = __config_search_engine(verbose=opt.runInVerbose) - print search_engine try: # use a personal dork as the query @@ -606,8 +598,7 @@ def __run_attacks_main(): __run_attacks( url, sqlmap=opt.runSqliScan, nmap=opt.runPortScan, intel=opt.intelCheck, xss=opt.runXssScan, - admin=opt.adminPanelFinder, given_path=opt.givenSearchPath, - auto=opt.autoStartSqlmap, verbose=opt.runInVerbose, batch=opt.runInBatch + admin=opt.adminPanelFinder, verbose=opt.runInVerbose, batch=opt.runInBatch ) else: logger.fatal(set_color(