def alert_domain(domain, triggers): """Create a network alert based on a domain name""" key = get_api_key() api = shodan.Shodan(key) try: # Grab a list of IPs for the domain domain = domain.lower() click.secho('Looking up domain information...', dim=True) info = api.dns.domain_info(domain, type='A') domain_ips = set([record['value'] for record in info['data']]) # Create the actual alert click.secho('Creating alert...', dim=True) alert = api.create_alert('__domain: {}'.format(domain), list(domain_ips)) # Enable the triggers so it starts getting managed by Shodan Monitor click.secho('Enabling triggers...', dim=True) api.enable_alert_trigger(alert['id'], triggers) except shodan.APIError as e: raise click.ClickException(e.value) click.secho('Successfully created domain alert!', fg='green') click.secho('Alert ID: {}'.format(alert['id']), fg='cyan')
def alert_list(expired): """List all the active alerts""" key = get_api_key() # Get the list api = shodan.Shodan(key) try: results = api.alerts(include_expired=expired) except shodan.APIError as e: raise click.ClickException(e.value) if len(results) > 0: click.echo(u'# {:14} {:<21} {:<15s}'.format('Alert ID', 'Name', 'IP/ Network')) for alert in results: click.echo(u'{:16} {:<30} {:<35} '.format( click.style(alert['id'], fg='yellow'), click.style(alert['name'], fg='cyan'), click.style(', '.join(alert['filters']['ip']), fg='white')), nl=False) if 'triggers' in alert and alert['triggers']: click.secho('Triggers: ', fg='magenta', nl=False) click.echo(', '.join(alert['triggers'].keys()), nl=False) if 'expired' in alert and alert['expired']: click.secho('expired', fg='red') else: click.echo('') else: click.echo("You haven't created any alerts yet.")
def remove(user): """Remove and downgrade a member""" key = get_api_key() api = shodan.Shodan(key) try: api.org.remove_member(user) except shodan.APIError as e: raise click.ClickException(e.value) click.secho('Successfully removed the member', fg='green')
def add(silent, user): """Add a new member""" key = get_api_key() api = shodan.Shodan(key) try: api.org.add_member(user, notify=not silent) except shodan.APIError as e: raise click.ClickException(e.value) click.secho('Successfully added the new member', fg='green')
def alert_disable_trigger(alert_id, trigger): """Disable a trigger for the alert""" key = get_api_key() # Get the list api = shodan.Shodan(key) try: api.disable_alert_trigger(alert_id, trigger) except shodan.APIError as e: raise click.ClickException(e.value) click.secho('Successfully disabled the trigger: {}'.format(trigger), fg='green')
def alert_create(name, netblocks): """Create a network alert to monitor an external network""" key = get_api_key() # Get the list api = shodan.Shodan(key) try: alert = api.create_alert(name, netblocks) except shodan.APIError as e: raise click.ClickException(e.value) click.secho('Successfully created network alert!', fg='green') click.secho('Alert ID: {}'.format(alert['id']), fg='cyan')
def domain_info(domain, details, save, history, type): """View all available information for a domain""" key = get_api_key() api = shodan.Shodan(key) try: info = api.dns.domain_info(domain, history=history, type=type) except shodan.APIError as e: raise click.ClickException(e.value) # Grab the host information for any IP records that were returned hosts = {} if details: ips = [ record['value'] for record in info['data'] if record['type'] in ['A', 'AAAA'] ] ips = set(ips) fout = None if save: filename = u'{}-hosts.json.gz'.format(domain) fout = helpers.open_file(filename) for ip in ips: try: hosts[ip] = api.host(ip) # Store the banners if requested if fout: for banner in hosts[ip]['data']: if 'placeholder' not in banner: helpers.write_banner(fout, banner) except shodan.APIError: pass # Ignore any API lookup errors as this isn't critical information # Save the DNS data if save: filename = u'{}.json.gz'.format(domain) fout = helpers.open_file(filename) for record in info['data']: helpers.write_banner(fout, record) click.secho(info['domain'].upper(), fg='green') click.echo('') for record in info['data']: click.echo( u'{:32} {:14} {}'.format( click.style(record['subdomain'], fg='cyan'), click.style(record['type'], fg='yellow'), record['value']), nl=False, ) if record['value'] in hosts: host = hosts[record['value']] click.secho(u' Ports: {}'.format(', '.join( [str(port) for port in sorted(host['ports'])])), fg='blue', nl=False) click.echo('')
def alert_list_triggers(): """List the available notification triggers""" key = get_api_key() # Get the list api = shodan.Shodan(key) try: results = api.alert_triggers() except shodan.APIError as e: raise click.ClickException(e.value) if len(results) > 0: click.secho('The following triggers can be enabled on alerts:', dim=True) click.echo('') for trigger in sorted(results, key=itemgetter('name')): click.secho('{:<12} '.format('Name'), dim=True, nl=False) click.secho(trigger['name'], fg='yellow') click.secho('{:<12} '.format('Description'), dim=True, nl=False) click.secho(trigger['description'], fg='cyan') click.secho('{:<12} '.format('Rule'), dim=True, nl=False) click.echo(trigger['rule']) click.echo('') else: click.echo("No triggers currently available.")
def alert_info(alert): """Show information about a specific alert""" key = get_api_key() api = shodan.Shodan(key) try: info = api.alerts(aid=alert) except shodan.APIError as e: raise click.ClickException(e.value) click.secho(info['name'], fg='cyan') click.secho('Created: ', nl=False, dim=True) click.secho(info['created'], fg='magenta') click.secho('Notifications: ', nl=False, dim=True) if 'triggers' in info and info['triggers']: click.secho('enabled', fg='green') else: click.echo('disabled') click.echo('') click.secho('Network Range(s):', dim=True) for network in info['filters']['ip']: click.echo(u' > {}'.format(click.style(network, fg='yellow'))) click.echo('') if 'triggers' in info and info['triggers']: click.secho('Triggers:', dim=True) for trigger in info['triggers']: click.echo(u' > {}'.format(click.style(trigger, fg='yellow'))) click.echo('')
def info(): """Show an overview of the organization""" key = get_api_key() api = shodan.Shodan(key) try: organization = api.org.info() except shodan.APIError as e: raise click.ClickException(e.value) click.secho(organization['name'], fg='cyan') click.secho('Access Level: ', nl=False, dim=True) click.secho(humanize_api_plan(organization['upgrade_type']), fg='magenta') if organization['domains']: click.secho('Authorized Domains: ', nl=False, dim=True) click.echo(', '.join(organization['domains'])) click.echo('') click.secho('Administrators:', dim=True) for admin in organization['admins']: click.echo(u' > {:30}\t{:30}'.format( click.style(admin['username'], fg='yellow'), admin['email'])) click.echo('') if organization['members']: click.secho('Members:', dim=True) for member in organization['members']: click.echo(u' > {:30}\t{:30}'.format( click.style(member['username'], fg='yellow'), member['email'])) else: click.secho('No members yet', dim=True)