mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-27 19:04:15 +01:00
Added enumerators for capabilities, kernel exploits, and package managers
This commit is contained in:
parent
8dea0b61e8
commit
da591f9a22
@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import textwrap
|
||||
|
||||
import pwncat
|
||||
from pwncat.commands.base import CommandDefinition
|
||||
|
||||
|
||||
class Command(CommandDefinition):
|
||||
|
||||
PROG = "service"
|
||||
ARGS = {}
|
||||
|
||||
def run(self, args):
|
||||
with pwncat.victim.open("/tmp/pwncat", "w") as filp:
|
||||
filp.write(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
#!/usr/bin/env bash
|
||||
|
||||
while [ 1 ]; do
|
||||
echo "Running"
|
||||
sleep 3
|
||||
done
|
||||
|
||||
"""
|
||||
).lstrip()
|
||||
)
|
||||
pwncat.victim.env(["chmod", "777", "/tmp/pwncat"])
|
||||
|
||||
pwncat.victim.create_service(
|
||||
"pwncat", "test pwncat service", "/tmp/pwncat", "root", False
|
||||
).start()
|
53
pwncat/enumerate/capabilities.py
Normal file
53
pwncat/enumerate/capabilities.py
Normal file
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
import dataclasses
|
||||
from typing import Generator, List
|
||||
|
||||
from colorama import Fore
|
||||
|
||||
import pwncat
|
||||
from pwncat.enumerate import FactData
|
||||
|
||||
name = "pwncat.enumerate.capabilities"
|
||||
provides = "file.caps"
|
||||
per_user = True
|
||||
always_run = False
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class FileCapabilityData(FactData):
|
||||
|
||||
path: str
|
||||
""" The path to the file """
|
||||
caps: List[str]
|
||||
""" List of strings representing the capabilities (e.g. "cap_net_raw+ep") """
|
||||
|
||||
def __str__(self):
|
||||
line = f"{Fore.CYAN}{self.path}{Fore.RESET} -> ["
|
||||
line += ",".join(
|
||||
f"{Fore.BLUE if c != 'ep' else Fore.RED}{c}{Fore.RESET}" for c in self.caps
|
||||
)
|
||||
line += "]"
|
||||
return line
|
||||
|
||||
|
||||
def enumerate() -> Generator[FactData, None, None]:
|
||||
"""
|
||||
Enumerate executables with assigned capabilities
|
||||
|
||||
:return: generator of FileCapability data
|
||||
"""
|
||||
|
||||
if pwncat.victim.which("getcap") is None:
|
||||
return
|
||||
|
||||
with pwncat.victim.subprocess(f"getcap -r / 2>/dev/null", "r") as filp:
|
||||
for line in filp:
|
||||
line = line.strip().decode("utf-8")
|
||||
# I don't know why this would happen, but just in case
|
||||
if " = " not in line:
|
||||
continue
|
||||
|
||||
filename, caps = [x.strip() for x in line.split(" = ")]
|
||||
caps = caps.split(",")
|
||||
|
||||
yield FileCapabilityData(filename, caps)
|
1157
pwncat/enumerate/kernel-exploit.py
Normal file
1157
pwncat/enumerate/kernel-exploit.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@ from pwncat import util
|
||||
import pwncat
|
||||
|
||||
name = "pwncat.enumerate.system"
|
||||
provides = "system.version.kernel"
|
||||
provides = "system.kernel.version"
|
||||
per_user = False
|
||||
|
||||
|
||||
|
71
pwncat/enumerate/system/packages.py
Normal file
71
pwncat/enumerate/system/packages.py
Normal file
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
import dataclasses
|
||||
from typing import Generator, List
|
||||
|
||||
from colorama import Fore
|
||||
|
||||
import pwncat
|
||||
from pwncat.enumerate import FactData
|
||||
|
||||
name = "pwncat.enumerate.capabilities"
|
||||
provides = "system.packages"
|
||||
per_user = True
|
||||
always_run = False
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class PackageData(FactData):
|
||||
"""
|
||||
Information describing an installed package
|
||||
"""
|
||||
|
||||
name: str
|
||||
version: str
|
||||
|
||||
def __str__(self):
|
||||
line = f"{Fore.CYAN}{self.name}{Fore.RESET}"
|
||||
if self.version is not None:
|
||||
line += f" version {Fore.BLUE}{self.version}{Fore.RESET}"
|
||||
return line
|
||||
|
||||
|
||||
def enumerate() -> Generator[FactData, None, None]:
|
||||
"""
|
||||
Enumerate installed packages agnostic to the underlying package manager
|
||||
|
||||
:return: generator of package data
|
||||
"""
|
||||
|
||||
rpm = pwncat.victim.which("rpm")
|
||||
if rpm is not None:
|
||||
with pwncat.victim.subprocess(f"rpm -qa", "r") as filp:
|
||||
for line in filp:
|
||||
line = line.decode("utf-8").strip()
|
||||
if "-" in line:
|
||||
line = line.split("-")
|
||||
package = "-".join(line[:-1])
|
||||
version = line[-1]
|
||||
else:
|
||||
package = line
|
||||
version = None
|
||||
yield PackageData(package, version)
|
||||
|
||||
dpkg = pwncat.victim.which("dpkg")
|
||||
if dpkg is not None:
|
||||
with pwncat.victim.subprocess(f"dpkg -l", "r") as filp:
|
||||
line = ""
|
||||
try:
|
||||
while not line.startswith("+"):
|
||||
line = next(filp).strip().decode("utf-8")
|
||||
except StopIteration:
|
||||
line = None
|
||||
if line is not None:
|
||||
for line in filp:
|
||||
line = line.strip().decode("utf-8")
|
||||
line = [c for c in line.split(" ") if c != ""]
|
||||
# This shouldn't happen
|
||||
if len(line) < 3:
|
||||
continue
|
||||
package = line[1]
|
||||
version = line[2]
|
||||
yield PackageData(package, version)
|
@ -2,5 +2,8 @@
|
||||
This package contains privilege escalation methods based on enumeration facts.
|
||||
|
||||
This could be passwords that the enumeration module found, or private keys or
|
||||
anything else of use.
|
||||
anything else of use. This is just an organizational module. Nothing special
|
||||
happens here compared to other privesc modules. It just helps me keep the
|
||||
different methods straight.
|
||||
|
||||
"""
|
||||
|
@ -480,7 +480,7 @@ class Victim:
|
||||
f"pruning {Fore.RED}{name}{Fore.RESET} from busybox"
|
||||
)
|
||||
|
||||
util.success(f"pruned {len(provides)-len(new_provides)} setuid entries")
|
||||
util.success(f"pruned {len(provides) - len(new_provides)} setuid entries")
|
||||
provides = new_provides
|
||||
|
||||
# Let the class know we now have access to busybox
|
||||
|
Loading…
Reference in New Issue
Block a user