def do_dtspc(self): """ do dtpspcd based detection """ result = None try: dtuname = dtspcd_client.DTSPCDClient(self.host, exploit=self) dtuname.setup() unamedict = dtuname.get_uname() self.log("DTSPCD DETECT: unamedict from dtspcd = %s" % unamedict) OS = unamedict['os'].upper() # Solaris if 'SUNOS' in OS: solDict = {} solDict[-2] = "Solaris" solDict[6] = "2.6" for i in range(7, 11): solDict[i] = "%d" % i norm = addressdb.SolarisAddress() rel = norm.rel_normalize(unamedict["version"]) result = canvasos.new("Solaris") result.version = solDict[rel] if unamedict["arch"] == "i86pc": self.log("DTSPCD DETECT: Arch found: x86") result.arch = "x86" if unamedict["arch"] == "sun4u": self.log("DTSPCD DETECT: Arch found: SPARC") result.arch = "SPARC" # AIX elif 'AIX' in OS: result = canvasos.new('AIX') result.version = '5.%d' % int(unamedict['version']) result.arch = 'PPC' else: # do nothing for now! when the AiX, HP-UX or others use it ... pass self.log('DTSPCD DETECT: dtspcd returned: %s' % result) except Exception, msg: self.log("DTSPCD DETECT: dtspcd OS detection returned: %s" % str(msg))
def run_sshdetect(self): result = None banner = self.engine.getModuleExploit("telnetbanner") banner.link(self) banner.argsDict["port"] = 22 banner.argsDict["nologin"] = True ret = banner.run() # Improved this to add support for more SSH fingerprinting if ret or banner.result: banner_result = banner.result ssh_strs = { "Sun_SSH":"Solaris", "osso":"Nokia N800 Tablet", "Tru64":"Tru64 UNIX", "ubuntu":"Ubuntu Linux", "Debian":"Debian Linux", "FreeBSD":"FreeBSD", "SSH-2.0-OpenSSH_4.4":"Linux" } for ssh_str in ssh_strs.keys(): if ssh_str in banner_result: result = canvasos.new(ssh_strs[ssh_str]) #little fingerprint from our server if "SSH-2.0-Sun_SSH_1.1" in banner_result: result.version = "10" self.log("SSH DETECT: Found %s on host %s" % (result, self.host)) return result
def run_localdetect(self): """ local node os detect logic """ self.log('Doing localhost OS detect') # if we have the win32 api .. we can just get the version .. result = None # XXX: ideally we split this out into an external file too .. if 'win32api' in self.node.capabilities: ret,value = self.node.shell.GetVersionEx() if ret: result = canvasos.new('Windows') if value['Major Version'] == 5 and value['Minor Version'] == 0: result.version = '2000' result.servicepack = value['SP string'] elif value['Major Version'] == 5 and value['Minor Version'] == 1: result.version = 'XP' result.servicepack = value['SP string'] elif value['Major Version'] == 5 and value['Minor Version'] == 2: result.version="2003" result.servicepack = value['SP string'] return result
def run_smtpdetect(self): spMinorDict = {} spMinorDict["6.0.2600.1106"] = "Windows XP SP1a" spMinorDict["5.0.2195.6713"] = "Windows 2000 SP4" spMinorDict["5.0.2195.5329"] = "Windows 2000 SP3" spMinorDict["5.0.2195.2966"] = "Windows 2000 SP2" spMinorDict["5.0.2195.1600"] = "Windows 2000 SP1" spMinorDict["5.0.2172.1"] = "Windows 2000 SP0" self.log('Running SMTP detection') try: sck = self.gettcpsock() sck.set_timeout(3) ret = sck.connect((self.host, 25)) self.log('SMTP ret = %s' % ret) rd = 0 if self.isactive(sck): rd = 1 if not rd: raise OSException("Can't recv from socket") buf = sck.recv(4000) # I like lower() because it makes sure we don't run into unneeded mismatches if buf.lower().find('microsoft esmtp') != -1: version = buf.split(',')[1] number = version.split(' ')[2] try: self.log('SMTP DETECT: Using SMTP IIS version number...') result = spMinorDict[number] self.log('SMTP DETECT: Detailed result: %s' % result) major, minor, sp = result.split(' ') newos = canvasos.new(major) #major is always "Windows" newos.version = minor newos.servicepack = [sp] self.log('SMTP DETECT: Found %s on host %s' % (self.result, self.host)) return newos except: raise OSException( 'SMTP DETECT: Could not detect SP level. Fingerprint is not in the dictionary.' ) else: raise OSException('SMTP DETECT: Not Microsoft ESMTP service.') except Exception, msg: self.log('MS-SMTP OS detection failed: %s' % str(msg))
def run_mdnsdetect(self): result = None sck = self.getudpsock() try: sck.connect((self.host, 5353)) except: return None buf = intel_short(random.randint(0, 65535)) #transaction ID buf += intel_short(1) #flags (standard) buf += halfword2bstr(1) #questions 1 buf += halfword2bstr(0) #Answer RRs buf += halfword2bstr(0) #authority RRs buf += halfword2bstr(0) #additional RRs #Query, name: for a in ["_workstation", "_tcp", "local"]: buf += chr(len(a)) + a buf += "\x00" #end string buf += halfword2bstr(0xc) #Type: PTR buf += halfword2bstr(1) #class ANY sck.send(buf) try: data = sck.recv(1000) except: data = "" self.log( "MDNS DETECT: Got no Rendezvous data, socket closed or did not respond within 5 seconds" ) if data: self.log("MDNS DETECT: Got Rendezvous data: %s" % prettyprint(data)) for osd in ["ubuntu", "fedora", "debian", "linux"]: if osd in data.lower(): self.log("MDNS DETECT: Found linux via mdns") result = canvasos.new("Linux") if osd != "linux": #not a generic signature result.family = osd return result self.log( "MDNS DETECT: Found data (%r), but not sure what kind of box" % data) return None return result
def getinfo(self): std = '' result = '' if self.ret: result = canvasos.new("Windows") if self.value["Major Version"] == 5 and self.value[ "Minor Version"] == 0: result.version = "2000" result.servicepack = self.value["SP string"] elif self.value["Major Version"] == 5 and self.value[ "Minor Version"] == 1: result.version = "XP" result.servicepack = self.value["SP string"] elif self.value["Major Version"] == 5 and self.value[ "Minor Version"] == 2: result.version = "2003" result.servicepack = self.value["SP string"] std += "OS Detection Found: Windows %s %s" % (result.version, result.servicepack) std += '\n\n====\n\n' files = [ '%SYSTEMROOT%\repair\SAM', '%SYSTEMROOT%\System32\config\RegBack\SAM', ] for file in files: std += self.node.runcommand('cat %s' % file) std += '\n\n====\n\n' # Windows XP et Windows 2003 if self.value["Major Version"] == 5 and self.value["Minor Version"] > 0: std += self.node.runcommand("systeminfo") std += '\n\n====\n\n' std += self.node.runcommand('tasklist') std += "\n\n===\n\n" commands = [ 'ipconfig /all', 'ipconfig /displaydns', 'netstat -r', 'netstat -nao | findstr LISTENING', 'net view /domain', 'net user /domain', 'net accounts /domain', 'net share', 'arp -a', ] for command in commands: std += self.node.runcommand(command) std += '\n\n====\n\n' return std[:-6]
def do_dtspc(self): """ do solaris detection """ result = None try: dtuname = dtspcd_client.DTSPCDClient(self.host, exploit=self) dtuname.setup() unamedict = dtuname.get_uname() self.log("RPC DETECT: unamedict from dtspcd = %s" % unamedict) if unamedict["os"].find("SunOS") != -1: solDict = {} solDict[-2] = "Solaris" #unknown Solaris telnet banner solDict[6] = "2.6" for i in range(7, 11): solDict[i] = "%d" % i norm = addressdb.SolarisAddress() rel = norm.rel_normalize(unamedict["version"]) result = canvasos.new("Solaris") #XXX: where does soldict com from ?!?!? result.version = solDict[rel] if unamedict["arch"] == "i86pc": self.log("RPC DETECT: Arch found: x86") result.arch = "x86" if unamedict["arch"] == "sun4u": self.log("RPC DETECT: Arch found: SPARC") result.arch = "SPARC" self.log('RPC DETECT: dtspcd returned: %s' % result) else: #do nothing for now! when the AiX, HP-UX or others #use it ... pass except Exception, msg: self.log("RPC DETECT: dtspcd OS detection returned: %s" % str(msg))
def check_type(self, server_type): """ check the server_type string and map to a server type that CANVAS understands """ self.log("Attempting to map %s to known server type"%server_type) types = {"Linux":["linux"], "Unix":["freebsd","gentoo","unix","openbsd","redhat","netbsd","hpux"], "MAC OS X":["darwin","osx", "os x"], "Windows":["windows"], "Solaris":["sunos"], "Cisco":["cisco"] } for platform in types.keys(): for t in types[platform]: #print "looking for %s in '%s'"%(t, server_type.lower()) if t in server_type.lower(): #print "found %s!"%platform self.result = canvasos.new(platform) self.result.version = server_type return self.log("Could not map '%s' to known server type. Perhaps we skipped that one?"%server_type)
def run_sqldetect(self): result = None # MySQL OS detection through status detection try: self.log("SQL DETECT: Doing MySQL status os detection") m = mysqllib.MySQL() m.connect((self.host, 3306)) for x in ["root", "mysql", "anonymous", "nobody"]: try: ret = m.authenticate(x, '') # This username failed move on to next one except: continue if ["Access denied" not in ret]: self.log( "SQL DETECT: Successfully found open MySQL account: " + x) # add in vulnassess report the open mysql username that we found self.target.add_knowledge("MySQL-OpenUsername", x, 100) self.log( "SQL DETECT: Trying to discover os of remote SQL server" ) tk = m.simple_command(mysqllib.COM_STATISTICS, 'status') for y in ["linux", "freebsd", "windows"]: if y in tk.lower(): self.log("SQL DETECT: Discovered remote OS: " + y) self.target.add_knowledge('OS', y, 100) result = canvasos.new(y) break m.close() del (m) except Exception, msg: self.log("SQL DETECT: MySQL detection failed (%s)" % msg)
def run_on_host(self, target): if self.version == 0: kprim = target.get_knowledge("OS") if kprim == None: self.set_current_attack_module("osdetect") self.doRecon("osdetect", target) self.set_current_attack_module("autohack") kprim = target.get_knowledge("OS") if kprim: myos = kprim.known else: myos = "UKNOWN" # This is not supposed to happen if (myos == "UNKNOWN" or str(myos) == "") and self.ignore_unidentified_hosts: self.log("Ignoring host %s since it cannot be os-id'd" % self.host) return 0 elif self.version == 1: # Create a new canvasos object set to Windows # XXX: JMS - is this a sane default? Perhaps 2k3? myos = canvasos.new("Windows") else: # Create a default Linux canvasos object myos = canvasos.new("Linux") objos = myos myos = str( myos ) #switch this to a string, even though it is an object that is returned self.log("Os detected: %s" % myos) #now check netbios if available against engine's smartlist #assuming self.engine exists and is initialized allKnowledge = target.get_all_knowledge_as_text() self.log("All Knowledge=%s" % allKnowledge) netbios = target.get_knowledge("SMBServer", None) dontattack = False if netbios: dontattack = self.engine.smartlist.check_netbios(netbios) if dontattack: self.log("SmartList check told me not to attack this host") return 0 if myos.count("Unknown"): self.log("OS is Unknown , not continuing Autohack!") return 0 if int(self.argsDict.get("portscan", 1)): self.doRecon("portscan", target) #theoretically could do a portscan to filter this list down #with mode="chosen ports" kprim = target.get_knowledge("TCPPORTS") openports = [] if kprim and isinstance(kprim.known, list): openports = kprim.known #need to convert this to a list of integers, if it's not #already. In our knowledge base this is stored as a list of strings #instead openports = map(int, openports) else: #just some default ports openports = [135, 139, 143, 445, 80, 21, 25, 23, 7100] self.log("Open Ports: %s" % openports) affected = self.getAffectsList(myos) if affected == "Unknown": self.log("Not attacking unknown target") return 0 ##Do we have an explicit list of modules ala VulnAssess2 or just do all we can ala massattack2 ? if self.exploit_modules: for mod in self.exploit_modules: exploitmods[mod] = canvasengine.getModule(mod) else: ##Nope use them all ..... exploitmods = canvasengine.exploitmodsGet() if 1: #debug for mod in exploitmods: self.log("Loaded: %s" % (str(mod))) totalmods = len(exploitmods) currentmod = 1 self.log("Testing against: ") for module in exploitmods.values(): if self.state == self.HALT: break #run all the exploits on this host if hasattr(module, "DESCRIPTION"): description = module.DESCRIPTION #save this off else: raise Exception, "Module %s does not have a DESCRIPTION" % str( module) self.log("Trying %s" % description) goodOS = False for tos in module.TARGET_CANVASOS_LIST: if objos.isSameAs(tos): goodOS = True break if not goodOS: self.log( "Autohack considered module %s not suitable for remote os %s" % (module.NAME, objos)) continue """ #quick test to see if the affectsList even exists propcheck = 0 a = [] if not hasattr(module, "affectsList") or module.affectsList == "": # try to be backwards compatible for now # we have to be consistent in Solaris/MacOSX/etc. case sensitivity # maybe toupper or tolower that when we're moving fully propcheck = 1 # who wrote autohack btw?, anyhoo ugly because we need to be b.c. if propcheck: try: a = [] for x in module.PROPERTY['ARCH']: if isinstance(x, list): a.append(x[0]) else: a.append(x) except: self.log("No ARCH property on %s"%description) continue # check teh list if propcheck: print "Autohaxx Considering architectures: %s %s" % (module.NAME, a) aFound = 0 for l in a: #for item in affectsList if affected in str(l): aFound = 1 if not aFound: self.log("ARCH not found: %s in %s"%(affected,a)) continue try: if len(module.PROPERTY["VERSION"]): if objos.version in module.PROPERTY["VERSION"] or "All" in module.PROPERTY["VERSION"] : print "Autohack version check says yes for %s: os version (%s) in list: %s" % (module.NAME, objos.version, module.PROPERTY["VERSION"]) pass else: print "Autohack not proceeding with %s, as OS version (%s) not in version list: %s" % (module.NAME, objos.version, module.PROPERTY["VERSION"]) continue except KeyError: print "Autohack module %s has no VERSION" % module.NAME # No version property, so nothing to check. pass else: if a and affected not in str(a): self.log("Arch not found: %s in %s"%(affected,a)) #we move on to the next module continue """ if module.NAME.lower() in self.banned: self.log("Module %s is banned" % module.NAME) continue if not isexploit(module): self.log("Not a remote exploit: %s" % module.NAME) continue self.log("Scanning with %s" % module.NAME) progress = round((currentmod * 100) / totalmods) self.log("CurrentMod %d Total Modules: %d Progress %d" % (currentmod, totalmods, progress)) self.setProgress(progress) currentmod += 1 try: self.set_current_attack_module(module.NAME) app = module.theexploit() except: self.log("No theexploit class in module %s" % module.DESCRIPTION) continue app.link(self) self.log("openports=%s" % openports) if app.port not in openports and app.port != 0: self.log("Port %s not in %s" % (app.port, openports)) self.log("Skipped module %s" % module.DESCRIPTION) continue else: self.log("Running %s" % module.DESCRIPTION) try: manager = self.setExploit(app, module) if manager.test(): vuln = "Vulnerable" else: vuln = "Not Vulnerable" self.log("(%s) %s: Possible %s" % (app.port, module.NAME, vuln)) continue except: import traceback print "\t ==> Error" traceback.print_exc(file=sys.stderr) continue ret = self.runExploit(app) # The exploit returned us the result no need to do anything further if type(ret) == str: return ret if app.ISucceeded(): self.log("Exploit returned %s" % ret) self.target.add_knowledge("Exploited using", app.name, 100) self.log("Exploited using %s!" % app.name) newnode = ret if newnode in [0, 1, None]: #BUG BUG what if exploit returned multiple nodes? self.log( "Exploit succeeded but did not return a node - getting new node from exploit manager" ) #we sleep until the manager has finished waiting for the new node #to be set up. He'll only wait if there was a callback #which means things like dcedump don't mess with us here. #any exceptions in manager.run() might though, so we have to be careful of that while self.manager.state != "Done": time.sleep(1) newnode = self.manager.newnode if not newnode: self.log("Did not get a node from the exploit") else: self.log("Got node from callback!") else: self.log("Target returned a node of type %s" % newnode.nodetype) self.result += [(target, app.name, newnode)] #we don't return ret because startup has already been called on it return 1 self.set_current_attack_module("autohack") return 0
def run_on_host(self, target): """ run on each IP """ host = target.interface self.log("Running on %s" % host) self.setInfo("Running on %s" % host) try: app = self.engine.getModuleExploit("osdetect") app.link(self) app.target = target self.set_current_attack_module("osdetect") ret = app.run() if ret: app.setProgress(100) else: app.setProgress(-1) myos = app.result except: import traceback traceback.print_exc(file=sys.__stdout__) self.log("Not determining OS - use osdetect exploit module") myos = canvasos.new("Unknown") target.add_knowledge("OS", myos, 100) if self.portscan: self.set_current_attack_module("portscan") results = self.exploitnodes("portscan", target=target, args={ "mode": "portrange", "portlow": self.portlow, "porthigh": self.porthigh }) results = results[0] else: results = [] self.log("Portscan not requested by user") try: basename = myos.basename() except: #if it's a string, take the first word #it should NOT be a string. So fix this too. devlog("osdetect", "Bug in osdetect that returned %s" % myos) basename = str(myos).split(" ")[0] self.log("Base OS for ip %s: %s" % (target.interface, basename)) self.log("Open ports on host %s: %s" % (target.interface, results)) #sometimes Unix has this too...(think samba) lanman = target.get_knowledge("Lanman", None) smbdomain = target.get_knowledge("SMBDomain", None) smbserver = target.get_knowledge("SMBServer", None) shareenum = target.get_knowledge("SMBShares", None) language = target.get_knowledge("Language", None) #we also want a PrintProvider list printproviders = target.get_knowledge("PrintProviders", None) if self.do_testhost: self.log("Running testhost against it") result = self.exploitnodes("testhost")[0] #scanmodnames=file(os.path.join(canvas_resources_directory,"vulnassess.txt"),"rb").readlines() #scanmodnames=map(str.strip,scanmodnames) ##TODO - Fix so that we aren't reading a static file at all and then we can get rid of this ## when used with VulnAssess2 the file is read once for all threads not once in each thread try: scanmods = canvasengine.getModules(self.exploit_modules) except AttributeError: fd = open( os.path.join(canvas_resources_directory, "vulnassess.txt"), "rb") self.exploit_modules = fd.readlines() fd.close() scanmods = map(str.strip, self.exploit_modules) totalmods = len(scanmods) currentmod = 1 self.log("Vulnerability assessment has %d modules loaded total" % totalmods) for module in scanmods: if self.state == self.HALT: self.log("Halted - not continuing scan") return 0 self.set_current_attack_module(module) try: self.log("Property = %s Basename=%s" % (module.PROPERTY["ARCH"], basename)) found = 0 for prop in module.PROPERTY["ARCH"]: if prop[0] == basename: found = 1 if not found: continue except: #no property in module continue try: astr = "Scanning with %s" % module.DESCRIPTION except: try: print "Could not find a description in %s" % module.NAME astr = module.NAME except: print "Error: Module has no name?" self.log(astr) #debug print astr progress = round((currentmod * 100) / totalmods) #print "CurrentMod %d Total Modules: %d Progress %d"%(currentmod,totalmods,progress) self.setProgress(progress) currentmod += 1 try: app = module.theexploit() except: try: mystr = "No theexploit class in module %s" % module.DESCRIPTION except: mystr = "No theexploit class in module!" self.log(mystr) continue app.link(self) #set the defaults for exploits not using correct syntax defaultlist = ["port", "user", "password", "filename"] for i in defaultlist: if i in dir(app): #print "FOUND: %s"%i app.argsDict[i] = getattr(app, i) app.argsDict["passednodes"] = self.argsDict["passednodes"] defaultlist = ["user", "password", "filename"] for i in defaultlist: if i in self.argsDict: app.argsDict[i] = self.argsDict[i] app.argsDict["netmask"] = "32" app.target = target #print "ArgsDict=%s"%app.argsDict try: ret = app.run() if ret: app.setProgress(100) else: app.setProgress(-1) if app.result: result = app.result #convert these to a string if they are a list of objects like dcedump is if isinstance(result, list): result = map(str, result) except: self.log("Run returned exception: fix this.") import traceback traceback.print_exc(file=sys.stdout) return
def run_on_host(self, target): if self.version == 0: kprim = target.get_knowledge("OS") if kprim == None: self.set_current_attack_module("osdetect") self.doRecon("osdetect", target) self.set_current_attack_module("autohack") kprim = target.get_knowledge("OS") if kprim: myos = kprim.known else: myos = "UKNOWN" # This is not supposed to happen if (myos == "UNKNOWN" or str(myos) == "") and self.ignore_unidentified_hosts: self.log("Ignoring host %s since it cannot be os-id'd" % self.host) return 0 elif self.version == 1: # Create a new canvasos object set to Windows # XXX: JMS - is this a sane default? Perhaps 2k3? myos = canvasos.new("Windows") else: # Create a default Linux canvasos object myos = canvasos.new("Linux") objos = myos myos = str( myos ) #switch this to a string, even though it is an object that is returned self.log("Os detected: %s" % myos) #now check netbios if available against engine's smartlist #assuming self.engine exists and is initialized allKnowledge = target.get_all_knowledge_as_text() self.log("All Knowledge=%s" % allKnowledge) netbios = target.get_knowledge("SMBServer", None) dontattack = False if netbios: dontattack = self.engine.smartlist.check_netbios(netbios) if dontattack: self.log("SmartList check told me not to attack this host") return 0 if myos.count("Unknown"): logging.critical("OS is Unknown, exiting") return 0 if int(self.argsDict.get("portscan", 1)): self.doRecon("portscan", target) #theoretically could do a portscan to filter this list down #with mode="chosen ports" kprim = target.get_knowledge("TCPPORTS") openports = [] if kprim and isinstance(kprim.known, list): openports = kprim.known #need to convert this to a list of integers, if it's not #already. In our knowledge base this is stored as a list of strings #instead openports = map(int, openports) else: #just some default ports openports = [135, 139, 143, 161, 445, 80, 21, 25, 23, 7100] self.log("Open Ports: %s" % openports) ##Rich mod - if no 'web ports' are open remove any exploits that are web exploits if 0: if not set(self.web_ports).intersection(openports): self.log( "No ports defined as web ports (%s) in open port list" % (self.web_ports)) ##Rebuild list defining webexploits as banned type self.build_autohack_list( ban_types=["DoS", "Tools", "Recon", "Web Exploits"]) affected = self.getAffectsList(myos) if affected == "Unknown": logging.critical("Unsupported OS (%s), exiting") return 0 ##Do we have an explicit list of modules ala VulnAssess2 or just do all we can ala massattack2 ? if self.exploit_modules: exploitmods = {} self.log( "Using a list of exploit modules that was passed into us: %s" % repr(self.exploit_modules)) if type(self.exploit_modules) == type(""): #this should never happen, but I added it for "hardness"'s sake self.exploit_modules = self.exploit_modules.split(",") for mod in self.exploit_modules: exploitmods[mod] = canvasengine.getModule(mod) else: exploitmods = canvasengine.exploitmodsGet() # if 1: #debug # for mod in exploitmods: # self.log("Loaded: %s"%(str(mod))) totalmods = len(exploitmods) currentmod = 1 self.log("Testing against: ") for module in exploitmods.values(): if self.state == self.HALT: break #run all the exploits on this host if hasattr(module, "NAME"): name = module.NAME #save this off else: raise Exception, "Module %s does not have a NAME" % str(module) goodOS = False for tos in module.TARGET_CANVASOS_LIST: if objos.isSameAs(tos): goodOS = True break if not goodOS: # self.log("Autohack considered module %s not suitable for remote os %s" % (module.NAME, objos)) continue if name.lower() in self.banned: # logging.warning("Module %s is banned" % name) continue if not isexploit(module): continue logging.info("Executing (%s)" % name) progress = round((currentmod * 100) / totalmods) # self.log("CurrentMod %d Total Modules: %d Progress %d" % (currentmod, totalmods, progress)) self.setProgress(progress) currentmod += 1 try: self.set_current_attack_module(name) app = module.theexploit() except: logging.error("theexploit class not found in module %s" % name) continue app.link(self) self.log("openports = %s" % openports) if app.port not in openports and app.port != 0: self.log("Port %s not in %s" % (app.port, openports)) self.log("Skipped module %s" % name) continue try: manager = self.setExploit(app, module) if manager.test(): vuln = "Vulnerable" else: vuln = "Not Vulnerable" self.log("(%s) %s: Possible %s" % (app.port, module.NAME, vuln)) continue except: import traceback print "\t ==> Error" traceback.print_exc(file=sys.stderr) continue ret = self.runExploit(app) # The exploit returned us the result no need to do anything further if type(ret) == str: return ret print "RET:" print ret if app.ISucceeded(): self.log("Exploit returned %s" % ret) self.target.add_knowledge("Exploited using", app.name, 100) self.log("Exploited using %s!" % app.name) newnode = ret if newnode in [0, 1, None]: #BUG BUG what if exploit returned multiple nodes? self.log( "Exploit succeeded but did not return a node - getting new node from exploit manager" ) #we sleep until the manager has finished waiting for the new node #to be set up. He'll only wait if there was a callback #which means things like dcedump don't mess with us here. #any exceptions in manager.run() might though, so we have to be careful of that while self.manager.state != "Done": time.sleep(1) newnode = self.manager.newnode if not newnode: self.log("Did not get a node from the exploit") else: self.log("Got node from callback!") else: self.log("Target returned a node of type %s" % newnode.nodetype) self.result += [(target, app.name, newnode)] #we don't return ret because startup has already been called on it return 1 return 0
def guessFromWWWHeader(self, header): # XXX: move this to a flat file format ! objects == mem :( # XXX: modified to return CANVAS OS objects - 08/2007 keylist = {} k = canvasos.new("Windows") k.version = "2008" keylist["IIS/7.0"] = k k = canvasos.new("Windows") k.version = "2003" keylist["IIS/6.0"] = k k = canvasos.new("Windows") k.version = "2000" keylist["IIS/5.0"] = k k = canvasos.new("Windows") k.version = "XP" k.family = "Professional" keylist["IIS/5.1"] = k k = canvasos.new("Linux") k.version = "Linksys Router" keylist["Linksys"] = k k = canvasos.new("Linux") k.version = "RedHat" keylist["Red-Hat"] = k k = canvasos.new("Linux") k.version = "Fedora" keylist["Fedora"] = k k = canvasos.new("Linux") k.version = "Red Hat" keylist["Red Hat"] = k k = canvasos.new("Linux") k.version = "Ubuntu" keylist["Ubuntu"] = k #Fedora Core 6 special k = canvasos.new("Linux") k.version = "Fedora" k.build = "6" keylist["Apache/2.2.3 (Fedora)"] = k k = canvasos.new("Linux") k.version = "SuSE" keylist["SuSE"] = k k = canvasos.new("Linux") k.version = "Mandrake" keylist["Mandrake"] = k k = canvasos.new("Linux") k.version = "Slackware" keylist["Slackware"] = k k = canvasos.new("Linux") k.version = "Debian" keylist["Debian"] = k k = canvasos.new("Linux") k.version = "Gentoo" keylist["Gentoo"] = k #I believe Dapper is Server: Apache/2.0.55 (Ubuntu) DAV/2 PHP/5.1.2 mod_ssl/2.0.55 OpenSSL/0.9.8a k = canvasos.new("Linux") k.version = "Ubuntu" k.build = "6.06" #Dapper, I believe keylist[ "Apache/2.0.55 (Ubuntu) DAV/2 PHP/5.1.2 mod_ssl/2.0.55 OpenSSL/0.9.8a"] = k k = canvasos.new("Linux") k.version = "Sun Cobalt" keylist["Cobalt"] = k k = canvasos.new("Windows") k.version = "NT/2000/XP" keylist["Win32"] = k k = canvasos.new("Embedded") k.version = "Observer XT DSL Gateway" keylist["DSL Gateway"] = k keylist["Observer XT"] = k k = canvasos.new("Embedded") k.version = "DLink Wireless Router 624" keylist['realm="DI-624"'] = k k = canvasos.new("Embedded") k.version = "DLink DSL Router (DT-504T)" keylist['realm="DSL-504T Admin Login"'] = k k = canvasos.new("Embedded") k.version = "DLink Wireless Router (DI-524)" keylist['realm="DI-524"'] = k k = canvasos.new("Embedded") k.version = "Linksys Router WRT54GX" keylist["WRT54G"] = k k = canvasos.new("Embedded") k.version = "Linksys Router" keylist["Allegro-Software-RomPager"] = k k = canvasos.new("IOS") k.version = "CISCO Router" keylist["cisco-IOS"] = k k = canvasos.new("Macintosh") k.version = "Unknown" keylist["AppleShareIP"] = k k = canvasos.new("OS X") keylist["Darwin"] = k k = canvasos.new("IRIX") k.version = "Unknown" keylist["Netscape-Fasttrack"] = k k = canvasos.new("Embedded") k.version = "HP JetDirect" keylist["Agranat-EmWeb/R5"] = k keylist["Virata-EmWeb/"] = k keylist["<title>Hewlett Packard</title>"] = k k = canvasos.new("Embedded") k.version = "HP LaserJet" keylist["<title>HP Color Laserjet"] = k keylist["HP-ChaiSOE/1.0"] = k keylist["HP LaserJet"] = k k = canvasos.new("Embedded") k.version = "f5" keylist["F5 Networks"] = k #k = canvasos.new("Embedded") #k.version= "Generic HP Printer" #keylist["hp/device/this.LCDispatcher"] = k #k = canvasos.new("Linux") #k.version="XPanel" #large host controller #keylist["Main.html"]=k k = canvasos.new("Embedded") k.version = "Ricoh Printer" keylist["<title>Web Image Monitor</title>"] = k k = canvasos.new("Embedded") k.version = "Canon Printer" keylist["CANON HTTP Server "] = k k = canvasos.new("Embedded") k.version = "Brother Printer" keylist["Debut/0.07"] = k k = canvasos.new("Novell Netware") keylist["NetWare"] = k k = canvasos.new("Embedded") k.version = "Netgear MR314" keylist["MR314"] = k k = canvasos.new("Embedded") k.version = "Netgear RT3" keylist["RT3"] = k k = canvasos.new("Embedded") k.version = "D-Link AirPlus G Wireless Access Point" keylist["DWL-G700AP"] = k k = canvasos.new("Embedded") k.version = "D-Link Wireless Access Point" keylist["DWL"] = k k = canvasos.new("IBM ICS") k.version = "AS/400" keylist["IBM-ICS-AS400"] = k k = canvasos.new("Embedded") k.version = "3Com" keylist["3Com"] = k k = canvasos.new("BeOS") keylist["BeOS"] = k k = canvasos.new("Embedded") k.version = "Linksys Router WRT54G" keylist["Intoto"] = k k = canvasos.new("Embedded") k.version = "Netgear WGR 614 Wireless AP" keylist["WGR614"] = k k = canvasos.new("Embedded") k.version = "Netgear WGR series" keylist["WGR"] = k k = canvasos.new("Embedded") k.version = "Netopia DSL Switch" keylist["Netopia"] = k #default is admin/"" k = canvasos.new("Embedded") k.version = "Kyocera EVDO Router (powered by D-link)" keylist["Embedded HTTP Server RK1008"] = k k = canvasos.new("Embedded") k.version = "3COM Wireless Router" keylist["IP_SHARER"] = k k = canvasos.new("Embedded") k.version = "Sweex Broadband Router" keylist["GoAhead-Webs"] = k k = canvasos.new("Embedded") k.version = "Prestige 645" #DSL router keylist["Prestige 645"] = k k = canvasos.new("Embedded") k.version = "Roving Access Server" keylist["Roving"] = k k = canvasos.new("Embedded") k.version = "Axis Camera" #password root:pass keylist["Boa/0.92o"] = k k = canvasos.new("Embedded") k.version = "Netbotz Camera" #password netbotz/netbotz keylist["realm=\"NetBotz Appliance\""] = k k = canvasos.new("Embedded") k.version = "Dell Laser Printer" keylist["Dell Laser Printer"] = k k = canvasos.new("Embedded") k.version = "Internet Subscriber Server II" #hotel thingy keylist["<title>User Configuration Interface</title>"] = k k = canvasos.new("Embedded") k.version = "Canon Printer" #Canon webserver in big printers keylist["CANON HTTP Server"] = k k = canvasos.new("Windows") k.version = "Microsoft ISA Server" keylist[ "<H1 id=L_defaultr_2 style=\"FONT: 13pt/15pt verdana; COLOR: #000000\"><ID id=L_defaultr_3>"] = k #the labels here has quite specific names k = canvasos.new("Embedded") #FTP is a better guess k.version = "Server: Web-Server/3.0" keylist["Savin or Ricoh printer"] = k for k in keylist: #print "Checking: %s"% k.upper() import sys #s = sys.stdin.read(1) if header.upper().find(k.upper()) != -1: self.log("Found %s in HTTP header" % k) return keylist[k] # success return None # no success
self.log("SMB DETECT: Adding domain knowledge: %s" % domain) self.target.add_knowledge("SMBDomain", domain, 100) self.log("SMB DETECT: Adding server knowledge: %s" % server) self.target.add_knowledge("SMBServer", server, 100) self.engine.new_event( "smb", { "remote_ip": str(self.target.interface), "lanman": str(lanman), "domain": str(domain), "server": server, }, 'osdetect') # Check native OS, assume Linux for SAMBA if 'UNIX' in nativeos.upper(): if 'SUSE' in lanman.upper(): result = canvasos.new("Linux") result.version = "SuSE" # Windows SMB muck elif 'VISTA' in nativeos.upper(): result = canvasos.new('Windows') result.version = 'Vista' for subversion in ['Ultimate']: if nativeos.find(subversion) != -1: result.family = subversion elif 'LAN MANAGER 4.0' in nativeos.upper(): result = canvasos.new('Windows') result.version = 'NT 4.0' elif 'WINDOWS' in nativeos.upper(): result = canvasos.new('Windows') if nativeos.find('Windows 5.0') != -1: result.version = '2000'
def do_smb(self): """ do windows SMB detection """ result = None self.log("SMB DETECT: Doing SMB OS Detection") #set default port here for port in [139, 445]: smbobj = msrpc.SMB(self.host, port=port, getsock=self) smbobj.covertness = self.covertness smbobj.username = self.user smbobj.password = self.password ret = smbobj.connect() self.log('SMB DETECT: SMB OS Detection (port=%d) returned %s' % (port, smbobj.os)) if smbobj.lanman.lower() != 'unknown': self.log("SMB DETECT: Adding lanman knowledge: %s" % smbobj.lanman) self.target.add_knowledge("Lanman", smbobj.lanman, 100) self.log("SMB DETECT: Adding domain knowledge: %s" % smbobj.domain) self.target.add_knowledge("SMBDomain", smbobj.domain, 100) self.log("SMB DETECT: Adding server knowledge: %s" % smbobj.server) self.target.add_knowledge("SMBServer", smbobj.server, 100) break # check native OS, assume Linux for SAMBA if 'UNIX' in smbobj.os.upper(): #When you assume... #if 'SAMBA' in smbobj.lanman.upper(): # self.log("SMB DETECT: found Unix SAMBA, assuming Linux OS") # result = canvasos.new("Linux") if 'SUSE' in smbobj.lanman.upper(): result = canvasos.new("Linux") result.version = "SuSE" # Windows SMB muck elif 'VISTA' in smbobj.os.upper(): result = canvasos.new('Windows') result.version = 'Vista' for subversion in ['Ultimate']: if smbobj.os.find(subversion) != -1: result.family = subversion elif 'LAN MANAGER 4.0' in smbobj.os.upper(): result = canvasos.new('Windows') result.version = 'NT 4.0' elif 'WINDOWS' in smbobj.os.upper(): result = canvasos.new('Windows') if smbobj.os.find('Windows 5.0') != -1: result.version = '2000' elif smbobj.os.find('Windows 5.1') != -1: result.version = 'XP' elif smbobj.os.find('Windows .NET 5.2') != -1: result.version = '.NET RC2' elif smbobj.os.find('Windows NT 4.0') != -1: result.version = 'NT' elif smbobj.os.find('Windows 4.0') != -1: result.version = '9x' elif smbobj.os.find('Windows Server 2003') != -1: result.version = '2003' if smbobj.os.find('Service Pack 1') != -1: result.servicepack.append('SP1') elif smbobj.os.find('Service Pack 2') != -1: result.servicepack.append('SP2') else: result.servicepack.append('SP0') return result
def run_on_host(self,target): """ runs once on each host that is alive in the netrange """ if self.state==self.HALT: self.log("Not running on target %s, halted"%target.interface) return 0 host=target.interface self.report.newhost(target) self.log("Running on %s"%host) self.setInfo("Running on %s"%host) # Do a traceroute for the reporting if self.traceroute == True: try: app=self.engine.getModuleExploit("traceroute") app.link(self) app.target=target ret=app.run() if ret: app.setProgress(100) else: app.setProgress(-1) mytrace=app.result except: import traceback traceback.print_exc(file=sys.__stdout__) self.log("No traceroute") tracelist = target.get_knowledge("TraceList", None) if tracelist: self.report.note(target, "%s"%str(tracelist)) else: self.log("Traceroute set to off, proceding") try: app=self.engine.getModuleExploit("osdetect") app.link(self) app.target=target ret=app.run() if ret: app.setProgress(100) else: app.setProgress(-1) myos=app.result except: import traceback traceback.print_exc(file=sys.__stdout__) self.log("Not determining OS - use osdetect exploit module") myos=canvasos.new("Unknown") target.add_knowledge("OS", myos,100) if self.portscan: results=self.exploitnodes("portscan",target=target, args={"mode" : "portrange", "portlow": self.portlow, "porthigh": self.porthigh}) results=results[0] else: results=[] self.log("Portscan not requested by user") try: basename=myos.basename() except: #if it's a string, take the first word #it should NOT be a string. So fix this too. devlog("osdetect", "Bug in osdetect that returned %s"%myos) basename=str(myos).split(" ")[0] self.log("Base OS for ip %s: %s"%(target.interface,basename)) self.log("Open ports on host %s: %s"%(target.interface,results)) if "Windows" in basename: if 88 in results: self.report.note(target,"This host appears to be a domain controller (kerberos is available)") if 3389 in results: self.report.note(target,"This host is likely managed by Term Services") #sometimes Unix has this too...(think samba) lanman=target.get_knowledge("Lanman",None) smbdomain=target.get_knowledge("SMBDomain",None) smbserver=target.get_knowledge("SMBServer",None) shareenum=target.get_knowledge("SMBShares",None) if lanman: self.report.note(target,"%s"%str(lanman)) if smbdomain: self.report.note(target,"%s"%str(smbdomain)) if smbserver: self.report.note(target,"%s"%str(smbserver)) if shareenum: text=shareenum.get_all_text() devlog("hostKnowledge", "Share Text: %s"%text) self.report.note(target,"%s"%prettyprint(text)) language=target.get_knowledge("Language", None) if language: self.report.note(target, "%s"%str(language)) #we also want a PrintProvider list printproviders=target.get_knowledge("PrintProviders",None) if printproviders: self.report.note(target,"%s"%prettyprint(printproviders.get_all_text())) if self.do_testhost: self.log("Running testhost against it") result=self.exploitnodes("testhost")[0] self.report.note(target,"Testhost returned: %s"%result) scanmodnames=file(os.path.join(canvas_resources_directory,"vulnassess.txt"),"rb").readlines() scanmodnames=map(str.strip,scanmodnames) scanmods = canvasengine.getModules(scanmodnames) #scanmods = canvasengine.exploitmodsGet() #exploitmods = [] #exploitmods=[] totalmods=len(scanmods) currentmod=1 self.log("Vulnerability assessment has %d modules loaded total"%totalmods) for module in scanmods: if self.state==self.HALT: self.log("Halted - not continuing scan") return 0 try: self.log("Property = %s Basename=%s"%(module.PROPERTY["ARCH"],basename)) found=0 for prop in module.PROPERTY["ARCH"]: if prop[0]==basename: found=1 if not found: continue except: #no property in module continue try: astr="Scanning with %s"%module.DESCRIPTION except: try: print "Could not find a description in %s"%module.NAME astr=module.NAME except: print "Error: Module has no name?" self.log(astr) #debug print astr progress=round((currentmod*100)/totalmods) #print "CurrentMod %d Total Modules: %d Progress %d"%(currentmod,totalmods,progress) self.setProgress(progress) currentmod+=1 try: app=module.theexploit() except: try: mystr="No theexploit class in module %s"%module.DESCRIPTION except: mystr="No theexploit class in module!" self.log(mystr) continue app.link(self) #set the defaults for exploits not using correct syntax defaultlist=["port","user","password","filename"] for i in defaultlist: if i in dir(app): #print "FOUND: %s"%i app.argsDict[i]=getattr(app,i) app.argsDict["passednodes"]=self.argsDict["passednodes"] defaultlist=["user","password","filename"] for i in defaultlist: if i in self.argsDict: app.argsDict[i]=self.argsDict[i] app.argsDict["netmask"]="32" app.target=target app.argsDict["autohack_state"]=self.autohack_state #print "ArgsDict=%s"%app.argsDict try: ret=app.run() if ret: app.setProgress(100) else: app.setProgress(-1) if app.result: result=app.result #convert these to a string if they are a list of objects like dcedump is if isinstance(result , list): result=map(str, result) self.report.note(target,"%s: %s"%(app.name,str(result))) except: self.log("Run returned exception: fix this.") import traceback traceback.print_exc(file=sys.stdout) return
host) except Exception, msg: self.log("FTP DETECT: Anonymous FTP login not allowed (%s)" % msg) postAuthBanner = "" # banner dict banners = {} defaults = {} ### FTP banner sigs and default logins go here # XXX: move this away from object dicts ... ! # APC PowerChutes banners['APC FTP'] = canvasos.new('Embedded') banners['APC FTP'].version = 'APC PowerChute' banners['DELLLASER'] = canvasos.new("Embedded") banners['DELLLASER'].version = "Dell Laser Printer" banners['RICOH Aficio'] = canvasos.new('Embedded') banners['RICOH Aficio'].version = "Ricoh Aficio Printer" banners['220 SAVIN SLP38c FTP server (1.83)'] = canvasos.new( 'Embedded') banners[ '220 SAVIN SLP38c FTP server (1.83)'].version = "220 SAVIN SLP38c FTP server (1.83)" banners['Hewlett-Packard FTP Print Server'] = canvasos.new('Embedded') banners[
def parse_results(self, results): """ Parse the results of ipfingerprint """ ret = "" if not results: self.log("Did not get a valid ipfingerprint.") return ret # Do we wanna move it to something like: # # OSDict = {} # # # populate heuristics dict ... # OSDict['AIX'] = { 'syn_ack_window' : [val1, val2, val3 ], 'start_ip_ttl' : [val1, val2] } # OSDict['Linux'] = { 'syn_ack_window' : [val1, val2, val3], 'start_ip_ttl' : [val1, val2] } # # for os in OSDict: # for window in OSDict[os]['syn_ack_window']: # if results.get('syn_ack_window') == window: # # match > ttl here # ret = canvasos.new(os) # if results.get("start_ip_ttl", -1) == -1 and results.get("syn_ack_window") == 8192: ret = canvasos.new("Embedded") elif results.get('start_ip_ttl', -1) > 200 and results.get( 'syn_ack_window', -1) == 16384: ret = canvasos.new('AIX') elif results.get("syn_ack_window") == 5840: ret = canvasos.new("Linux") elif results.get("start_ip_ttl", -1) >= 60 and results.get( "start_ip_ttl") <= 128 and results.get("icmp_error_quote_len"): """ Scan your gateway from a NAT'd VM, for example (this is a Linux host->Linux guest scan: Fri Apr 24 10:03:46 2009 ](192.168.103.2/32) Sending TCP ECN attempt to port 1025 from port 50208 [ Fri Apr 24 10:03:47 2009 ](192.168.103.2/32) Got tcp_ecn Reply back! [ Fri Apr 24 10:03:47 2009 ](192.168.103.2/32) Got result: {'syn_ack_window': 64240, 'tcp_ip_ttl': 128, 'tcp_ecn': 0} """ ret = canvasos.new("VMWare") ret.vm = "VMware" elif results.get("start_ip_ttl", -1) > 0 and results.get("start_ip_ttl") < 70: ret = canvasos.new("Linux") elif results.get("syn_ack_window") == 8192: ret = canvasos.new("Windows") elif results.get("syn_ack_window") == 16384 and results.get( "tcp_ip_ttl") > 64 and results.get("tcp_ecn") == 0: ret = canvasos.new("Windows") ret.version = "2003" #this is probably SP1 or SP2 (figure that out later) elif results.get("icmp_error_quote_len", -1) > 0 and results.get("icmp_error_quote_len") < 40: ret = canvasos.new("Embedded") elif results.get("tcp_ip_ttl", -1) > 0 and results.get("tcp_ip_ttl") > 120: ret = canvasos.new("Windows") elif results.get("syn_ack_window") == 16384 and results.get( "tcp_ip_ttl") <= 64 and results.get("tcp_ecn") == 0: #this is probably an openBSD machine ret = canvasos.new("BSD") ret.version = "OpenBSD" return ret
def parse_results(self, results): """ Parse the results of ipfingerprint """ ret = "" if not results: self.log("Cannot parse None as ipfingerprint") return ret # Do we wanna move it to something like: # # OSDict = {} # # # populate heuristics dict ... # OSDict['AIX'] = { 'syn_ack_window' : [val1, val2, val3 ], 'start_ip_ttl' : [val1, val2] } # OSDict['Linux'] = { 'syn_ack_window' : [val1, val2, val3], 'start_ip_ttl' : [val1, val2] } # # for os in OSDict: # for window in OSDict[os]['syn_ack_window']: # if results.get('syn_ack_window') == window: # # match > ttl here # ret = canvasos.new(os) # if results.get("start_ip_ttl", -1) == -1 and results.get("syn_ack_window") == 8192: ret = canvasos.new("Embedded") elif results.get('start_ip_ttl', -1) > 200 and results.get( 'syn_ack_window', -1) == 16384: ret = canvasos.new('AIX') elif results.get("syn_ack_window") == 5840: ret = canvasos.new("Linux") elif results.get("start_ip_ttl", -1) > 0 and results.get("start_ip_ttl") < 70: ret = canvasos.new("Linux") elif results.get("syn_ack_window") == 8192: ret = canvasos.new("Windows") elif results.get("syn_ack_window") == 16384 and results.get( "tcp_ip_ttl") > 64 and results.get("tcp_ecn") == 0: ret = canvasos.new("Windows") ret.version = "2003" #this is probably SP1 or SP2 (figure that out later) elif results.get("icmp_error_quote_len", -1) > 0 and results.get("icmp_error_quote_len") < 40: ret = canvasos.new("Embedded") elif results.get("tcp_ip_ttl", -1) > 0 and results.get("tcp_ip_ttl") > 120: ret = canvasos.new("Windows") elif results.get("syn_ack_window") == 16384 and results.get( "tcp_ip_ttl") <= 64 and results.get("tcp_ecn") == 0: #this is probably an openBSD machine ret = canvasos.new("BSD") ret.version = "OpenBSD" return ret