From 7943f0e0a64ea767605ade5cf9bd13b83800ce8a Mon Sep 17 00:00:00 2001 From: Evan Lewis Date: Wed, 21 Feb 2018 16:19:48 -0500 Subject: [PATCH 1/3] Added censys functionality --- .gitignore | 4 +- autosploit.py | 165 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 158 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 9f7f845..7618756 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ *.pyc .idea/* api.p -hosts.txt \ No newline at end of file +hosts.txt +secret.p +uid.p diff --git a/autosploit.py b/autosploit.py index a01bb7c..1a39598 100644 --- a/autosploit.py +++ b/autosploit.py @@ -23,6 +23,8 @@ import pickle import threading import subprocess +import json +import requests import shodan # idk if you're going to need this since retrying is a decorator (see line 410) @@ -343,6 +345,115 @@ def targets(clobber=True, hostLimit = -1): print("\n\n\n[{}]Done.".format(t.green("+"))) print("[{}]Hosts appended to list at ".format(t.green("+"), hostpath)) +def censysTargets(clobber=True, hostLimit=-1): + """Function to gather target host(s) from Shodan.""" + global query + global stop_animation + API_URL = "https://censys.io/api/v1/search/ipv4" + UID = "" + SECRET = "" + + print("\033[H\033[J") # Clear terminal + logo() + + if not os.path.isfile("uid.p"): + print("[{}]Please provide your Censys API ID.".format(t.green("+"))) + + UID = raw_input("API ID: ") + pickle.dump(UID, open("uid.p", "wb")) + path = os.path.abspath("uid.p") + print("[{}]\nYour API ID has been saved to {}".format(t.green("+"), path)) + + else: + try: + UID = pickle.load(open("uid.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("uid.p") + print("\n[{}]Your API ID was loaded from {}".format(t.green("+"), path)) + + if not os.path.isfile("secret.p"): + print("[{}]Please provide your Censys Secret key.".format(t.green("+"))) + + SECRET = raw_input("Secret key: ") + pickle.dump(UID, open("secret.p", "wb")) + path = os.path.abspath("secret.p") + print("[{}]\nYour Secret key has been saved to {}".format(t.green("+"), path)) + + else: + try: + SECRET = pickle.load(open("secret.p", "rb")) + except IOError as e: + print("\n[{}]Critical. An IO error was raised while attempting to read Secret key data.\n{}".format( + t.red("!"), e)) + + path = os.path.abspath("secret.p") + print("\n[{}]Your Secret key was loaded from {}".format(t.green("+"), path)) + + 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: + # fix this, seems to be some issues with it, I could be wrong though + while True: + query = raw_input("\n<" + t.cyan("PLATFORM") + ">$ ") + if query == "": + print("[{}]Query cannot be null.".format(t.red("!"))) + else: + break + params = {'query' : query} + print("[{}]Please stand by while results are being collected...\n\n\n".format( + t.green("+"))) + time.sleep(1) + + try: + response = requests.post(API_URL, json = params, auth=(UID, SECRET)) + except Exception as e: + print("\n[{}]Critical. An error was raised with the following error message.\n".format(t.red("!"))) + + if response.status_code != 200: + print(result.json()["error"]) + sys.exit(1) + + result = response.json() + + thread = threading.Thread(target=animation, args=("collecting results", )) + thread.daemon = True + thread.start() + + # TODO:/ + # edit the clobber function to work properly + if clobber: + with open('hosts.txt', 'wb') as log: + for _ in xrange(toolbar_width): + time.sleep(0.1) + for service in result['results']: + if hostLimit > 0 or hostLimit < 0: + log.write("{}{}".format(service['ip'], os.linesep)) + hostLimit -= 1 + else: + break + hostpath = os.path.abspath("hosts.txt") + stop_animation = True + print("\n\n\n[{}]Done.".format(t.green("+"))) + print("[{}]Host list saved to {}".format(t.green("+"), hostpath)) + else: + with open("hosts.txt", "ab") as log: + for i in xrange(toolbar_width): + time.sleep(0.1) + for service in result['results']: + if hostLimit > 0 or hostLimit < 0: + log.write("{}{}".format(service['ip'], os.linesep)) + hostLimit -= 1 + else: + break + hostpath = os.path.abspath("hosts.txt") + stop_animation = True + print("\n\n\n[{}]Done.".format(t.green("+"))) + print("[{}]Hosts appended to list at ".format(t.green("+"), hostpath)) # TODO:/ # custom list importing needs to be done here. @@ -481,6 +592,7 @@ def try_shodan(): # 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() @@ -493,23 +605,56 @@ def try_shodan(): 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': + searchOption = input("\nSelect an option:\n1. Search Shodan\n2. Search Censys\n3. Search Shodan and Censys ") + if searchOption == 1: + if not os.path.isfile("hosts.txt"): targets(True, hostLimit) else: - print("\n[{}]Unhandled Option.".format(t.red("!"))) + 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 searchOption == 2: + if not os.path.isfile("hosts.txt"): + censysTargets(True, hostLimit) + else: + append = raw_input( + "\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [A/O]: ").lower() + if append == 'a': + censysTargets(False, hostLimit) + elif append == 'o': + censysTargets(True, hostLimit) + else: + print("\n[{}]Unhandled Option.".format(t.red("!"))) + elif searchOption == 3: + if not os.path.isfile("hosts.txt"): + targets(True, hostLimit) + censysTargets(False, hostLimit) + else: + append = raw_input( + "\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [A/O]: ").lower() + if append == 'a': + targets(False, hostLimit) + censysTargets(False, hostLimit) + elif append == 'o': + targets(True, hostLimit) + censysTargets(False, hostLimit) + else: + print("\n[{}]Unhandled Option.".format(t.red("!"))) + + else: + print("\n[{}]Unhandled Option.".format(t.red("!"))) + + elif action == '3': if not os.path.isfile("hosts.txt"): import_custom(True) From 0d3cafa2e660458d990e5b6d2ae52b18314d76a8 Mon Sep 17 00:00:00 2001 From: Evan Lewis Date: Wed, 21 Feb 2018 17:12:29 -0500 Subject: [PATCH 2/3] Added Censys functionality Moved Censys search function into its own file --- autosploit.py | 122 +++-------------------------------------------- censysSearch.py | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 115 deletions(-) create mode 100644 censysSearch.py diff --git a/autosploit.py b/autosploit.py index 1a39598..34c17de 100644 --- a/autosploit.py +++ b/autosploit.py @@ -25,7 +25,7 @@ import subprocess import json import requests - +import censysSearch import shodan # idk if you're going to need this since retrying is a decorator (see line 410) # from retrying import retry @@ -345,115 +345,7 @@ def targets(clobber=True, hostLimit = -1): print("\n\n\n[{}]Done.".format(t.green("+"))) print("[{}]Hosts appended to list at ".format(t.green("+"), hostpath)) -def censysTargets(clobber=True, hostLimit=-1): - """Function to gather target host(s) from Shodan.""" - global query - global stop_animation - API_URL = "https://censys.io/api/v1/search/ipv4" - UID = "" - SECRET = "" - - print("\033[H\033[J") # Clear terminal - logo() - - if not os.path.isfile("uid.p"): - print("[{}]Please provide your Censys API ID.".format(t.green("+"))) - UID = raw_input("API ID: ") - pickle.dump(UID, open("uid.p", "wb")) - path = os.path.abspath("uid.p") - print("[{}]\nYour API ID has been saved to {}".format(t.green("+"), path)) - - else: - try: - UID = pickle.load(open("uid.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("uid.p") - print("\n[{}]Your API ID was loaded from {}".format(t.green("+"), path)) - - if not os.path.isfile("secret.p"): - print("[{}]Please provide your Censys Secret key.".format(t.green("+"))) - - SECRET = raw_input("Secret key: ") - pickle.dump(UID, open("secret.p", "wb")) - path = os.path.abspath("secret.p") - print("[{}]\nYour Secret key has been saved to {}".format(t.green("+"), path)) - - else: - try: - SECRET = pickle.load(open("secret.p", "rb")) - except IOError as e: - print("\n[{}]Critical. An IO error was raised while attempting to read Secret key data.\n{}".format( - t.red("!"), e)) - - path = os.path.abspath("secret.p") - print("\n[{}]Your Secret key was loaded from {}".format(t.green("+"), path)) - - 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: - # fix this, seems to be some issues with it, I could be wrong though - while True: - query = raw_input("\n<" + t.cyan("PLATFORM") + ">$ ") - if query == "": - print("[{}]Query cannot be null.".format(t.red("!"))) - else: - break - params = {'query' : query} - print("[{}]Please stand by while results are being collected...\n\n\n".format( - t.green("+"))) - time.sleep(1) - - try: - response = requests.post(API_URL, json = params, auth=(UID, SECRET)) - except Exception as e: - print("\n[{}]Critical. An error was raised with the following error message.\n".format(t.red("!"))) - - if response.status_code != 200: - print(result.json()["error"]) - sys.exit(1) - - result = response.json() - - thread = threading.Thread(target=animation, args=("collecting results", )) - thread.daemon = True - thread.start() - - # TODO:/ - # edit the clobber function to work properly - if clobber: - with open('hosts.txt', 'wb') as log: - for _ in xrange(toolbar_width): - time.sleep(0.1) - for service in result['results']: - if hostLimit > 0 or hostLimit < 0: - log.write("{}{}".format(service['ip'], os.linesep)) - hostLimit -= 1 - else: - break - hostpath = os.path.abspath("hosts.txt") - stop_animation = True - print("\n\n\n[{}]Done.".format(t.green("+"))) - print("[{}]Host list saved to {}".format(t.green("+"), hostpath)) - else: - with open("hosts.txt", "ab") as log: - for i in xrange(toolbar_width): - time.sleep(0.1) - for service in result['results']: - if hostLimit > 0 or hostLimit < 0: - log.write("{}{}".format(service['ip'], os.linesep)) - hostLimit -= 1 - else: - break - hostpath = os.path.abspath("hosts.txt") - stop_animation = True - print("\n\n\n[{}]Done.".format(t.green("+"))) - print("[{}]Hosts appended to list at ".format(t.green("+"), hostpath)) # TODO:/ # custom list importing needs to be done here. @@ -625,29 +517,29 @@ def try_shodan(): print("\n[{}]Unhandled Option.".format(t.red("!"))) elif searchOption == 2: if not os.path.isfile("hosts.txt"): - censysTargets(True, hostLimit) + censysSearch.censysTargets(True, hostLimit) else: append = raw_input( "\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [A/O]: ").lower() if append == 'a': - censysTargets(False, hostLimit) + censysSearch.censysTargets(False, hostLimit) elif append == 'o': - censysTargets(True, hostLimit) + censysSearch.censysTargets(True, hostLimit) else: print("\n[{}]Unhandled Option.".format(t.red("!"))) elif searchOption == 3: if not os.path.isfile("hosts.txt"): targets(True, hostLimit) - censysTargets(False, hostLimit) + censysSearch.censysTargets(False, hostLimit) else: append = raw_input( "\n[" + t.magenta("?") + "]Append hosts to file or overwrite? [A/O]: ").lower() if append == 'a': targets(False, hostLimit) - censysTargets(False, hostLimit) + censysSearch.censysTargets(False, hostLimit) elif append == 'o': targets(True, hostLimit) - censysTargets(False, hostLimit) + censysSearch.censysTargets(False, hostLimit) else: print("\n[{}]Unhandled Option.".format(t.red("!"))) diff --git a/censysSearch.py b/censysSearch.py new file mode 100644 index 0000000..14454b3 --- /dev/null +++ b/censysSearch.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python2.7 +import os +import sys +import time +import pickle +import threading +import subprocess +import json +import requests +import autosploit +from blessings import Terminal + +t = Terminal() + +def censysTargets(clobber=True, hostLimit=-1): + """Function to gather target host(s) from Censys.""" + global query + global stop_animation + API_URL = "https://censys.io/api/v1/search/ipv4" + UID = "" + SECRET = "" + + print("\033[H\033[J") # Clear terminal + autosploit.logo() + + if not os.path.isfile("uid.p"): + print("[{}]Please provide your Censys API ID.".format(t.green("+"))) + + UID = raw_input("API ID: ") + pickle.dump(UID, open("uid.p", "wb")) + path = os.path.abspath("uid.p") + print("[{}]\nYour API ID has been saved to {}".format(t.green("+"), path)) + + else: + try: + UID = pickle.load(open("uid.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("uid.p") + print("\n[{}]Your API ID was loaded from {}".format(t.green("+"), path)) + + if not os.path.isfile("secret.p"): + print("[{}]Please provide your Censys Secret key.".format(t.green("+"))) + + SECRET = raw_input("Secret key: ") + pickle.dump(UID, open("secret.p", "wb")) + path = os.path.abspath("secret.p") + print("[{}]\nYour Secret key has been saved to {}".format(t.green("+"), path)) + + else: + try: + SECRET = pickle.load(open("secret.p", "rb")) + except IOError as e: + print("\n[{}]Critical. An IO error was raised while attempting to read Secret key data.\n{}".format( + t.red("!"), e)) + + path = os.path.abspath("secret.p") + print("\n[{}]Your Secret key was loaded from {}".format(t.green("+"), path)) + + 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: + # fix this, seems to be some issues with it, I could be wrong though + while True: + query = raw_input("\n<" + t.cyan("PLATFORM") + ">$ ") + if query == "": + print("[{}]Query cannot be null.".format(t.red("!"))) + else: + break + params = {'query' : query} + print("[{}]Please stand by while results are being collected...\n\n\n".format( + t.green("+"))) + time.sleep(1) + + try: + response = requests.post(API_URL, json = params, auth=(UID, SECRET)) + except Exception as e: + print("\n[{}]Critical. An error was raised with the following error message.\n".format(t.red("!"))) + + if response.status_code != 200: + print(result.json()["error"]) + sys.exit(1) + + result = response.json() + + thread = threading.Thread(target=autosploit.animation, args=("collecting results", )) + thread.daemon = True + thread.start() + + # TODO:/ + # edit the clobber function to work properly + if clobber: + with open('hosts.txt', 'wb') as log: + for _ in xrange(autosploit.toolbar_width): + time.sleep(0.1) + for service in result['results']: + if hostLimit > 0 or hostLimit < 0: + log.write("{}{}".format(service['ip'], os.linesep)) + hostLimit -= 1 + else: + break + autosploit.hostpath = os.path.abspath("hosts.txt") + autosploit.stop_animation = True + print("\n\n\n[{}]Done.".format(t.green("+"))) + print("[{}]Host list saved to {}".format(t.green("+"), autosploit.hostpath)) + else: + with open("hosts.txt", "ab") as log: + for i in xrange(autosploit.toolbar_width): + time.sleep(0.1) + for service in result['results']: + if hostLimit > 0 or hostLimit < 0: + log.write("{}{}".format(service['ip'], os.linesep)) + hostLimit -= 1 + else: + break + autosploit.hostpath = os.path.abspath("hosts.txt") + autosploit.stop_animation = True + print("\n\n\n[{}]Done.".format(t.green("+"))) + print("[{}]Hosts appended to list at ".format(t.green("+"), autosploit.hostpath)) From 408189973dcba6538548b3b969aaa08ba6c2503f Mon Sep 17 00:00:00 2001 From: Evan Lewis Date: Wed, 21 Feb 2018 17:56:39 -0500 Subject: [PATCH 3/3] Updated requirements document to include requests module --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index e4af09f..91f4edb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ shodan==1.7.7 blessings==1.6.1 +requests==2.18.4