def getCVEList(self): """ Create a dictionary where we link CVE Numbers to CANVAS module instances """ self.log("Finding CVEs for all installed modules...") canvasengine.registerAllModules() exploitmods_old = canvasengine.exploitmodsGet(False) bunkList = [ "N/A", '', 'Unknown', 'Unkown', 'None', 'None/SilentlyPatched' ] cveDict = {} # {str(CVE-Num): module Instance} skipList = 0 for key in exploitmods_old.keys(): try: exploitmods_old[key].DOCUMENTATION["CVE Name"] if exploitmods_old[key].DOCUMENTATION[ "CVE Name"] not in bunkList and exploitmods_old[ key].PROPERTY['SITE'] == 'Remote': # If it has a legitimate CVE number and it is a remote cveDict[ exploitmods_old[key].DOCUMENTATION["CVE Name"]] = key except: skipList += 1 self.log( "Found %d remote exploit modules with CVEs, skipped %d non-applicable modules" % (len(cveDict), skipList)) return cveDict, exploitmods_old
def lpe_special_privs(self, node): exploit_list = [] exploit_modules = canvasengine.exploitmodsGet() get_token_privs = self.engine.getModuleExploit("get_token_info") get_token_privs.link(self) get_token_privs.argsDict["passednodes"] = [node] info_success = get_token_privs.run() if not info_success: logging.warning("Failed to obtain token privileges") return [] token_info = get_token_privs.privileges[node] for (token_type, privileges) in token_info.iteritems(): if token_type == "process": if privileges and privileges.get("SeImpersonatePrivilege"): logging.info("Process has SeImpersonatePrivilege") logging.info("Prioritizing configuration abusing seimpersonatepriv_lpe") # lpe = self.engine.getModuleExploit("seimpersonatepriv_lpe") lpe = exploit_modules["seimpersonatepriv_lpe"] exploit_list.append(lpe) return exploit_list
def build_autohack_list(self, ban_types=["DoS", "Tools", "Recon"]): """ Autogenerate the list of modules to include in autohack *If your exploit is unreliable then set the AUTOHACK_EXCLUDE key in its properties* """ self.autohack_dict = {} e_modules = canvasengine.exploitmodsGet() for exploit_mod in e_modules.values(): ##Are we a known class of stuff that should be excluded? if exploit_mod.PROPERTY["TYPE"] in ban_types: self.banned.append(exploit_mod.NAME.lower()) continue ##Have we declared that this shouldn't be included in the PROPERTY dict elif exploit_mod.PROPERTY.has_key("AUTOHACK_EXCLUDE"): self.banned.append(exploit_mod.NAME.lower()) continue ##Use this exploit in autohack else: self.autohack_dict[exploit_mod.NAME.lower()] = exploit_mod # self.log("Modules INCLUDED in autohack: %s"%(self.autohack_dict)) return
def get_client_sides( self ): useable_exploits = [] mod_list = canvasengine.exploitmodsGet() for mod in mod_list: try: if mod_list[mod].PROPERTY["SITE"] == "Clientside" and mod_list[mod].PROPERTY['DELIVERY'] == "HTTP": logging.debug("Added: %s" % mod_list[mod].NAME) useable_exploits.append( mod ) except: logging.warning("Skipped: %s" % mod_list[mod].NAME) return useable_exploits
def dialog_update(gtk, wTree): import gobject treemodel = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING) treeview = wTree.get_widget('treeview1') singleexploit = wTree.get_widget('singleexploit') # do not initialize twice if len(treeview.get_columns()) != 0: return useable_exploits = [] mod_list = canvasengine.exploitmodsGet() for mod in mod_list: try: if mod_list[mod].PROPERTY["SITE"] == "Clientside" and mod_list[mod].PROPERTY['DELIVERY'] == "HTTP": treemodel.append( None, [mod, mod_list[mod].DESCRIPTION] ) except: pass nameColumn = gtk.TreeViewColumn('Name') descrColumn = gtk.TreeViewColumn('Description') treeview.append_column(nameColumn) treeview.append_column(descrColumn) nameCell = gtk.CellRendererText() descrCell = gtk.CellRendererText() # add the cell to the tvcolumn and allow it to expand nameColumn.pack_start(nameCell, True) descrColumn.pack_start(descrCell, True) # set the cell "text" attribute to column 0 - retrieve text # from that column in treestore nameColumn.add_attribute(nameCell, 'text', 0) descrColumn.add_attribute(descrCell, 'text', 1) # make it searchable treeview.set_search_column(0) # Allow sorting on the column nameColumn.set_sort_column_id(0) treeview.set_headers_visible(True) treeview.set_model(treemodel) treeview.show() selection = treeview.get_selection() selection.connect('changed', on_selection_changed, singleexploit)
def get_linux_modules(exploitsOnly=False): #Returns a dictionary, dict[module_name] = module_instance. #If exploits want to be excluded, then exploitsOnly can be set. candidates = canvasengine.exploitmodsGet(True) output_list = dict() for candidate in candidates: candidate = candidates[candidate].mod for arch in candidate.PROPERTY['ARCH']: if 'Linux' in arch or 'Unix' in arch: if candidate.PROPERTY['SITE'].lower() == 'local': if not exploitsOnly or candidate.PROPERTY['TYPE'].lower( ) == 'exploit': output_list[candidate.__name__] = candidate return output_list
def exploit_list_win8(self): exploit_modules = canvasengine.exploitmodsGet() return [ exploit_modules['menu_confusion_lpe'], exploit_modules['tpminit_wbemcomn'], exploit_modules['ms16_111'], exploit_modules['ms16_032'], exploit_modules['ms15_102'], exploit_modules['unmarshal_to_system'], exploit_modules['atmfd_pool_buffer_underflow'], exploit_modules['ms14_040'], exploit_modules['ms15_051'], exploit_modules['menu_confusion_lpe'] ]
def get_windows_local_map(self): canvasengine.registerAllModules() exploit_modules = canvasengine.exploitmodsGet() patch_map = {} for (module_name, exploit_module) in exploit_modules.iteritems(): if hasattr(exploit_module, "PROPERTY"): if all(["local" in exploit_module.PROPERTY["SITE"].lower(), "exploit" in exploit_module.PROPERTY["TYPE"].lower()]): if "MS PATCHES" in exploit_module.PROPERTY: for patch in exploit_module.PROPERTY["MS PATCHES"]: patch_map[patch] = exploit_module return patch_map
def exploit_list_win10(self): exploit_modules = canvasengine.exploitmodsGet() return [ exploit_modules['smbghost_lpe'], exploit_modules['alpc_takeover_lpe'], exploit_modules['alpc_appxedge_lpe'], exploit_modules['error_reporting_lpe'], exploit_modules['sdclt_uac_bypass'], exploit_modules['unmarshal_to_system'], exploit_modules['ms16_032'], exploit_modules['setwindowfnid_lpe'], exploit_modules['special_lnk'], exploit_modules['dde_closehandle_lpe'], exploit_modules['ms16_111'], exploit_modules['tpminit_wbemcomn'], exploit_modules['ms16_135'], exploit_modules['menu_confusion_lpe'] ]
def getCVEList(self): """ Return a dict where {cve number : module name} """ canvasengine.registerAllModules() exploitmods_old = canvasengine.exploitmodsGet(False) bunkList = ["N/A", '', 'Unknown' , 'Unkown', 'None', 'None/SilentlyPatched'] cveDict = {} skipList = 0 for key in exploitmods_old.keys(): try: exploitmods_old[key].DOCUMENTATION["CVE Name"] if exploitmods_old[key].DOCUMENTATION["CVE Name"] not in bunkList: cveDict[exploitmods_old[key].DOCUMENTATION["CVE Name"]] = key except: skipList += 1 self.log_info("Found %d modules with CVEs, skipped %d" % (len(cveDict), skipList)) return cveDict
def get_blacklist(self, os_info): blacklist_map = {"Windows Server 2008": ["MS11-032", "MS11-054", # "win32k.sys bServerSideWindowProc", "atmfd", "MS10-048", "MS16-135", "ms14_025", "MS12-042", # this doesn't crash but it generates a /ton/ of output ], "Windows 10": ["alpc_tasksched_lpe"], "Windows Server 2012": ["MS16-111"], "Windows 8.1": ["MS16-111"], "Windows Server 2016": ["MS16-135"], "all": ["ms_ntvdm", "event_viewer_mscfile"], } blacklist_names = blacklist_map.get(os_info["os_name"],[]) + blacklist_map.get("all", []) exploit_modules = canvasengine.exploitmodsGet() blacklist_modules = [] for exploit_name in blacklist_names: blacklist_modules.append(exploit_modules[exploit_name]) return blacklist_modules
def run_on_host(self, target): """ runs once on each host that is alive in the netrange """ host = target.interface self.log("Running on %s" % host) exploitmods = canvasengine.exploitmodsGet() try: app = self.engine.getModuleExploit("osdetect") app.link(self) app.target = target app.run() myos = app.result except: import traceback traceback.print_exc(file=sys.__stdout__) self.log("Not determining OS - use osdetect exploit module") myos = "Unknown" target.add_knowledge("OS", myos, 100) totalmods = len(exploitmods) currentmod = 1 for module in exploitmods.values(): if self.state == self.HALT: self.log("Halted.") self.setInfo("%s - (halted)" % NAME) return 0 try: str = "Scanning with %s" % module.DESCRIPTION except: try: print "Could not find a description in %s" % module.NAME str = module.NAME except: print "Error: Module has no name?" self.log(str) #debug print str 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"] app.argsDict["autohack_state"] = self.autohack_state defaultlist = ["user", "password", "filename"] for i in defaultlist: if i in self.argsDict: app.argsDict[i] = self.argsDict[i] app.target = target #print "ArgsDict=%s"%app.argsDict try: if app.test(): self.log( "Module %s said host %s is potentially vulnerable" % (module.NAME, host)) self.vulns.append((host, module.NAME, module)) fromhost = "127.0.0.1" #hard coded for now #if self.engine: # self.engine.registerPotentialVuln(fromhost,host,module.__name__,module.DESCRIPTION) else: #import traceback #traceback.print_exc(file=sys.stdout) self.log( "Module %s said host %s is not potentially vulnerable" % (module.NAME, host)) except: self.log("Test 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 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