def devices_nearby(lat, lon, id, query): SHODAN_API_KEY = keys['keys']['shodan'] device = Device.objects.get(id=id) api = Shodan(SHODAN_API_KEY) fail = 0 # Shodan sometimes fails with no reason, sleeping when it happens and it prevents rate limitation try: # Search Shodan results = api.search("geo:" + lat + "," + lon + ",15 " + query) except: fail = 1 print('fail1') if fail == 1: try: results = api.search("geo:" + lat + "," + lon + ",15 " + query) except Exception as e: print(e) try: # Show the results total = len(results['matches']) for counter, result in enumerate(results['matches']): if 'product' in result: product = result['product'] else: product = "" current_task.update_state(state='PROGRESS', meta={ 'current': counter, 'total': total, 'percent': int((float(counter) / total) * 100) }) device1 = DeviceNearby(device=device, ip=result['ip_str'], product=product, org=result['org'], port=str(result['port']), lat=str(result['location']['latitude']), lon=str(result['location']['longitude'])) device1.save() return {'current': total, 'total': total, 'percent': 100} except Exception as e: print(e)
def info_domains(self, domain): results = Shodan.search(self, 'hostname:%s' % domain) if 'matches' in results: all_domains = list( set([ item for r in results['matches'] for item in r['hostnames'] ])) ips = list(set([r['ip_str'] for r in results['matches']])) ports = list(set([r['port'] for r in results['matches']])) transports = list(set([r['transport'] for r in results['matches']])) isp = list( set([r['isp'] for r in results['matches'] if 'isp' in r])) asn = list( set([r['asn'] for r in results['matches'] if 'asn' in r])) orgs = list( set([r['org'] for r in results['matches'] if 'org' in r])) return { 'all_domains': all_domains, 'ips': ips, 'ports': ports, 'transports': transports, 'isp': isp, 'asn': asn, 'orgs': orgs }
def Shodan_start(self, text, page): try: data = '' self.Ui.action_start.setEnabled(False) self.Ui.pushButton_start.setEnabled(False) api = Shodan(self.shodan_key) self.Ui.textEdit_log.append(self.getTime() + '正在查询数据,请稍等...') eventlet.monkey_patch(thread=False) try: timeout = int(self.Ui.comboBox_timeout.currentText()) with eventlet.Timeout(timeout, True): search = api.search(text, int(page)) except: self.Ui.textEdit_log.append(self.getTime() + '获取数据超时') self.Ui.action_start.setEnabled(True) self.Ui.pushButton_start.setEnabled(True) return for result in search['matches']: # print(result) ip = result['ip_str'].strip() port = result['port'] data += 'http://' + str(ip) + ':' + str(port) + '\n' self.Ui.textEdit_result.append(data.strip()) self.Ui.textEdit_log.append(self.getTime() + "查询结束!") except Exception as e: self.Ui.textEdit_log.append(self.getTime() + str(e)) self.Ui.action_start.setEnabled(True) self.Ui.pushButton_start.setEnabled(True) self.Ui.action_start.setEnabled(True) self.Ui.pushButton_start.setEnabled(True)
def main(): API_KEY = getpass.getpass("输入你的APIKEY:") try: os.system("clear") api = Shodan(API_KEY) results = api.search("port:3389 os:windows", limit=None, page=10) except: os.system('clear') print("\nWDNMD,别搞事啊!!") exit(0) print("共有:{}个结果".format(results['total'])) FINAL = get_results(results).get_result() try: id = int(input('1.存入数据库\n2.存入文件\n你的选择:')) except: os.system('clear') print("\nWDNMD,别搞事啊!!") exit(0) if id ==1: db_action(FINAL) elif id == 2: save_to_file(FINAL) else: os.system('clear') print("\nWDNMD,别搞事啊!!") exit(0)
def shodan_search(term): """ Search in shodan using the dork received as parameter and return a list of IPs. """ from shodan import Shodan api = Shodan(SHODAN_API_KEY) try: results = api.search(term) except Exception, e: print 'Error: %s' % e
def shodan_search(fav_hash): ip = None shodan = Shodan(get_api_key()) try: search = shodan.search(f"http.favicon.hash:{fav_hash}") for result in search["matches"]: ip = result['ip_str'] except: print("Shodan Search Error") return ip
def apicheck(): api = Shodan('key') try: # Search Shodan results = api.search('thinkphp') # Show the results print('Results found: {}'.format(results['total'])) for result in results['matches']: url = "http://" + result['ip_str'] checkall(url) except: pass
def query_shodan(crtsh_results, args): """ check shodan for infra using certificate serial number Params: crtsh_results - list of ssl cert serials to query shodan shodan_key - a string representing a Shodan API token """ # for each certifcate returned from crt.sh, query Shodan using the serial # number and return IP addresses for hosts that match shodan_key = args.token api = Shodan(shodan_key) shodan_results = [] print("[+] Querying Shodan for certificate serial numbers") for cert in crtsh_results: shodan_result = {} serial_num = cert['serial_number'] common_name = cert['common_name'] query = f'ssl.cert.serial:{serial_num}' shodan_result['cert_serial'] = serial_num shodan_result['cert_common_name'] = common_name shodan_result['ips'] = [] shodan_result['hostnames'] = [] print(f'[+] Checking serial {serial_num}') try: result = api.search(query) except Exception as e: print(f'Error: {e}') sys.exit(1) else: time.sleep(1) if result['total'] != 0: print( f'[!] Found infrastructure for serial: {serial_num} and common name: {common_name}' ) for service in result['matches']: print(service['ip_str']) shodan_result['ips'].append(service['ip_str']) for hostname in service['hostnames']: print(hostname) shodan_result['hostnames'].append(hostname) else: if global_verbose == True: print(f'[+] No results found for serial: {serial_num}') continue shodan_results.append(shodan_result) return shodan_results
def sd(self): #shodan conf = configparser.ConfigParser() conf.read("config.ini") API_KEY = conf.get("shodan", "key") api = Shodan(API_KEY) sdsearch = self.lineEdit_3.text() #搜索 pages = self.lineEdit_4.text() #页数 for mun in range(1, int(pages) + int(1)): results = api.search(sdsearch, page=mun) for result in results['matches']: ip = result['ip_str'] port = result['port'] self.textEdit_3.append(str(ip) + ':' + str(port))
def main(): if parser.query and parser.api: api = Shodan(parser.api) try: b = api.search(parser.query) print('Total targets: {}'.format(b['total'])) for i in b['matches']: print('Target found: {}'.format(i['ip_str'])) except: print('An error has occurred') else: print('Both params (query and api) are required')
def extend_cert_list(): with open('config.json', 'r') as config: data = json.load(config) shodan_key = data['shodan_key'] if not shodan_key: return shodan_api = Shodan(shodan_key) http_banners = [] mmh3_hashes = set() with open('cert_list.txt', 'r') as cert_list: for _, target in enumerate(cert_list): try: target = target.strip() print(target) s = socket.socket() tport = 80 s.connect((target, tport)) head_request = str.encode('HEAD / HEAD/1.1\nHost: ' + target + '\n\n') s.send(head_request) http_banner = s.recv(1024).decode() http_banners.append(http_banner) s.close() except socket.error as socketerror: print("Error: ", socketerror) print('Continuing to next entry on cert list') s.close() continue for http_banner in http_banners: h = mmh3.hash(http_banner) mmh3_hashes.add(h) mmh3_hashes.remove(0) with open('extended_cert_list.txt', 'w+') as extended_cert_list: try: for h in mmh3_hashes: query = f'hash:{h}' results = shodan_api.search(query) print(f'Total for hash {h}: {results["total"]}') for result in results['matches']: hostnames = result['hostnames'] for hostname in hostnames: extended_cert_list.write(f'{hostname}\n') except: print('Potential API Error. Please upgrade your shodan account to support filter/paging')
def get_ip_data_from_shodan(api_key): api = Shodan(api_key) # https://developer.shodan.io/api # search = 'scada country:"DE"' # search = "s7-300 country:'DE'" ## Siemens SIMATIC S7-300 (maybe Honeypots) search = "Wasserwerk" # search = "flowChief" # search = "http.title:'Secure Access SSL VPN' country:'DE'" ## PulseSecure, maybe CVE-2021-2289 print("Query shodan ...") data = api.search(query=search) for d in tqdm.tqdm(data["matches"]): yield d
def main(): if parser.query: if parser.api: api = Shodan(parser.api) try: b = api.search(parser.query) print("Total de Objetivos: {}".format(b['total'])) for i in b['matches']: print("Target encontrado: {}".format(i['ip_str'])) except: print("Error en la consulta") else: print("Introduce tu api key") else: print("Introduce un caracter de busqueda")
def info_domains(self, domain): results = Shodan.search(self, 'hostname:%s' % domain) if 'matches' in results: all_domains = list(set([item for r in results['matches'] for item in r['hostnames']])) ips = list(set([r['ip_str'] for r in results['matches']])) ports = list(set([r['port'] for r in results['matches']])) transports = list(set([r['transport'] for r in results['matches']])) isp = list(set([r['isp'] for r in results['matches'] if 'isp' in r])) asn = list(set([r['asn'] for r in results['matches'] if 'asn' in r])) orgs = list(set([r['org'] for r in results['matches'] if 'org' in r])) return {'all_domains': all_domains, 'ips': ips, 'ports': ports, 'transports': transports, 'isp': isp, 'asn': asn, 'orgs': orgs }
def sudanFunction(ip): ip = ip.strip() lines = [] api = Shodan(shodanAPIKey.getAPIKey()) if isAnIP(ip) != 1: return "545" else: # Perform the search query = ' '.join(ip) result = api.search(query) print(type(result)) for service in result['matches']: lines.append(service['ip_str']) return lines
def api_query(self): try: api = Shodan(self.api_key) result = api.search(query=self.query, offset=self.offset, limit=self.limit) except APIError as e: outputscreen.error(e) sys.exit() if 'matches' in result: for match in result.get('matches'): conf.target.put( match.get('ip_str') + ':' + str(match.get('port'))) else: pass
def prepare_lists(): from shodan import Shodan import configparser config = configparser.ConfigParser() config.read(RootDir + "/config.txt") shodan_key = config['credentials']['SHODAN_API_KEY'] pages = config['configuration']['PAGES'] dork = config['configuration']['DORK'] api = Shodan(shodan_key) IPs = [] for i in pages: results = ([l['ip_str'] for l in api.search(dork)['matches']]) IPs += results with open(RootDir + "/sources.txt", mode="w") as sourcelist: for IP in IPs: sourcelist.write("ftp://{}\n".format(IP))
def search(self, query): try: success("Shodan'daki {}. sayfadan bot aranıyor!".format( self.last_page)) api = Shodan(self.api_key) tmp = api.search(query, page=self.last_page) self.last_page = self.last_page + 1 success("Liste indirildi") real_ips = [] for zombie in tmp["matches"]: ip = IPAddress(zombie["ip_str"]) if (str(ip.version) == "4"): real_ips.append(zombie) self.last_search = { "matches": self.last_search["matches"] + real_ips, "total": self.last_search["total"] + len(real_ips) } return self.last_search except APIError as e: error(str(e)) return False
if not args.silent: sys.stdout.write('%s[-] invalid favicon%s\n' % (fg('red'), attr(0))) exit() favhash = faviconHash(data, web_src) if not args.silent: sys.stdout.write('%s[+] hash calculated: %s%s\n' % (fg('green'), str(favhash), attr(0))) if shokey: shodan = Shodan(shokey) search = 'http.favicon.hash:' + str(favhash) if not args.silent: sys.stdout.write('[+] searching: %s\n' % search) try: t_results = shodan.search(search) # print(t_results) except Exception as e: sys.stdout.write("%s[-] error occurred: %s%s\n" % (fg('red'), e, attr(0))) exit() if not args.silent: sys.stdout.write('%s[+] %d results found%s\n' % (fg('green'), len(t_results['matches']), attr(0))) for result in t_results['matches']: tmp = [] for v in t_values: if v in result: tmp.append(str(result[v])) else: tmp.append('')
def shodan_search_worker(fk, query, search_type, category, country=None, coordinates=None, all_results=False): results = True page = 1 SHODAN_API_KEY = keys['keys']['shodan'] pages = 0 screenshot = "" print(query) while results: if pages == page: results = False break # Shodan sometimes fails with no reason, sleeping when it happens and it prevents rate limitation search = Search.objects.get(id=fk) api = Shodan(SHODAN_API_KEY) fail = 0 try: time.sleep(5) if coordinates: results = api.search("geo:" + coordinates + ",20 " + query, page) if country: results = api.search("country:" + country + " " + query, page) except: fail = 1 print('fail1, sleeping...') if fail == 1: try: time.sleep(10) if coordinates: results = api.search("geo:" + coordinates + ",20 " + query, page) if country: results = api.search("country:" + country + " " + query, page) except Exception as e: results = False print(e) try: total = results['total'] if total == 0: print("no results") break except Exception as e: print(e) break pages = math.ceil(total / 100) + 1 print(pages) for counter, result in enumerate(results['matches']): lat = str(result['location']['latitude']) lon = str(result['location']['longitude']) city = "" indicator = [] # print(counter) # time.sleep(20) try: product = result['product'] except: product = "" if 'vulns' in result: vulns = [*result['vulns']] else: vulns = "" if result['location']['city'] != None: city = result['location']['city'] hostnames = "" try: if 'hostnames' in result: hostnames = result['hostnames'][0] except: pass try: if 'SAILOR' in result['http']['title']: html = result['http']['html'] soup = BeautifulSoup(html) for gps in soup.find_all("span", {"id": "gnss_position"}): coordinates = gps.contents[0] space = coordinates.split(' ') if "W" in space: lon = "-" + space[2][:-1] else: lon = space[2][:-1] lat = space[0][:-1] except Exception as e: pass if 'opts' in result: try: screenshot = result['opts']['screenshot']['data'] with open( "app_kamerka/static/images/screens/" + result['ip_str'] + ".jpg", "wb") as fh: fh.write(base64.b64decode(screenshot)) fh.close() for i in result['opts']['screenshot']['labels']: indicator.append(i) except Exception as e: pass if query == "Niagara Web Server": try: soup = BeautifulSoup(result['http']['html'], features="html.parser") nws = soup.find("div", {"class": "top"}) indicator.append(nws.contents[0]) except: pass # get indicator from niagara fox if result['port'] == 1911 or result['port'] == 4911: try: fox_data_splitted = result['data'].split("\n") for i in fox_data_splitted: if "station.name" in i: splitted = i.split(":") indicator.append(splitted[1]) except: pass # get indicator from tank if result['port'] == 10001: try: tank_info = result['data'].split("\r\n\r\n") indicator.append(tank_info[1]) except: pass if result['port'] == 2000: try: ta_data = result['data'].split("\\n") indicator.append(ta_data[1][:-3]) except Exception as e: pass if result['port'] == 502: try: sch_el = result['data'].split('\n') if sch_el[4].startswith("-- Project"): indicator.append(sch_el[4].split(": ")[1]) except: pass if "GPGGA" in result['data']: try: splitted_data = result['data'].split('\n') for i in splitted_data: if "GPGGA" in i: msg = pynmea2.parse(i) lat = msg.latitude lon = msg.longitude break except Exception as e: print(e) if result['port'] == 102: try: s7_data = result['data'].split("\n") for i in s7_data: if i.startswith("Plant"): indicator.append(i.split(":")[1]) if i.startswith("PLC"): indicator.append(i.split(":")[1]) if i.startswith("Module name"): indicator.append(i.split(":")[1]) except: pass # get indicator from bacnet if result['port'] == 47808: try: bacnet_data_splitted = result['data'].split("\n") for i in bacnet_data_splitted: if "Description" in i: splitted1 = i.split(":") indicator.append(splitted1[1]) if "Object Name" in i: splitted2 = i.split(":") indicator.append(splitted2[1]) if "Location" in i: splitted3 = i.split(":") indicator.append(splitted3[1]) except: pass device = Device(search=search, ip=result['ip_str'], product=product, org=result['org'], data=result['data'], port=str(result['port']), type=search_type, city=city, lat=lat, lon=lon, country_code=result['location']['country_code'], query=search_type, category=category, vulns=vulns, indicator=indicator, hostnames=hostnames, screenshot=screenshot) device.save() page = page + 1 if not all_results: results = False
class FavUp(object): def __init__(self, *args, **kwargs): """ Parse the arguments """ self.show = None self._iterator = None self.shodan = None self.key = None self.keyFile = None self.shodanCLI = None self.faviconFile = [] self.faviconURL = [] self.web = [] self.fileList = [] self.urlList = [] self.webList = [] self.faviconsList = [] self.current_work_dir = os.getcwd() self.ua_json_location = "{}/data/ua.json".format(self.current_work_dir) self.ua = UserAgent(path=self.ua_json_location) self.output = "" self._output = None if kwargs.get('show'): self.show = True ap = argparse.ArgumentParser(prog="favup", usage="python3 %(prog)s [options]") ap.add_argument( '-kf', '--key-file', help="Specify the file which contains the API key.") ap.add_argument('-k', '--key', help="Specify the API key.") ap.add_argument('-sc', '--shodan-cli', help="Load the API key from Shodan CLI.", action="store_true") ap.add_argument('-ff', '--favicon-file', help="Load the favicon icon from a local file.") ap.add_argument('-fu', '--favicon-url', help="Load the favicon icon from an URL.") ap.add_argument( '-w', '--web', help="Extracts the favicon location from the page.") ap.add_argument( '-fl', '--favicon-list', help= "Iterate over a file that contains the full path of all the icons which you want to lookup." ) ap.add_argument( '-ul', '--url-list', help= "Iterate over a file that contains the full URL of all the icons which you want to lookup." ) ap.add_argument( '-wl', '--web-list', help= "Iterate over a file that contains all the domains which you want to lookup." ) ap.add_argument( '-o', '--output', help= "Specify output file, currently supported formats are CSV and JSON." ) args = self._argsCheck(ap.parse_args()) self.key = args.key self.keyFile = args.key_file self.shodanCLI = args.shodan_cli self.faviconFile = [args.favicon_file] if args.favicon_file else [] self.faviconURL = [args.favicon_url] if args.favicon_url else [] self.web = [args.web] if args.web else [] self.fileList = self._serializeListFile( args.favicon_list) if args.favicon_list else [] self.urlList = self._serializeListFile( args.url_list) if args.url_list else [] self.webList = self._serializeListFile( args.web_list) if args.web_list else [] self.output = args.output self._iterator = tqdm(total=len(self.fileList) + len(self.urlList) + len(self.webList)) if self.output: self._output = { 'type': self.output.split('.')[1], 'file': open(self.output, 'w') } self.run() if self.output: self._output['file'].close() def _argsCheck(self, args): if not (args.key_file or args.key or args.shodan_cli): print( '[x] Please specify the key with --key, --key-file or --shodan-cli.' ) exit(1) if not (args.favicon_file or args.favicon_url or args.web or args.favicon_list or args.url_list or args.web_list): print( '[x] Please specify the source of the favicon with --favicon-file, --favicon-url, --web' + ', --favicon-list, --url-list or --web-list.') exit(1) return args def _serializeListFile(self, inputFile): """ Remove whitespace chars and lines """ _output = [] with open(inputFile, 'r') as inFile: for _l in inFile: if _l.strip(): _output.append(_l.strip()) return _output def run(self): if self.keyFile: self.shodan = Shodan(open(self.keyFile, "r").readline().strip()) elif self.key: self.shodan = Shodan(self.key) elif self.shodanCLI: self.shodan = Shodan(get_api_key()) else: print('[x] Wrong input API key type.') exit(1) if self.faviconFile or self.fileList: self.fileList.extend(self.faviconFile) for fav in self.fileList: self._iterator.set_description( f"[+] iterating over favicon files | processing {fav}") self._iterator.update(1) data = open(fav, 'rb').read() _fH = self.faviconHash(data) self.faviconsList.append({ 'favhash': _fH, 'file': fav, '_origin': fav }) if self.faviconURL or self.urlList: self.urlList.extend(self.faviconURL) for fav in self.urlList: self._iterator.set_description( f"[+] iterating over favicon URLs | processing {fav}") self._iterator.update(1) headers = { 'User-Agent': self.get_user_agent(), } data = requests.get(fav, stream=True, headers=headers) _dcL = self.deepConnectionLens(data) data = data.content _fH = self.faviconHash(data) self.faviconsList.append({ 'favhash': _fH, 'url': self.faviconURL, 'domain': fav, 'maskIP': _dcL['mIP'], 'maskISP': _dcL['mISP'], '_origin': fav }) if self.web or self.webList: self.webList.extend(self.web) for w in self.webList: self._iterator.set_description( f"[+] iterating over domains | processing {w}") self._iterator.update(1) try: headers = { 'User-Agent': self.get_user_agent(), } data = requests.get(f"https://{w}", stream=True, headers=headers) _dcL = self.deepConnectionLens(data) data = self.searchFaviconHTML(f"https://{w}") if not isinstance(data, str): _fH = self.faviconHash(data.content, web_source=True) else: _fH = "not-found" except requests.exceptions.ConnectionError: self._iterator.write(f"[x] Connection refused by {w}.") if len(self.webList) == 1: exit(1) self.faviconsList.append({ 'favhash': _fH, 'domain': f"https://{w}", 'maskIP': _dcL['mIP'], 'maskISP': _dcL['mISP'], '_origin': w }) _alreadyScanned = {} _aF = set([f for i in self.faviconsList for f in i]) _aF.remove('_origin') _aF.add('found_ips') _cObj = {} for f in _aF: _cObj.update({f: ''}) if self.output: if self._output['type'].lower() == 'csv': self._output['file'].write(','.join(f for f in _aF) + '\n') self._iterator.reset(total=len(self.faviconsList)) for _fObject in self.faviconsList: self._iterator.set_description( f"[+] lookup for {_fObject['favhash']}") self._iterator.update(1) try: _ = _alreadyScanned[_fObject['favhash']] except KeyError: found_ips = "not-found" if _fObject['favhash'] != "not-found": found_ips = self.shodanSearch(_fObject['favhash']) _alreadyScanned.update({_fObject['favhash']: found_ips}) found_ips = _alreadyScanned[_fObject['favhash']] _fObject.update({'found_ips': found_ips}) if self.show: self._iterator.write("-" * 25) self._iterator.write(f"[{_fObject['_origin']}]") del _fObject['_origin'] for _atr in _fObject: self._iterator.write(f"--> {_atr:<10} :: {_fObject[_atr]}") if self.output: _tcObj = _cObj _tcObj.update(_fObject) _t = self._output['type'] if _t.lower() == 'csv': self._output['file'].write(','.join( str(_tcObj[k]) for k in _tcObj) + '\n') elif _t.lower() == 'json': self._output['file'].write(json.dumps(_tcObj) + '\n') else: self._iterator.write( "[x] Output format not supported, closing.") exit(1) def faviconHash(self, data, web_source=None): if web_source: b64data = base64.encodebytes(data).decode() else: b64data = base64.encodebytes(data) return mmh3.hash(b64data) def searchFaviconHTML(self, link): data = requests.get(link, stream=True) soup = BeautifulSoup(data.content, 'html.parser') searchIcon = soup.find('link', rel='icon') if searchIcon: iconLink = searchIcon.get("href") if not iconLink.startswith("http"): iconLink = link + "/" + iconLink return requests.get(iconLink) return "not-found" def shodanSearch(self, favhash): time.sleep(1) results = self.shodan.search(f"http.favicon.hash:{favhash}") return '|'.join([s['ip_str'] for s in results["matches"]]) def deepConnectionLens(self, response): mIP = 'not-found' mISP = 'not-found' if response.status_code == 200: try: mIP = list(response.raw._connection.sock.getpeername())[0] mISP = IPWhois(mIP).lookup_whois()['nets'][0]['name'] except AttributeError: try: mIP = list( response.raw._connection.sock.socket.getpeername())[0] mISP = IPWhois(mIP).lookup_whois()['nets'][0]['name'] except AttributeError: pass if mIP == 'not-found': self._iterator.write( f"[x] There's problem when getting icon for {response.url.split('/')[2]} with status code: {response.status_code}" ) return {'mIP': mIP, 'mISP': mISP} def get_user_agent(self): try: return self.ua.random except FakeUserAgentError: return "Mozilla/5.0 (X11; Linux x86_64; rv:69.0) Gecko/20100101 Firefox/69.0"
# coding=utf-8 from shodan import Shodan import requests api = Shodan('PSKINdQe1GyxGgecYz2191H2JoS9qvgD') for i in range(1, 20): print('开始第:{}页'.format(i)) results = api.search('port:"888"', i) if len(results['matches']) > 0: for result in results['matches']: try: url = "http://" + result['ip_str'] + ":888/pma" res = requests.get(url) if res.status_code == 200: print('接口状态:{} 地址:{}'.format(200, url)) except: pass else: print '结束' break
def query_shodan(list_id_domain, con, lazy_rating=1): ret_list = [] with open('../config/shodan.key', 'r') as f: key = f.read().replace('\n', '') api = Shodan(key) for domain_id, domain in list_id_domain: print("domain: " + domain) ipaddr = socket.gethostbyname(domain) res = {} for i in range(0, 5): try: honeypot_score = query_honeypot_score(ipaddr, key) break except: time.sleep(1) if str(honeypot_score)[0] != "{": res["honeypot_score"] = honeypot_score query_base = "https://www.shodan.io/search?query=" query_malware = 'category:malware ip:' + ipaddr for i in range(0, 5): try: result_malware = api.search(query_malware) break except: time.sleep(1) try: if len(result_malware["matches"]) == 0: res["shodan_malware"] = 0 res["shodan_malware_query"] = "" else: res["shodan_malware"] = 1 res["shodan_malware_query"] = base64.b64encode( (query_base + query_malware).encode('ascii')) except: pass query_default_creds = '"default password" ip:' + ipaddr for i in range(0, 5): try: result_creds = api.search(query_default_creds) break except: time.sleep(1) try: if len(result_creds["matches"]) == 0: res["shodan_creds"] = 0 res["shodan_creds_query"] = "" else: res["shodan_creds"] = 1 res["shodan_creds_query"] = base64.b64encode( (query_base + query_default_creds).encode('ascii')) except: pass res = {k: v for k, v in res.items() if v is not None} update_query = 'UPDATE urls SET {} WHERE idUrl=%s'.format(', '.join( '{}=%s'.format(k) for k in res)) cur = con.cursor() changed = cur.execute(update_query, tuple(list(res.values())) + (domain_id, )) con.commit() if lazy_rating == 0 or changed != 0: if update_score(con, domain_id) != 0: ret_list.append(domain_id) return ret_list
def shodan_search_worker(fk, query, search_type, category, country=None, coordinates=None, all_results=False): results = True page = 1 SHODAN_API_KEY = keys['keys']['shodan'] pages = 0 while results: if pages == page: results = False break search = Search.objects.get(id=fk) api = Shodan(SHODAN_API_KEY) fail = 0 try: time.sleep(5) if coordinates: results = api.search("geo:" + coordinates + ",20 " + query, page) if country: results = api.search("country:" + country + " " + query, page) except: fail = 1 print('fail1, sleeping...') if fail == 1: try: time.sleep(10) if coordinates: results = api.search("geo:" + coordinates + ",20 " + query, page) if country: results = api.search("country:" + country + " " + query, page) except Exception as e: results = False print(e) total = results['total'] if total == 0: print("no results") break pages = math.ceil(total / 100) + 1 print(pages) for counter, result in enumerate(results['matches']): city = "" indicator = [] print(counter) # time.sleep(20) try: product = result['product'] except: product = "" if 'vulns' in result: vulns = [*result['vulns']] else: vulns = "" if result['location']['city'] != None: city = result['location']['city'] hostnames = "" try: if 'hostnames' in result: hostnames = result['hostnames'][0] except: pass if result['port'] == 1911 or result['port'] == 4911: try: fox_data_splitted = result['data'].split("\n") for i in fox_data_splitted: if "station.name" in i: splitted = i.split(":") indicator.append(splitted[1]) except: pass elif result['port'] == 10001: try: tank_info = result['data'].split("\r\n\r\n") indicator.append(tank_info[1]) except: pass elif result['port'] == 47808: try: bacnet_data_splitted = result['data'].split("\n") for i in bacnet_data_splitted: if "Description" in i: splitted1 = i.split(":") indicator.append(splitted1[1]) if "Object Name" in i: splitted2 = i.split(":") indicator.append(splitted2[1]) if "Location" in i: splitted3 = i.split(":") indicator.append(splitted3[1]) except: pass else: indicator = "" device = Device(search=search, ip=result['ip_str'], product=product, org=result['org'], data=result['data'], port=str(result['port']), type=search_type, city=city, lat=str(result['location']['latitude']), lon=str(result['location']['longitude']), country_code=result['location']['country_code'], query=search_type, category=category, vulns=vulns, indicator=indicator, hostnames=hostnames) device.save() page = page + 1 if not all_results: results = False
def search(self, query, page=1): results = Shodan.search(self, query, page=page) return results
from shodan import Shodan import sys domain = sys.argv[1] hosts=[] api = Shodan('YOUR_API_KEY') results=api.search('hostname:.{}'.format(domain)) try: for res in results['matches']: hosts.append(''.join(res['hostnames'])) except KeyError: pass with open('shodan_subdomains.txt', 'w') as f: for item in hosts: f.write("%s\n" % item) #return hosts
from shodan import Shodan import requests import subprocess IP = "" api = Shodan('') def url_ok(url): r = requests.head("http://" + url) return r.status_code == 200 def check_page(url): r = requests.get("http://" + url + "/admin/") return "Pi-hole" in r.text def pruneIPS(vulnerableIPs): for i in vulnerableIPs: if not url_ok(i): if not check_page(i): vulnerableIPs.remove(i) return vulnerableIPs result = api.search("pi-hole") VulnerableIP = [] for service in result['matches']: if service['ip_str'] == IP: ulnerableIP.append(service['ip_str']) print("Yes")
def Search(self): try: Data_to_Cache = [] Directory = General.Make_Directory(self.Plugin_Name.lower()) logger = logging.getLogger() logger.setLevel(logging.INFO) Log_File = General.Logging(Directory, self.Plugin_Name.lower()) handler = logging.FileHandler(os.path.join(Directory, Log_File), "w") handler.setLevel(logging.DEBUG) formatter = logging.Formatter("%(levelname)s - %(message)s") handler.setFormatter(formatter) logger.addHandler(handler) Shodan_API_Key = self.Load_Configuration() API_Session = Shodan(Shodan_API_Key) Cached_Data_Object = General.Cache(Directory, self.Plugin_Name) Cached_Data = Cached_Data_Object.Get_Cache() for Query in self.Query_List: try: if self.Type == "Search": Local_Plugin_Name = self.Plugin_Name + "-Search" try: API_Response = API_Session.search(Query) except Exception as e: logging.error( f"{Common.Date()} - {self.Logging_Plugin_Name} - {str(e)}." ) break JSON_Output_Response = Common.JSON_Handler( API_Response).Dump_JSON() Main_File = General.Main_File_Create( Directory, Local_Plugin_Name, JSON_Output_Response, Query, self.The_File_Extensions["Main"]) Output_Connections = General.Connections( Query, Local_Plugin_Name, self.Domain, self.Result_Type, self.Task_ID, self.Plugin_Name.lower()) Current_Step = 0 for Shodan_Item in API_Response["matches"]: Shodan_Item_Module = Shodan_Item['_shodan'][ 'module'] Shodan_Item_Module = Shodan_Item_Module.replace( '-simple-new', '') if Shodan_Item_Module.startswith("http"): Shodan_Item_Host = "" Shodan_Item_Port = 0 if 'http' in Shodan_Item: Shodan_Item_Host = Shodan_Item['http'][ 'host'] Shodan_Item_Response = Shodan_Item['http'][ 'html'] elif 'ip_str' in Shodan_Item and 'domains' in Shodan_Item and len( Shodan_Item['domains']) > 0: Shodan_Item_Host = Shodan_Item['domains'][ 0] Shodan_Item_Response = Shodan_Item['data'] elif 'ip_str' in Shodan_Item and 'domains' not in Shodan_Item: Shodan_Item_Host = Shodan_Item['ip_str'] Shodan_Item_Response = Shodan_Item['data'] if Shodan_Item_Host: if 'port' in Shodan_Item_Host: if int(Shodan_Item['port']) not in [ 80, 443 ]: Shodan_Item_Port = Shodan_Item[ 'port'] if Shodan_Item_Port != 0: Shodan_Item_URL = f"{Shodan_Item_Module}://{Shodan_Item_Host}:{str(Shodan_Item_Port)}" else: Shodan_Item_URL = f"{Shodan_Item_Module}://{Shodan_Item_Host}" Title = f"Shodan | {str(Shodan_Item_Host)}" if Shodan_Item_URL not in Cached_Data and Shodan_Item_URL not in Data_to_Cache and Current_Step < int( self.Limit): Output_file = General.Create_Query_Results_Output_File( Directory, Query, Local_Plugin_Name, Shodan_Item_Response, Shodan_Item_Host, self.The_File_Extensions["Query"]) if Output_file: Output_Connections.Output( [Main_File, Output_file], Shodan_Item_URL, Title, self.Plugin_Name.lower()) Data_to_Cache.append( Shodan_Item_URL) else: logging.warning( f"{Common.Date()} - {self.Logging_Plugin_Name} - Failed to create output file. File may already exist." ) Current_Step += 1 elif self.Type == "Host": Local_Plugin_Name = self.Plugin_Name + "-Host" try: API_Response = API_Session.host(Query) except Exception as e: logging.error( f"{Common.Date()} - {self.Logging_Plugin_Name} - {str(e)}." ) break JSON_Output_Response = Common.JSON_Handler( API_Response).Dump_JSON() Main_File = General.Main_File_Create( Directory, Local_Plugin_Name, JSON_Output_Response, Query, self.The_File_Extensions["Main"]) Output_Connections = General.Connections( Query, Local_Plugin_Name, self.Domain, self.Result_Type, self.Task_ID, self.Plugin_Name.lower()) Shodan_URL = f"https://www.{self.Domain}/host/{Query}" Title = f"Shodan | {Query}" if Shodan_URL not in Cached_Data and Shodan_URL not in Data_to_Cache: Shodan_Responses = Common.Request_Handler( Shodan_URL, Application_JSON_CT=True, Accept_XML=True, Accept_Language_EN_US=True, Filter=True, Host=f"https://www.{self.Domain}") Shodan_Response = Shodan_Responses["Filtered"] Output_file = General.Create_Query_Results_Output_File( Directory, Query, self.Plugin_Name, Shodan_Response, Query, self.The_File_Extensions["Query"]) if Output_file: Output_Connections.Output( [Main_File, Output_file], Shodan_URL, Title, self.Plugin_Name.lower()) Data_to_Cache.append(Shodan_URL) else: logging.warning( f"{Common.Date()} - {self.Logging_Plugin_Name} - Failed to create output file. File may already exist." ) else: logging.warning( f"{Common.Date()} - {self.Logging_Plugin_Name} - No results found." ) except: logging.warning( f"{Common.Date()} - {self.Logging_Plugin_Name} - Failed to complete task." ) Cached_Data_Object.Write_Cache(Data_to_Cache) except Exception as e: logging.warning( f"{Common.Date()} - {self.Logging_Plugin_Name} - {str(e)}")
print("\n{}".format(host.get('ip_str'))) print("\nHostnames: {}".format(', '.join(host.get('hostnames')))) print("City: {}".format(host.get('city'))) print("Country: {}".format(host.get('country_name'))) print("Organization: {}".format(host.get('org'))) print("Number of open ports: {}".format(len(host.get('ports')))) print("Ports:") portsvisited=[] for i in host['data']: if 'product' in i: if i.get('port') not in portsvisited: print(" {} {}".format(i['port'], i['product'])) portsvisited.append(i.get('port')) else: continue if 'port' in i: if i.get('port') not in portsvisited: print(" {} ".format(i['port'])) portsvisited.append(i.get('port')) else: continue else: continue if selection == 3: print("\nInput your query to search: \n") strinng = input() results = api.search(strinng) print('\nResults found: {}\n'.format(results['total'])) for result in results['matches']: print('{} {} {} {}'.format(result.get('ip_str',"Not Found"), result.get('port',"Not Found"), result.get('org',"Not Found"), ', '.join(result.get('hostnames',"Not Found"))))
ip_to_vulnerabilities = defaultdict(set) if debug_flag == "debug": # Query an IP address using the Shodan REST API r = requests.get("https://api.shodan.io/shodan/host/{}?key={}".format( ip, SHODAN_API_KEY)) # The response from the REST API is returned as JSON array data = r.json() for d in data["data"]: if "vulns" in d and len(d["vulns"]) > 0: for vulnerability_id in d["vulns"]: ip_to_vulnerabilities[ip].add(vulnerability_id) api = Shodan(SHODAN_API_KEY) results = api.search('apache') print('Results found: {}'.format(results['total'])) print('Results found: {}'.format(len(results['matches']))) mydoc = minidom.parse('official-cpe-dictionary_v2.3.xml') items = mydoc.getElementsByTagName('cpe-item') #total amount of items print(len(items)) # dom = parseString('official-cpe-dictionary_v2.3.xml') for s in mydoc.getElementsByTagName('cpe-item'): if s.getAttribute('name') == 'cpe:/a:10-strike:network_monitor:1.1': print(s.childNodes[0].data) #cpeData = mydoc.getElementsByName("cpe:/a:10-strike:network_monitor:1.1") #"cpe:/a:10-strike:network_monitor:1.0"
class CamScan: def __init__(self, dirname='Images', search=None, path=None, timeout=4, pages=0, verbose=False): self.search = search self.path = path self.dirname = dirname self.timeout = timeout self.pages = pages self.verbose = verbose self.api = None try: keyfile = open('shodan_api_key', 'r') key = keyfile.readline() keyfile.close() self.api = Shodan(key) except FileNotFoundError: print('Key file not found') DIR_NUMBER = 2 while os.path.exists(self.dirname): self.dirname = self.dirname.strip('0987654321') + str(DIR_NUMBER) DIR_NUMBER += 1 def initShodan(self, key): with open('shodan_api_key', 'w') as file: file.write(key) self.api = Shodan(key) def chooseFromCSV(self, file): if os.path.exists(file): f = open(file, newline='') data = csv.DictReader(f) searches = {} for x in data: searches[x['searchQuery']] = x['imagePath'] f.close() print('CSV file input. Select search from below:\n') y = 0 for search in searches: print(str(y) + ') ' + search) y += 1 choice = int(input('\nChoose search: ')) self.search = list(searches.keys())[choice] self.path = list(searches.values())[choice] else: raise FileNotFoundError def pagesCount(self): hosts = self.api.count(self.search)['total'] return int(hosts / 100) + 1 def setPages(self, pages): if type(pages) in [int, range, type(None)]: self.pages = pages else: raise Exception( 'Wrong type. pages value can be set to int, range, or None') def requestAndDownload(self, url): try: r = requests.get(url, timeout=self.timeout) if r.status_code == 200: if self.verbose: print(url, ' - Success') filename = urlparse(url).netloc.replace(':', '-') + '.png' with open(filename, 'wb') as img: img.write(r.content) else: if self.verbose: print(url, r.status_code, 'Error') except requests.exceptions.ReadTimeout: if self.verbose: print(url, '- Timed out') except Exception as e: #print(e) if self.verbose: print(url, '- Connection Error') def runOnPage(self, pagenumber): results = None tries = 0 while results is None and tries < 10: try: results = self.api.search(self.search, page=pagenumber) except Exception as e: tries += 1 print('Shodan error') if tries == 10: print('Giving up') raise Exception(e.args[0]) threads = [] for result in results['matches']: url = 'http://' + str(result['ip_str']) + ':' + str( result['port']) + self.path x = threading.Thread(target=self.requestAndDownload, args=(url, )) threads.append(x) x.start() for thread in threads: thread.join() def run(self): if self.api == None: raise Exception('No Shodan key') os.mkdir(self.dirname) os.chdir(self.dirname) print('Saving images to', os.getcwd(), '\n') if self.pages is None: print('Running every page') for page in range(self.pagesCount()): print('Starting page:', page) self.runOnPage(page) elif type(self.pages) is int: print('Running page', self.pages) self.runOnPage(self.pages) elif type(self.pages) is range: for page in self.pages: print('Starting page:', page) self.runOnPage(page) def generatePage(self): html = ''' <!DOCTYPE html> <html> <head> <title>Saved Images</title> <script> let emptyImages = []; function removeEmpty() { let images = document.getElementsByTagName('img'); for (let i = 0; i < images.length; i++) { if (images[i].naturalHeight == 0) { emptyImages.push(images[i]); } } for (let i = 0; i < emptyImages.length; i++) { emptyImages[i].remove(); } } </script> </head> <body style="background-color:black"> <button onclick="removeEmpty()">Remove Empty Images</button> <p style="color:white;">Click on an image to open stream</p> ''' with open('images.html', 'w') as page: page.write(html) for name_of_file in os.listdir(): if '.png' in name_of_file: link = 'http://' + name_of_file.replace('-', ':').strip('.png') page.write( '\n\t<a href="{}" target="_blank">'.format(link)) page.write( '\n\t\t<img src="{}" height="480" width="720">'.format( name_of_file)) page.write('\n\t</a>') page.write('\n</body>\n</html>') def showImages(self): webbrowser.open('images.html') def info(self): print('search:', self.search) print('path:', self.path) print('dirname', self.dirname) print('timeout:', self.timeout) print('pages:', self.pages)
#!/usr/bin/env python #_*_ coding: utf8 _*_ import sys from shodan import Shodan reload(sys) sys.setdefaultencoding('utf8') key = "shXLINeBiCP4FLh4IhvFiT2Ypbnh5PjK" motor = Shodan(key) try: query = motor.search("struts") print("Total de resultados: {}".format(query['total'])) for host in query['matches']: print("IP: {}".format(host['ip_str'])) print("Puerto: {}".format(host['port'])) print("ORG: {}".format(host['org'])) try: print("ASN: {}".format(host['asn'])) except: pass for l in host['location']: print(l + " : " + str(host['location'][l])) print(host['data']) except: print("Ocurrio un error")
def run(self, args, lookup, report_directory, api_key_directory): """main function""" self.shodan_query_result = [] self.shodan_api_key = None self.api_key_value = None #first if https://shodan.readthedocs.io/en/latest/tutorial.html#connect-to-the-api #else https://shodan.readthedocs.io/en/latest/tutorial.html#looking-up-a-host #check for a stored api key, if missing ask for it and if it should be saved if not os.path.exists(api_key_directory + 'shodan.key'): print('[!] You are missing {}shodan.key'.format(api_key_directory)) self.api_key_value = getpass.getpass('[i] Please provide an API Key: ') response = raw_input('[i] Would you like to save this key to a plaintext file? (y/n): ') if 'y' in response.lower(): with open(api_key_directory + 'shodan.key', 'w') as api_key_file: api_key_file.writelines(self.api_key_value) else: pass with open(api_key_directory + 'shodan.key') as f: self.api_key_value = f.readlines()[0] #invoke api with api key provided shodanApi = Shodan(self.api_key_value) #roll through the lookup list from -i or -d for i, l in enumerate(lookup): #open output file shodan_text_output=open(report_directory+l+'/'+l+'_shodan.txt','w') #user notification that something is happening print('[+] Querying Shodan via API search for {}'.format(l)) try: #set results to api search of current lookup value #https://shodan.readthedocs.io/en/latest/examples/basic-search.html result = shodanApi.search(query="hostname:"+l) print('[+] Shodan found: {} hosts'.format(str(result['total']))) #for each result for service in result['matches']: if args.verbose is True: print(str(service['ip_str'].encode('utf-8')+\ ' ISP: '+service['isp'].encode('utf-8')+\ ' Last seen: '+service['timestamp'].encode('utf-8'))) if args.verbose is True: #print and encode if there are non-us chars print(service['data'].encode('utf-8')) #append to shodanResult list self.shodan_query_result.append(str(\ service['ip_str'].encode('utf-8')+\ '\nISP:'+service['isp'].encode('utf-8')+\ '\nLast seen:'+service['timestamp'].encode('utf-8'))+\ '\n'+service['data'].encode('utf-8')) #catch exceptions except Exception as e: #print excepted error print('[-] Shodan Error: {} '.format(e)) print('[!] You may need to specify an API key with -s <api key>') return #write contents of shodanResult list. this needs formatted shodan_text_output.writelines('[+] Shodan found: {} hosts\n\n'.format(str(result['total']))) shodan_text_output.writelines(self.shodan_query_result) return self.shodan_query_result