1
0
mirror of https://github.com/calebstewart/pwncat.git synced 2024-11-27 19:04:15 +01:00

Added aslr, container, and selinux enumeration

This commit is contained in:
Caleb Stewart 2020-05-31 00:40:54 -04:00
parent bb1a48d7ab
commit 5089fc2cc9
5 changed files with 188 additions and 3 deletions

View File

@ -231,6 +231,22 @@ class Command(CommandDefinition):
except ValueError:
pass
try:
# Grab SELinux State
selinux = pwncat.victim.enumerate.first("system.selinux").data
system_details.append(["SELinux", selinux.state])
except ValueError:
pass
try:
# Grab ASLR State
aslr = pwncat.victim.enumerate.first("system.aslr").data
system_details.append(
["ASLR", "DISABLED" if aslr.state == 0 else "ENABLED"]
)
except ValueError:
pass
try:
# Grab init system
init = pwncat.victim.enumerate.first("system.init").data
@ -238,6 +254,13 @@ class Command(CommandDefinition):
except ValueError:
pass
try:
# Check if we are in a container
container = pwncat.victim.enumerate.first("system.container").data
system_details.append(["Container", container.type])
except ValueError:
pass
# Build the table writer for the main section
table_writer = MarkdownTableWriter()
table_writer.headers = ["Property", "Value"]
@ -256,12 +279,16 @@ class Command(CommandDefinition):
"system.distro",
"system.init",
"system.arch",
"system.aslr",
"system.container",
]
# This is the list of known enumeration types that we want to
# happen first in this order. Other types will still be output
# but will be output in an arbitrary order following this list
ordered_types = [
# Sudo privileges
"sudo",
# Possible kernel exploits - very important
"system.kernel.exploit",
# Enumerated user passwords - very important

View File

@ -0,0 +1,44 @@
#!/usr/bin/env python3
import dataclasses
from typing import Generator
from colorama import Fore
import pwncat
from pwncat.enumerate import FactData
name = "pwncat.enumerate.system"
provides = "system.aslr"
per_user = False
@dataclasses.dataclass
class ASLRState(FactData):
state: int
""" the value of /proc/sys/kernel/randomize_va_space """
def __str__(self):
if self.state == 0:
return f"ASLR is {Fore.GREEN}disabled{Fore.RESET}"
return f"ASLR is {Fore.RED}enabled{Fore.RESET}"
def enumerate() -> Generator[FactData, None, None]:
"""
Check if this system is inside a container
:return:
"""
try:
with pwncat.victim.open("/proc/sys/kernel/randomize_va_space", "r") as filp:
value = filp.read()
try:
value = int(value)
except ValueError:
value = None
if value is not None:
yield ASLRState(value)
except (FileNotFoundError, PermissionError):
pass

View File

@ -0,0 +1,52 @@
#!/usr/bin/env python3
import dataclasses
from typing import Generator
from colorama import Fore
import pwncat
from pwncat.enumerate import FactData
name = "pwncat.enumerate.system"
provides = "system.container"
per_user = False
@dataclasses.dataclass
class ContainerData(FactData):
type: str
""" what type of container? either docker or lxd """
def __str__(self):
return f"Running in a {Fore.YELLOW}{self.type}{Fore.RESET} container"
def enumerate() -> Generator[FactData, None, None]:
"""
Check if this system is inside a container
:return:
"""
try:
with pwncat.victim.open("/proc/self/cgroup", "r") as filp:
if "docker" in filp.read().lower():
yield ContainerData("docker")
return
except (FileNotFoundError, PermissionError):
pass
with pwncat.victim.subprocess(
f'find / -maxdepth 3 -name "*dockerenv*" -exec ls -la {{}} \\; 2>/dev/null', "r"
) as pipe:
if pipe.read().strip() != b"":
yield ContainerData("docker")
return
try:
with pwncat.victim.open("/proc/1/environ", "r") as filp:
if "container=lxc" in filp.read().lower():
yield ContainerData("lxc")
return
except (FileNotFoundError, PermissionError):
pass

View File

@ -0,0 +1,62 @@
#!/usr/bin/env python3
import dataclasses
from typing import Generator, Dict
from colorama import Fore
from pwncat.enumerate import FactData
import pwncat
name = "pwncat.enumerate.system"
provides = "system.selinux"
per_user = False
@dataclasses.dataclass
class SELinuxState(FactData):
state: str
status: Dict[str, str]
def __str__(self):
result = f"SELinux is "
if self.state == "enabled":
result += f"{Fore.RED}enabled{Fore.RESET}"
elif self.state == "disabled":
result += f"{Fore.GREEN}disabled{Fore.RESET}"
else:
result += f"{Fore.YELLOW}{self.state}{Fore.RESET}"
return result
@property
def description(self):
width = max(len(x) for x in self.status) + 1
return "\n".join(
f"{key+':':{width}} {value}" for key, value in self.status.items()
)
def enumerate() -> Generator[FactData, None, None]:
"""
Check for SELinux status/availability
"""
try:
output = pwncat.victim.env(["sestatus"]).strip().decode("utf-8")
except (FileNotFoundError, PermissionError):
return
status = {}
for line in output.split("\n"):
line = line.strip().replace("\t", " ")
values = " ".join([x for x in line.split(" ") if x != ""]).split(":")
key = values[0].rstrip(":").strip()
value = " ".join(values[1:])
status[key] = value.strip()
if "SELinux status" in status:
state = status["SELinux status"]
else:
state = "unknown"
yield SELinuxState(state, status)

View File

@ -483,7 +483,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
@ -1556,11 +1556,11 @@ class Victim:
try:
new = self.client.recv(4096)
if len(new) == 0:
if len(output) > 0 or some == False:
if len(output) > 0 or some is False:
break
output += new
except (socket.timeout, BlockingIOError):
if len(output) > 0 or some == False:
if len(output) > 0 or some is False:
break
self.client.settimeout(old_timeout)