def shoNuff(ip, sKEY): api = shodan.Shodan(sKEY) shodanDICT = {} ssList = set() try: helper.printW("Shodan : " + ip) host = api.host(ip) except shodan.APIError as e: helper.printR("Shodan : " + str(e)) return shodanDICT, ssList shodanDICT["Host"] = host['ip_str'] shodanDICT["HostName"] = str(host['hostnames']) shodanDICT["Org"] = host.get('org', 'n/a') shodanDICT["OS"] = str(host.get('os', 'n/a')) shodanDICT["Ports"] = str(host['ports']) shodanDICT["vulns"] = str(host.get('vulns', 'n/a')) for item in host['data']: shodanDICT[str(item['port'])] = item['data'].strip() # Add to the screen shot list if we got an http response CBH = item['data'].strip() if re.search('http', CBH, re.IGNORECASE): url = "http://" + ip + ":" + str(item['port']) ssList.add(url) return shodanDICT, ssList
def confirmIP (matchWork, cidr): # Lets see if this is a real IP ipFull = str(matchWork) + cidr matchWork = str(matchWork) try: ip = ipaddress.ip_address(matchWork) except ValueError: helper.printR2("Address/Netmask is invalid", ipFull) return False except Exception as e: helper.printR("[validateHost] " + str(e) + " " + ipFull) return False # If we got here the IP is valid. return matchWork
def main(): chromeSHOT = set() hostSET = set() privHostDIC = {} hostDIC = {} domain = args.domain SoFileTXT = oDir + "/Shodan-IO.txt" SoFileCSV = oDir + "/Shodan-IO.csv" CoFileCSV = oDir + "/Censys-IO.csv" CoFileTXT = oDir + "/Censys-IO.txt" pubLog = oDir + "/Resolved-Public-Hosts.txt" privLog = oDir + "/Resolved-Private-Hosts.txt" # SATGE 0 : Gather the targets if args.hostName: CBH = args.hostName hostSET.add(CBH.strip()) # or a hostlist elif args.hostList: CBH = args.hostList with open(CBH, encoding="utf8", errors='ignore') as f: for target in f: # lets clean up any non ascii characters target = re.sub(r'[^\x00-\x7f]', r'', target) target = target.strip() hostSET.add(target) else: helper.printR("I dont know how u got here") sys.exit(1) # SATGE 1 : If we have work to do let do it workS1 = len(hostSET) if workS1 > 0: count = 0 helper.printP2("STAGE1 Validating IP/Hosts", str(workS1)) for hst in hostSET: count = count + 1 pubHSTs, privHSTs = hostWork.validateHost(hst, count, workS1, domain) if pubHSTs: hostDIC = {**pubHSTs, **hostDIC} if privHSTs: privHostDIC = {**privHSTs, **privHostDIC} # Write out the current hosts helper.logTXT(hostDIC, pubLog) helper.logTXT(privHostDIC, privLog) # SATGE 2 : Now we have a list of hosts to ip workS2 = len(hostDIC) InvalidTargets = workS1 - workS2 helper.printP2("Invalid Dropped Targets", str(InvalidTargets)) helper.printP2("Remaining Valid Targets", str(workS2)) if workS2 > 0: if (args.shodan or args.censys): for key, value in hostDIC.items(): Results = {} # SHODAN if args.shodan: Results, scrSHOT = shoNuff.shoNuff(key, sKEY) if Results: #Now we have results ... Guess we can output it now helper.loggER(Results) helper.logTXT(Results, SoFileTXT) helper.logCSV(Results, SoFileCSV) if scrSHOT: # Now lets see if we want and need to take screenshots count = 0 shots = len(scrSHOT) for u in scrSHOT: count = count + 1 match = re.search(r'.*://(.*):(.*)', u) # replace ip with hostname if available hname = hostDIC.get(key, match.group(1)) u = u.replace(key, hname) helper.printP2( "Taking Screen Shots [" + str(count) + "/" + str(shots) + "]", u) ssFile = oDir + "/" + hname + "_" + match.group( 2) + "_shodan_screenshot.png" chromeShot.chromeShot(u, ssFile) # CENSYS if args.censys: Results, scrSHOT = censei.cenSYS(key, cID, cCRET) if Results: #Now we have results ... Guess we can output it now helper.loggER(Results) helper.logTXT(Results, CoFileTXT) helper.logCSV(Results, CoFileCSV) if scrSHOT: # Now lets see if we want and need to take screenshots count = 0 shots = len(scrSHOT) for u in scrSHOT: count = count + 1 match = re.search(r'.*://(.*):(.*)', u) # replace ip with hostname if available hname = hostDIC.get(key, match.group(1)) u = u.replace(key, hname) helper.printP2( "Taking Screen Shots [" + str(count) + "/" + str(shots) + "]", u) ssFile = oDir + "/" + hname + "_" + match.group( 2) + "_censys_screenshot.png" chromeShot.chromeShot(u, ssFile) workS2 = workS2 - 1 helper.printW2("Fin", value) helper.printW2("Hosts Left", str(workS2)) # Note: All API methods are rate-limited to 1 request/ second. shleep = 5 helper.printW2("Sleeping for ", str(shleep)) time.sleep(shleep) print('') # --sshot without checking censys or shodan if (args.sshot and not (args.shodan or args.censys)): hostDIC = {**hostDIC, **privHostDIC} # We are just going to try screenshotting both HTTP and HTTPs Count = len(hostDIC) c = 0 helper.printW2("Screenshoting Host(s)", str(Count)) for key, value in hostDIC.items(): c = c + 1 helper.printW2("Screenshot [" + str(c) + "/" + str(Count) + "]", value) u = "http://" + value ssFile = oDir + "/" + value + "_http_screenshot.png" chromeShot.chromeShot(u, ssFile) u = "https://" + value ssFile = oDir + "/" + value + "_https_screenshot.png" chromeShot.chromeShot(u, ssFile) # Done ! print('') helper.printY2("Output Files are located at:", oDir + "/") print('')
def cenSYS(ip, cID, cCRET): host = dict() censysDICT = {} ssList = set() try: c = censys.ipv4.CensysIPv4(cID, cCRET) host = c.view(ip) helper.printW("CensysIO : " + ip) except Exception as e: helper.printR("CensysIO : " + ip + " : " + str(e)) return censysDICT, ssList censysDICT["Host"] = host['ip'] if 'autonomous_system' in host.keys(): censysDICT["Network"] = host['autonomous_system']['routed_prefix'] censysDICT["Desc"] = host['autonomous_system']['description'] censysDICT["Name"] = host['autonomous_system']['name'] censysDICT["Proto"] = str(host.get('protocols', 'n/a')) censysDICT["Ports"] = str(host.get('ports', 'n/a')) # HTTP Ports for p in host['protocols']: match = re.search(r'(\d+)\/(\w+)', p) if match: port = match.group(1) proto = match.group(2) # Add to the screen shot list if its http if re.search('http', proto, re.IGNORECASE): url = proto + "://" + ip + ":" + port ssList.add(url) if proto == "https": try: otherNames = host[str(port)][str( proto)]['tls']['certificate']['parsed']['names'] dns_names = host[str(port)][str( proto)]['tls']['certificate']['parsed']['extensions'][ 'subject_alt_name']['dns_names'] censysDICT[str(port) + "_Names"] = str(otherNames) censysDICT[str(port) + "_DNS"] = str(dns_names) except KeyError: continue try: if 'title' in host[str(port)][str(proto)]['get'].keys(): title = host[str(port)][str(proto)]['get']['title'] censysDICT[str(port) + "_title"] = str(title) if 'status_code' in host[str(port)][str(proto)]['get'].keys(): status = host[str(port)][str(proto)]['get']['status_code'] censysDICT[str(port) + "_status"] = str(status) if 'metadata' in host[str(port)][str(proto)]['get'].keys(): metadata = host[str(port)][str(proto)]['get']['metadata'] censysDICT[str(port) + "_metadata"] = str(metadata) if 'headers' in host[str(port)][str(proto)]['get'].keys(): headers = host[str(port)][str(proto)]['get']['headers'] censysDICT[str(port) + "_headers"] = str(headers) except Exception as error: continue return censysDICT, ssList
dest="combine", help="Combine output types", action="store_true") parser.add_argument("--domain", dest="domain", help="Add domain to hostnames") args = parser.parse_args() # Its either a hostfile or a single host if (args.hostList is None) and (args.hostName is None): parser.print_help() exit() if (args.hostList): if not os.path.isfile(args.hostList): helper.printR("Check File: " + args.hostList) exit() # Load the keys from config file #PSconfigFile = os.path.abspath(os.path.dirname(__file__)) + "/api-keys.ini" # Moved keys to a not git controled directory PSconfigFile = "/home/cb/Documents/api-keys.ini" if not os.path.isfile(PSconfigFile): helper.printR("Check API key File: " + PSconfigFile) exit() config = configparser.ConfigParser() config.read(PSconfigFile) sKEY = config.get('shodan.io', 'shodan_apiKEY', fallback='Not-Configured') cID = config.get('censys.io', 'censys_apiID', fallback='Not-Configured') cCRET = config.get('censys.io',