def enumerate(self, caps: Capability = Capability.ALL) -> List[Technique]: """ Find all techniques known at this time """ # Update the cache for the current user # self.find_suid() known_techniques = [] try: for suid in pwncat.victim.enumerate.iter("suid"): # Print status message util.progress(( f"enumerating suid binaries: " f"{Fore.CYAN}{os.path.basename(suid.data.path)}{Fore.RESET}" )) try: binary = pwncat.victim.gtfo.find_binary( suid.data.path, caps) except BinaryNotFound: continue for method in binary.iter_methods(suid.data.path, caps, Stream.ANY): known_techniques.append( Technique( suid.data.owner.name, self, method, method.cap, )) finally: util.erase_progress() return known_techniques
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]: """ Find all techniques known at this time """ # If we have ran this before, don't bother running it if self.ran_before or not (Capability.SHELL & capability): return [] # Carve out the version of screen version_output = pwncat.victim.run("screen -v").decode("utf-8").strip() match = re.search(r"(\d+\.\d+\.\d+)", version_output) if not match: raise PrivescError("could not gather screen version") # Knowing the version of screen, check if it is vulnerable... version_triplet = [int(x) for x in match.group().split(".")] if version_triplet[0] > 4: raise PrivescError("screen seemingly not vulnerable") if version_triplet[0] == 4 and version_triplet[1] > 5: raise PrivescError("screen seemingly not vulnerable") if ( version_triplet[0] == 4 and version_triplet[1] == 5 and version_triplet[2] >= 1 ): raise PrivescError("screen seemingly not vulnerable") # If screen is vulnerable, try the technique! techniques = [Technique("root", self, None, Capability.SHELL)] return techniques
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]: """ Enumerate capabilities for this method. :param capability: the requested capabilities :return: a list of techniques implemented by this method """ for fact in pwncat.victim.enumerate.iter("system.service"): if "ssh" in fact.data.name and fact.data.state == "running": break else: raise PrivescError("no sshd service running") # We only provide shell capability if Capability.SHELL not in capability: return [] techniques = [] for fact in pwncat.victim.enumerate.iter(typ="system.user.private_key"): util.progress(f"enumerating private key facts: {str(fact.data)}") if not fact.data.encrypted: techniques.append( Technique(fact.data.user.name, self, fact.data, Capability.SHELL) ) return techniques
def enumerate(self, progress, task, capability=Capability.ALL) -> List[Technique]: current_user = pwncat.victim.whoami() for user, info in pwncat.victim.users.items(): progress.update(task, step=str(user)) if user == current_user: continue if info.password is not None or current_user == "root": yield Technique( user=user, method=self, ident=info.password, capabilities=Capability.SHELL, )
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]: """ Enumerate capabilities for this method. :param capability: the requested capabilities :return: a list of techniques implemented by this method """ # We only provide shell capability if Capability.SHELL not in capability: return [] seen_password = [] techniques = [] for fact in pwncat.victim.enumerate.iter(typ="configuration.password"): util.progress(f"enumerating password facts: {str(fact.data)}") if fact.data.value is None: continue if fact.data.value in seen_password: continue if len(fact.data.value) < 6: continue if len(fact.data.value.split(" ")) > 3: continue for _, user in pwncat.victim.users.items(): # This password was already tried for this user and failed if user.name in fact.data.invalid: continue # We already know the password for this user if user.password is not None: continue if ( user.id == 0 and user.name != pwncat.victim.config["backdoor_user"] ) or user.id >= 1000: techniques.append( Technique(user.name, self, fact, Capability.SHELL) ) seen_password.append(fact.data.value) util.erase_progress() return techniques
def enumerate( self, progress, task, capability: int = Capability.ALL ) -> List[Technique]: """ Enumerate capabilities for this method. :param capability: the requested capabilities :return: a list of techniques implemented by this method """ # We only provide shell capability if Capability.SHELL not in capability: return for fact in pwncat.victim.enumerate.iter(typ="system.user.password"): progress.update(task, step=str(fact.data)) yield Technique(fact.data.user.name, self, fact.data, Capability.SHELL)
def enumerate(self, capability=Capability.ALL) -> List[Technique]: result = [] current_user = pwncat.victim.whoami() for user, info in pwncat.victim.users.items(): if user == current_user: continue if info.password is not None or current_user == "root": result.append( Technique( user=user, method=self, ident=info.password, capabilities=Capability.SHELL, )) return result
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]: """ Find all techniques known at this time """ # If we have ran this before, don't bother running it if Capability.SHELL not in capability: return [] # Grab all possibly vulnerable screen version # It has to be SUID for this to work. facts = [ f for f in pwncat.victim.enumerate("screen-version") if f.data.vulnerable and f.data.perms & 0o4000 ] # Make a list of techniques to return techniques: List[Technique] = [] for fact in facts: # Carve out the version of screen version_output = (pwncat.victim.run(f"{fact.data.path} -v").decode( "utf-8").strip()) match = re.search(r"(\d+\.\d+\.\d+)", version_output) if not match: continue # We know the version of screen, check if it is vulnerable... version_triplet = [int(x) for x in match.group().split(".")] if version_triplet[0] > 4: continue if version_triplet[0] == 4 and version_triplet[1] > 5: continue if (version_triplet[0] == 4 and version_triplet[1] == 5 and version_triplet[2] >= 1): continue # This may work! techniques.append(Technique("root", self, fact, Capability.SHELL)) return techniques
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]: """ Find all techniques known at this time """ rules = [] for fact in pwncat.victim.enumerate("sudo"): util.progress(f"enumerating sudo rules: {fact.data}") # Doesn't appear to be a user specification if not fact.data.matched: continue # This specifies a user that is not us if (fact.data.user != "ALL" and fact.data.user != pwncat.victim.current_user.name and fact.data.group is None): continue # Check if we are part of the specified group if fact.data.group is not None: for group in pwncat.victim.current_user.groups: if fact.data.group == group.name: break else: # Non of our secondary groups match, was our primary group specified? if fact.data.group != pwncat.victim.current_user.group.name: continue # The rule appears to match, add it to the list rules.append(fact.data) # We don't need that progress after this is complete util.erase_progress() techniques = [] for rule in rules: for method in pwncat.victim.gtfo.iter_sudo(rule.command, caps=capability): user = "******" if rule.runas_user == "ALL" else rule.runas_user techniques.append( Technique(user, self, (method, rule), method.cap)) return techniques
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]: """ Enumerate capabilities for this method. :param capability: the requested capabilities :return: a list of techniques implemented by this method """ # We only provide shell capability if Capability.SHELL not in capability: return [] techniques = [] for fact in pwncat.victim.enumerate.iter(typ="system.user.password"): util.progress(f"enumerating password facts: {str(fact.data)}") techniques.append( Technique(fact.data.user.name, self, fact.data, Capability.SHELL)) util.erase_progress() return techniques
def enumerate( self, progress, task, capability: int = Capability.ALL ) -> List[Technique]: """ Find all techniques known at this time """ rules = [] for fact in pwncat.victim.enumerate("sudo"): progress.update(task, step=str(fact.data)) # Doesn't appear to be a user specification if not fact.data.matched: continue # This specifies a user that is not us if ( fact.data.user != "ALL" and fact.data.user != pwncat.victim.current_user.name and fact.data.group is None ): continue # Check if we are part of the specified group if fact.data.group is not None: for group in pwncat.victim.current_user.groups: if fact.data.group == group.name: break else: # Non of our secondary groups match, was our primary group specified? if fact.data.group != pwncat.victim.current_user.group.name: continue # The rule appears to match, add it to the list rules.append(fact.data) for rule in rules: for method in pwncat.victim.gtfo.iter_sudo(rule.command, caps=capability): progress.update(task, step=str(rule)) user = "******" if rule.runas_user == "ALL" else rule.runas_user yield Technique(user, self, (method, rule), method.cap)
def enumerate(self, progress, task, caps: Capability = Capability.ALL) -> List[Technique]: """ Find all techniques known at this time """ for suid in pwncat.victim.enumerate.iter("suid"): progress.update(task, step=str(suid.data)) try: binary = pwncat.victim.gtfo.find_binary(suid.data.path, caps) except BinaryNotFound: continue for method in binary.iter_methods(suid.data.path, caps, Stream.ANY): yield Technique( suid.data.owner.name, self, method, method.cap, )
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]: """ Find all techniques known at this time """ if self.ran_before or (Capability.SHELL & capability): return [] # Determine if this kernel version is vulnerable kernel = pwncat.victim.run("uname -r").decode("utf-8").strip() triplet = [int(x) for x in kernel.split(".")] if triplet[0] > 4: raise PrivescError("kernel seemingly not vulnerable") if triplet[0] == 4 and triplet[1] == 7 and triplet[2] >= 9: raise PrivescError("kernel seemingly not vulnerable") if triplet[0] == 4 and triplet[1] == 8 and triplet[2] >= 3: raise PrivescError("kernel seemingly not vulnerable") if triplet[0] == 4 and triplet[1] == 4 and triplet[2] >= 26: raise PrivescError("kernel seemingly not vulnerable") techniques = [Technique("root", self, None, Capability.SHELL)] return techniques
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]: """ Find all techniques known at this time """ sudo_rules = self.find_sudo() if not sudo_rules: return [] sudo_no_password = [] sudo_all_users = [] sudo_other_commands = [] for rule in sudo_rules: for commands in rule["commands"]: if commands["tags"] is None: command_split = commands["command"].split() run_as_user = command_split[0] tag = "" command = " ".join(command_split[1:]) if type(commands["tags"]) is list: tags_split = " ".join(commands["tags"]).split() if len(tags_split) == 1: command_split = commands["command"].split() run_as_user = command_split[0] tag = " ".join(tags_split) command = " ".join(command_split[1:]) else: run_as_user = tags_split[0] tag = " ".join(tags_split[1:]) command = commands["command"] if "NOPASSWD" in tag: sudo_no_password.append({ "run_as_user": run_as_user, "command": command, "password": False, }) if "ALL" in run_as_user: sudo_all_users.append({ "run_as_user": "******", "command": command, "password": True }) else: sudo_other_commands.append({ "run_as_user": run_as_user, "command": command, "password": True, }) current_user = pwncat.victim.current_user techniques = [] for sudo_privesc in [ *sudo_no_password, *sudo_all_users, *sudo_other_commands ]: if current_user.password is None and sudo_privesc["password"]: continue # Split the users on a comma users = sudo_privesc["run_as_user"].split(",") # We don't need to go anywhere else... if "ALL" in users: users = ["root"] for method in pwncat.victim.gtfo.iter_sudo(sudo_privesc["command"], caps=capability): for user in users: techniques.append( Technique( user, self, (method, sudo_privesc["command"], sudo_privesc["password"]), method.cap, )) pwncat.victim.flush_output() return techniques