chevron_left chevron_right
Login Register invert_colors photo_library


Stay updated and chat with others! - Join the Discord!
Thread Rating:
  • 0 Vote(s) - 0 Average


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






Users browsing this thread: 1 Guest(s)