-
Notifications
You must be signed in to change notification settings - Fork 648
Expand file tree
/
Copy pathhost.py
More file actions
133 lines (107 loc) · 5.59 KB
/
host.py
File metadata and controls
133 lines (107 loc) · 5.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Helper methods for printing `host` information to the terminal.
import click
from shodan.helpers import get_ip
def host_print_pretty(host, history=False):
"""Show the host information in a user-friendly way and try to include
as much relevant information as possible."""
# General info
click.echo(click.style(get_ip(host), fg='green'))
if len(host['hostnames']) > 0:
click.echo(u'{:25s}{}'.format('Hostnames:', ';'.join(host['hostnames'])))
if 'city' in host and host['city']:
click.echo(u'{:25s}{}'.format('City:', host['city']))
if 'country_name' in host and host['country_name']:
click.echo(u'{:25s}{}'.format('Country:', host['country_name']))
if 'os' in host and host['os']:
click.echo(u'{:25s}{}'.format('Operating System:', host['os']))
if 'org' in host and host['org']:
click.echo(u'{:25s}{}'.format('Organization:', host['org']))
if 'last_update' in host and host['last_update']:
click.echo('{:25s}{}'.format('Updated:', host['last_update']))
click.echo('{:25s}{}'.format('Number of open ports:', len(host['ports'])))
# Output the vulnerabilities the host has
if 'vulns' in host and len(host['vulns']) > 0:
vulns = []
for vuln in host['vulns']:
if vuln.startswith('!'):
continue
if vuln.upper() == 'CVE-2014-0160':
vulns.append(click.style('Heartbleed', fg='red'))
else:
vulns.append(click.style(vuln, fg='red'))
if len(vulns) > 0:
click.echo('{:25s}'.format('Vulnerabilities:'), nl=False)
for vuln in vulns:
click.echo(vuln + '\t', nl=False)
click.echo('')
click.echo('')
# If the user doesn't have access to SSL/ Telnet results then we need
# to pad the host['data'] property with empty banners so they still see
# the port listed as open. (#63)
if len(host['ports']) != len(host['data']):
# Find the ports the user can't see the data for
ports = host['ports']
for banner in host['data']:
if banner['port'] in ports:
ports.remove(banner['port'])
# Add the placeholder banners
for port in ports:
banner = {
'port': port,
'transport': 'tcp', # All the filtered services use TCP
'timestamp': host['data'][-1]['timestamp'], # Use the timestamp of the oldest banner
'placeholder': True, # Don't store this banner when the file is saved
}
host['data'].append(banner)
click.echo('Ports:')
for banner in sorted(host['data'], key=lambda k: k['port']):
product = ''
version = ''
if banner.get('product'):
product = banner['product']
if banner.get('version'):
version = '({})'.format(banner['version'])
click.echo(click.style('{:>7d}'.format(banner['port']), fg='cyan'), nl=False)
if 'transport' in banner:
click.echo('/', nl=False)
click.echo(click.style('{} '.format(banner['transport']), fg='yellow'), nl=False)
click.echo('{} {}'.format(product, version), nl=False)
if history:
# Format the timestamp to only show the year-month-day
date = banner['timestamp'][:10]
click.echo(click.style('\t\t({})'.format(date), fg='white', dim=True), nl=False)
click.echo('')
# Show optional HTTP information
if banner.get('http') and banner['http'].get('title'):
click.echo('\t|-- HTTP title: {}'.format(banner['http']['title']))
# Show optional ssl info
if 'ssl' in banner:
if 'cert' in banner['ssl'] and banner['ssl']['cert']:
if 'issuer' in banner['ssl']['cert'] and banner['ssl']['cert']['issuer']:
issuer = ', '.join(['{}={}'.format(key, value) for key, value in banner['ssl']['cert']['issuer'].items()])
click.echo('\t|-- Cert Issuer: {}'.format(issuer))
if banner['ssl']['cert'].get('subject'):
subject = ', '.join(['{}={}'.format(key, value) for key, value in banner['ssl']['cert']['subject'].items()])
click.echo('\t|-- Cert Subject: {}'.format(subject))
if banner['ssl'].get('versions'):
click.echo('\t|-- SSL Versions: {}'.format(', '.join([item for item in sorted(banner['ssl']['versions']) if not version.startswith('-')])))
if banner['ssl'].get('dhparams'):
click.echo('\t|-- Diffie-Hellman Parameters:')
click.echo('\t\t{:15s}{}\n\t\t{:15s}{}'.format('Bits:', banner['ssl']['dhparams']['bits'], 'Generator:', banner['ssl']['dhparams']['generator']))
if banner['ssl']['dhparams'].get('fingerprint'):
click.echo('\t\t{:15s}{}'.format('Fingerprint:', banner['ssl']['dhparams']['fingerprint']))
def host_print_tsv(host, history=False):
"""Show the host information in a succinct, grep-friendly manner."""
for banner in sorted(host['data'], key=lambda k: k['port']):
click.echo(click.style('{:>7d}'.format(banner['port']), fg='cyan'), nl=False)
click.echo('\t', nl=False)
click.echo(click.style('{} '.format(banner['transport']), fg='yellow'), nl=False)
if history:
# Format the timestamp to only show the year-month-day
date = banner['timestamp'][:10]
click.echo(click.style('\t({})'.format(date), fg='white', dim=True), nl=False)
click.echo('')
HOST_PRINT = {
'pretty': host_print_pretty,
'tsv': host_print_tsv,
}