Login Register




The stories and information posted here are artistic works of fiction and falsehood. Only a fool would take anything posted here as fact.


Python Shodan API Search filter_list
Author
Message
Python Shodan API Search #1
Love shodan. Think this is a great tool. Make sure you register and put in your API Key, or else this script wont work...

http://shodanhq.com

Code:
#!/usr/bin/python2 import os import sys import signal import time #Please set your api key here in between the qoute marks. userapi = "tDUKzBYL52cAxDt3ObWRLeazSokWRP" #yep right up there try: from json import dumps, loads except: from simplejson import dumps, loads try: # Python 2 from urllib2 import urlopen from urllib import urlencode except: # Python 3 from urllib.request import urlopen from urllib.parse import urlencode __all__ = ['WebAPI'] class WebAPIError(Exception): def __init__(self, value): self.value = value def __str__(self): return self.value class WebAPI: """Wrapper around the SHODAN webservices API""" class Exploits: def __init__(self, parent): self.parent = parent def search(self, query, sources=[], cve=None, osvdb=None, msb=None, bid=None): """Search the entire Shodan Exploits archive using the same query syntax as the website. Arguments: query -- exploit search query; same syntax as website Optional arguments: sources -- metasploit, cve, osvdb, exploitdb, or packetstorm cve -- CVE identifier (ex. 2010-0432) osvdb -- OSVDB identifier (ex. 11666) msb -- Microsoft Security Bulletin ID (ex. MS05-030) bid -- Bugtraq identifier (ex. 13951) """ if sources: query += ' source:' + ','.join(sources) if cve: query += ' cve:%s' % (str(cve).strip()) if osvdb: query += ' osvdb:%s' % (str(osvdb).strip()) if msb: query += ' msb:%s' % (str(msb).strip()) if bid: query += ' bid:%s' % (str(bid).strip()) return self.parent._request('search_exploits', {'q': query}) class ExploitDb: def __init__(self, parent): self.parent = parent def download(self, id): """Download the exploit code from the ExploitDB archive. Arguments: id -- ID of the ExploitDB entry Returns: A dictionary with the following fields: filename -- Name of the file content-type -- Mimetype data -- Contents of the file """ return self.parent._request('exploitdb/download', {'id': id}) def search(self, query, **kwargs): """Search the ExploitDB archive. Arguments: query -- Search terms Optional arguments: author -- Name of the exploit submitter platform -- Target platform (e.g. windows, linux, hardware etc.) port -- Service port number type -- Any, dos, local, papers, remote, shellcode and webapps Returns: A dictionary with 2 main items: matches (list) and total (int). Each item in 'matches' is a dictionary with the following elements: id author date description platform port type """ return self.parent._request('exploitdb/search', dict(q=query, **kwargs)) class Msf: def __init__(self, parent): self.parent = parent def download(self, id): """Download a metasploit module given the fullname (id) of it. Arguments: id -- fullname of the module (ex. auxiliary/admin/backupexec/dump) Returns: A dictionary with the following fields: filename -- Name of the file content-type -- Mimetype data -- File content """ return self.parent._request('msf/download', {'id': id}) def search(self, query, **kwargs): """Search for a Metasploit module. """ return self.parent._request('msf/search', dict(q=query, **kwargs)) def __init__(self, key): """Initializes the API object. Arguments: key -- your API key """ self.api_key = key self.base_url = 'http://www.shodanhq.com/api/' self.exploits = self.Exploits(self) self.exploitdb = self.ExploitDb(self) self.msf = self.Msf(self) def _request(self, function, params): """General-purpose function to create web requests to SHODAN. Arguments: function -- name of the function you want to execute params -- dictionary of parameters for the function Returns A JSON string containing the function's results. """ # Add the API key parameter automatically params['key'] = self.api_key # Send the request data = urlopen(self.base_url + function + '?' + urlencode(params)).read().decode('utf-8') # Parse the text into JSON data = loads(data) # Raise an exception if an error occurred if data.get('error', None): raise WebAPIError(data['error']) # Return the data return data def count(self, query): """Returns the total number of search results for the query. """ return self._request('count', {'q': query}) def locations(self, query): """Return a break-down of all the countries and cities that the results for the given search are located in. """ return self._request('locations', {'q': query}) def fingerprint(self, banner): """Determine the software based on the banner. Arguments: banner - HTTP banner Returns: A list of software that matched the given banner. """ return self._request('fingerprint', {'banner': banner}) def host(self, ip): """Get all available information on an IP. Arguments: ip -- IP of the computer Returns: All available information SHODAN has on the given IP, subject to API key restrictions. """ return self._request('host', {'ip': ip}) def info(self): """Returns information about the current API key, such as a list of add-ons and other features that are enabled for the current user's API plan. """ return self._request('info', {}) def search(self, query, page=1, limit=None, offset=None): """Search the SHODAN database. Arguments: query -- search query; identical syntax to the website Optional arguments: page -- page number of the search results limit -- number of results to return offset -- search offset to begin getting results from Returns: A dictionary with 3 main items: matches, countries and total. Visit the website for more detailed information. """ args = { 'q': query, 'p': page, } if limit: args['l'] = limit if offset: args['o'] = offset return self._request('search', args) #ending of useless bullshit if len(sys.argv) <= 1: arewescanmode = 'no' elif len(sys.argv) > 1: if sys.argv[1] == '--scan-mode': arewescanmode = '--scan-mode' if sys.argv[1] == '--help' or sys.argv[1] == '-h': print '''To use this script you must first set your API key into the script by placing it in the variable. Then you can use the script to gather information about IPs using the shodan database. You can just run the script normally without any flags or you can run it with the --scan-mode to flag to take the list of IP's and scan them with nmap. nmap must be installed on your system. ''' exit() if userapi == "": exit( 'You api key is not set. Please open the program and put your api key in the userapi variable.' ) api = WebAPI(userapi) #settings all the variables for the program. if arewescanmode != '--scan-mode': shodansearch = raw_input( 'What would you like to search?:' ) shodantotal = raw_input( 'Would you like to show the total results found? [y/n]:' ) shodancountry = raw_input( 'Would you like to show the country? [y/n]:' ) shodanhostname = raw_input( 'Would you like to show the hostname? [y/n]:' ) shodanos = raw_input( 'Would you like to show the os? [y/n]:' ) shodanport = raw_input( 'Would you like to show the port? [y/n]:' ) shodanupdated = raw_input( 'Would you like to show when target was last updated? [y/n]:' ) shodandata = raw_input( 'Would you like to show banner data? [y/n]:' ) shodanfileopt = raw_input( 'Would you like to save the output to a file? [y/n]:' ) elif arewescanmode == '--scan-mode': shodansearch = raw_input( 'What would you like to search?:' ) if arewescanmode != '--scan-mode': if shodanfileopt == 'y': shodanfile = raw_input( 'Please enter in the path to an existing file. This will overwrite it:' ) while True: if not os.path.exists(shodanfile): shodanfile = raw_input( 'File does not exist. Try again:' ) else: editshodanfile = open( shodanfile, 'w' ) break #sets the initial try statement to grab all the results try: # search shodan results = api.search(shodansearch) # show the results if not in scan mode if arewescanmode != '--scan-mode': if shodansearch == 'y': print 'Results found: %s' % results['total'] if shodanfileopt == 'y': editshodanfile.write( 'Results found: %s\n' % results['total'] ) for result in results['matches']: print 'IP: %s' % result['ip'] if shodancountry == 'y': print 'Country: %s' % result['country_name'] if shodanhostname == 'y': print 'Hostname: %s' % result['hostnames'] if shodanos == 'y': print 'OS: %s' % result['os'] if shodanport == 'y': print 'Port: %s' % result['port'] if shodanupdated == 'y': print 'Updated: %s' % result['updated'] if shodandata == 'y': print '\n%s' % result['data'] if shodanfileopt == 'y': editshodanfile.write( 'IP: %s\n' % result['ip'] ) if shodancountry == 'y': editshodanfile.write( 'Country: %s\n' % result['country_name'] ) if shodanhostname == 'y': editshodanfile.write( 'Hostname: %s\n' % result['hostnames'] ) if shodanos == 'y': editshodanfile.write( 'OS: %s\n' % result['os'] ) if shodanport == 'y': editshodanfile.write( 'Port: %s\n' % result['port'] ) if shodanupdated == 'y': editshodanfile.write( 'Updated: %s\n' % result['updated'] ) if shodandata == 'y': editshodanfile.write( '\n%s' % result['data'] ) except Exception, e: print 'Error: %s' % e #if in scan mode then this menu is used instead if arewescanmode == '--scan-mode': scanfileopt = raw_input( 'Would you like to save output to a file? [y/n]:' ) if scanfileopt == 'y': scanfile = raw_input( 'Please enter in the path to an existing file. This will overwrite it:' ) while True: if not os.path.exists(scanfile): scanfile = raw_input( 'File does not exist. Try again:' ) else: editshodanfile = open( scanfile, 'w' ) tempscanfile = scanfile+'-temp' fin = open(tempscanfile, "r") break os.system('clear') #finds the estimated time resultsinseconds = (results['total']*130) if resultsinseconds >= 60 and resultsinseconds < 3600: estimatedtime = resultsinseconds/60 print 'Estimated time to complete scanning all hosts: >%s minutes' % estimatedtime elif resultsinseconds >= 3600 and resultsinseconds < 86400: estimatedtime = (resultsinseconds/60)/24 print 'Estimated time to complete scanning all hosts: >%s days' % estimatedtime elif resultsinseconds >= 86400 and resultsinseconds < 604800: estimatedtime = ((resultsinseconds/60)/24)/7 print 'Estimated time to complete scanning all hosts: >%s weeks' % estimatedtime elif resultsinseconds >= 604800 and resultsinseconds < 18144000: estimatedtime = (((resultsinseconds/60)/24)/7)/30 print 'Estimated time to complete scanning all hosts: >%s months' % estimatedtime elif resultsinseconds >= 18144000 and resultsinseconds < 217728000: estimatedtime = ((((resultsinseconds/60)/24)/7)/30)/12 print 'Estimated time to complete scanning all hosts: >%s years' % estimatedtime elif resultsinseconds > 217728000: print 'Estimated time to complete scanning all hosts: Unknown' #sets the menu and starts the scanning def scanner(ignore): if ignore == 'ignoring': os.system( 'nmap '+result['ip']+' -Pn --host-timeout 2m') else: os.system( 'nmap '+result['ip']+' --host-timeout 2m') print '\nWaiting for 10 seconds. If you want to pause the scan and see the menu then press ctrl-c now.' time.sleep(10) def scannerfile(ignore): if ignore == 'ignoring': os.system( 'nmap '+result['ip']+' --host-timeout 2m'+' -Pn -oN '+tempscanfile) else: os.system( 'nmap '+result['ip']+' --host-timeout 2m'+' -oN '+tempscanfile) for line in fin.readlines(): editshodanfile.write(line) print '\nWaiting for 10 seconds. If you want to pause the scan and see the menu then press ctrl-c now.' time.sleep(10) for result in results['matches']: try: print '#'*10+'Target Information'+'#'*10 print 'IP: %s' % result['ip'] print 'Country: %s' % result['country_name'] print 'Hostname: %s' % result['hostnames'] print 'OS: %s' % result['os'] print 'Updated: %s' % result['updated'] print '#'*10+'Nmap Output'+'#'*10 if scanfileopt != 'y': scanner('foo') if scanfileopt == 'y': editshodanfile.write( '#'*10+'Target Information'+'#'*10+'\n' ) editshodanfile.write( 'IP: %s\n' % result['ip'] ) editshodanfile.write( 'Country: %s\n' % result['country_name'] ) editshodanfile.write( 'Hostname: %s\n' % result['hostnames'] ) editshodanfile.write( 'OS: %s\n' % result['os'] ) editshodanfile.write( 'Updated: %s\n' % result['updated'] ) editshodanfile.write( '#'*10+'Nmap Output'+'#'*10+'\n' ) scannerfile('foo') editshodanfile.write( '\n' ) except KeyboardInterrupt: print '\nMenu options: ' print 'rescan rescan the target using the -Pn flag' print ' WARNING: ' print ' after running rescan you won\'t be ' print ' able to access the menu until another' print ' ip is scanned. If you do it will ' print ' exit and delete all content in log ' print ' file is option is chose.\n ' print 'exit exit the scan ' print 'continue continue the scan ' menuopt = raw_input( ':' ) if menuopt == 'rescan': if scanfileopt != 'y': scanner( 'ignoring' ) elif scanfileopt == 'y': scannerfile( 'ignoring' ) elif menuopt == 'exit': if scanfileopt == 'y': editshodanfile.close() fin.close() print '\nExiting...' exit() else: print 'Continuing...' if scanfileopt == 'y': editshodanfile.close() fin.close()

Reply