diff --git a/.gitignore b/.gitignore index 7618756..589e0df 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ api.p hosts.txt secret.p uid.p +etc/tokens/* \ No newline at end of file diff --git a/api_calls/censys.py b/api_calls/censys.py index 4e709c9..7a73b35 100644 --- a/api_calls/censys.py +++ b/api_calls/censys.py @@ -11,6 +11,10 @@ class CensysAPIHook(object): + """ + Censys API hook + """ + def __init__(self, identity, token, query): self.id = identity self.token = token @@ -18,6 +22,9 @@ def __init__(self, identity, token, query): self.host_file = HOST_FILE def censys(self): + """ + connect to the Censys API and pull all IP addresses from the provided query + """ discovered_censys_hosts = set() try: req = requests.post(API_URLS["censys"], auth=(self.id, self.token), json={"query": self.query}) diff --git a/api_calls/shodan.py b/api_calls/shodan.py index 510fbf6..f7277fa 100644 --- a/api_calls/shodan.py +++ b/api_calls/shodan.py @@ -13,6 +13,10 @@ class ShodanAPIHook(object): + """ + Shodan API hook, saves us from having to install another dependency + """ + def __init__(self, token, query, proxy=None): self.token = token self.query = query @@ -20,6 +24,9 @@ def __init__(self, token, query, proxy=None): self.host_file = HOST_FILE def shodan(self): + """ + connect to the API and grab all IP addresses associated with the provided query + """ discovered_shodan_hosts = set() try: req = requests.get(API_URLS["shodan"].format(query=self.query, token=self.token)) diff --git a/api_calls/zoomeye.py b/api_calls/zoomeye.py index a7a882f..2ddb3e1 100644 --- a/api_calls/zoomeye.py +++ b/api_calls/zoomeye.py @@ -15,6 +15,11 @@ class ZoomEyeAPIHook(object): + """ + API hook for the ZoomEye API, in order to connect you need to provide a phone number + so we're going to use some 'lifted' credentials to login for us + """ + def __init__(self, query): self.query = query self.host_file = HOST_FILE @@ -23,6 +28,9 @@ def __init__(self, query): @staticmethod def __decode(filepath): + """ + we all know what this does + """ with open(filepath) as f: data = f.read() token, n = data.split(":") @@ -31,6 +39,11 @@ def __decode(filepath): return token.strip() def __get_auth(self): + """ + get the authorization for the authentication token, you have to login + before you can access the API, this is where the 'lifted' creds come into + play. + """ username = self.__decode(self.user_file) password = self.__decode(self.pass_file) data = {"username": username, "password": password} @@ -39,6 +52,10 @@ def __get_auth(self): return token def zoomeye(self): + """ + connect to the API and pull all the IP addresses that are associated with the + given query + """ discovered_zoomeye_hosts = set() try: token = self.__get_auth() @@ -48,8 +65,8 @@ def zoomeye(self): _json_data = req.json() for item in _json_data["matches"]: if len(item["ip"]) > 1: - # TODO:/ grab all the IP addresses when there's more then 1 - discovered_zoomeye_hosts.add(str(item["ip"][0])) + for ip in item["ip"]: + discovered_zoomeye_hosts.add(ip) else: discovered_zoomeye_hosts.add(str(item["ip"][0])) write_to_file(discovered_zoomeye_hosts, self.host_file) diff --git a/autosploit.py b/autosploit.py index 0d7782e..6871798 100644 --- a/autosploit.py +++ b/autosploit.py @@ -34,6 +34,7 @@ from lib.settings import ( validate_ip_addr, check_services, + load_api_keys, PLATFORM_PROMPT, AUTOSPLOIT_PROMPT, AUTOSPLOIT_TERM_OPTS @@ -556,6 +557,63 @@ def try_shodan(): if __name__ == "__main__": + '''from api_calls import ( + shodan, + censys, + zoomeye + ) + from lib.settings import ( + load_api_keys, + API_URLS, + AUTOSPLOIT_PROMPT + ) + + from lib.output import ( + prompt, + info, + warning + ) + + tokens = load_api_keys() + + possible_apis = API_URLS.keys() + + def get_query(): + query = prompt("enter your search query") + return query + + selected = False + info_msg = "searching {} API with query '{}'" + info("pick a search engine") + for i, api in enumerate(sorted(possible_apis), start=1): + print("{}. {}".format(i, api)) + + while not selected: + choice = raw_input(AUTOSPLOIT_PROMPT) + try: + choice = int(choice) + if choice == 1: + selected = True + query = get_query() + info(info_msg.format("Shodan", query)) + censys.CensysAPIHook(tokens["censys"][1], tokens["censys"][0], query).censys() + elif choice == 2: + selected = True + query = get_query() + info(info_msg.format("Censys", query)) + shodan.ShodanAPIHook(tokens["shodan"][0], query).shodan() + elif choice == 3: + query = get_query() + selected = True + info("ZoomEye token will be loaded automatically") + info(info_msg.format("Zoomeye", query)) + zoomeye.ZoomEyeAPIHook(query).zoomeye() + else: + warning("choice must be between 1-{}".format(len(API_URLS.keys()))) + except: + warning("choice must be integer not string")''' + + logo() if len(sys.argv) > 1: @@ -605,20 +663,17 @@ def start_apache(): start_ap = prompt("Start Apache Service? [Y]es/[N]o") if start_ap == 'y': start_apache() - time.sleep(1.5) - elif start_ap == 'n': error("AutoSploit's MSF related operations require this service to be active.") error("Aborted.") - time.sleep(1.5) sys.exit(0) else: warning("Unhandled Option. Defaulting to starting the service.") start_apache() - 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 + # load_api_keys() if not os.path.isfile("api.p"): info("Please provide your Shodan.io API key.") diff --git a/lib/settings.py b/lib/settings.py index 2370bf4..39f960d 100644 --- a/lib/settings.py +++ b/lib/settings.py @@ -5,6 +5,7 @@ import psutil import lib.output +import api_calls HOST_FILE = "{}/hosts.txt".format(os.getcwd()) @@ -12,6 +13,10 @@ START_APACHE_PATH = "{}/etc/scripts/start_apache.sh".format(os.getcwd()) PLATFORM_PROMPT = "\n{}@\033[36mPLATFORM\033[0m$ ".format(getpass.getuser()) AUTOSPLOIT_PROMPT = "\n\033[31m{}\033[0m@\033[36mautosploit\033[0m# ".format(getpass.getuser()) +API_KEYS = { + "censys": ("{}/etc/tokens/censys.key".format(os.getcwd()), "{}/etc/tokens/censys.id".format(os.getcwd())), + "shodan": ("{}/etc/tokens/shodan.key".format(os.getcwd()), ) +} API_URLS = { "shodan": "https://api.shodan.io/shodan/host/search?key={token}&query={query}", "censys": "https://censys.io/api/v1/search/ipv4", @@ -73,3 +78,35 @@ def write_to_file(data_to_write, filename, mode="a+"): log.write(data_to_write) lib.output.info("successfully wrote info to '{}'".format(filename)) return filename + + +def load_api_keys(path="{}/etc/tokens".format(os.getcwd())): + + """ + load the API keys from their .key files + """ + + def makedir(dir): + """ + make the directory if it does not exist + """ + if not os.path.exists(dir): + os.mkdir(dir) + + makedir(path) + for key in API_KEYS.keys(): + if not os.path.isfile(API_KEYS[key][0]): + access_token = lib.output.prompt("enter your {} API token".format(key.title()), lowercase=False) + if key.lower() == "censys": + identity = lib.output.prompt("enter your {} ID".format(key.title()), lowercase=False) + with open(API_KEYS[key][1], "a+") as log: + log.write(identity) + with open(API_KEYS[key][0], "a+") as log: + log.write(access_token.strip()) + else: + lib.output.info("{} API token loaded from {}".format(key.title(), API_KEYS[key][0])) + api_tokens = { + "censys": (open(API_KEYS["censys"][0]).read(), open(API_KEYS["censys"][1]).read()), + "shodan": (open(API_KEYS["shodan"][0]).read(), ) + } + return api_tokens \ No newline at end of file