-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathsshdefaultscan.py
More file actions
executable file
·141 lines (123 loc) · 5.19 KB
/
Copy pathsshdefaultscan.py
File metadata and controls
executable file
·141 lines (123 loc) · 5.19 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
134
135
136
137
138
139
140
141
#!/usr/bin/env python
"""
sshdefaultscan
Scan networks for SSH servers with default username and password.
"""
import argparse
import logging
import socket
from time import time
import nmap
import paramiko
SSH_DEFAULT_USERNAME = 'root'
SSH_DEFAULT_PASSWORD = 'root'
BATCH_TEMPLATE_DEFAULT = '{host}'
def out(hostname, username, password, port, template='{host}'):
"""
Return a string to be used as output when "--batch" mode is enabled
:param hostname: String with the hostname
:param username: String with the username
:param password: String with the password
:param template: String with a template, defaults to "{host}" [1]
:return: String to be used as output
[1] See https://docs.python.org/2/library/string.html#formatstrings
"""
return template.format(
host=hostname,
username=username,
password=password,
port=port
)
#
# Main
#
if __name__ == '__main__':
###########################################################################
# Bootstrap
#
# Parse command line arguments
parser = argparse.ArgumentParser(description='Scan networks for SSH servers with default username and password.')
parser.add_argument('hosts', help='An IP address for a hostname or network, ex: 192.168.1.1 for single host or 192.168.1.1-254 for network.')
parser.add_argument('--username', help='Set username, default is "root".', default=SSH_DEFAULT_USERNAME)
parser.add_argument('--password', help='Set password, default is "root".', default=SSH_DEFAULT_PASSWORD)
parser.add_argument('--port', help='Set port, default is 22.', default='22')
parser.add_argument('--fast', help='Change timeout settings for the scanner in order to scan faster (T5).', default=False, action='store_true')
parser.add_argument('--batch', help='Batch mode will only output hosts, handy to use with unix pipes.', default=False, action='store_true')
parser.add_argument('--batch-template', help='Change batch mode output template, default is "{host}". Available context variables: host, username, password. Ex: "{username}@{host}" will return "root@192.168.0.1" as output when running in batch mode.', default=BATCH_TEMPLATE_DEFAULT)
args = parser.parse_args()
# If "--batch-template" is sent, assume that the user wants batch mode
if args.batch_template != BATCH_TEMPLATE_DEFAULT:
args.batch = True
# Setup logging
logger = logging.getLogger('sshdefaultscan')
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler = logging.FileHandler('sshdefaultscan.log')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
if args.batch:
logger.setLevel(logging.INFO)
else:
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
###########################################################################
# Scan
#
logger.debug('Scanning...')
hosts = list()
nmap_arguments = ['-n']
if args.fast:
nmap_arguments.append('-T5')
nm = nmap.PortScanner()
scan = nm.scan(args.hosts, args.port, arguments=' '.join(nmap_arguments))
stats = scan.get('nmap').get('scanstats')
logger.debug(
'{up} hosts up, {total} total in {elapsed_time}s'.format(
up=stats.get('uphosts'),
total=stats.get('totalhosts'),
elapsed_time=stats.get('elapsed')
)
)
for host, data in list(scan.get('scan').items()):
if data.get('tcp') and data.get('tcp').get(int(args.port)).get('state') == 'open':
hosts.append(host)
logger.debug('{host} Seems to have SSH open'.format(host=host))
if not hosts:
logger.debug('No hosts found with port {port} open.'.format(port=args.port))
exit()
###########################################################################
# Test credentials
#
logger.debug('Testing credentials...')
for host in hosts:
start_time = time()
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(
host,
username=args.username,
password=args.password,
port=int(args.port)
)
if args.batch:
print(out(host, args.username, args.password, args.port, template=args.batch_template))
logger.info('{host} Logged in with {username}:{password} in {elapsed_time}s'.format(
host=host,
username=args.username,
password=args.password,
elapsed_time=round(time() - start_time, 2)
))
except (
paramiko.ssh_exception.AuthenticationException,
paramiko.ssh_exception.SSHException,
socket.error
) as e:
logger.debug('{host} {exception} ({elapsed_time}s)'.format(
host=host,
exception=e,
elapsed_time=round(time() - start_time, 2)
))