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:
parent
bb1a48d7ab
commit
5089fc2cc9
@ -231,6 +231,22 @@ class Command(CommandDefinition):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
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:
|
try:
|
||||||
# Grab init system
|
# Grab init system
|
||||||
init = pwncat.victim.enumerate.first("system.init").data
|
init = pwncat.victim.enumerate.first("system.init").data
|
||||||
@ -238,6 +254,13 @@ class Command(CommandDefinition):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
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
|
# Build the table writer for the main section
|
||||||
table_writer = MarkdownTableWriter()
|
table_writer = MarkdownTableWriter()
|
||||||
table_writer.headers = ["Property", "Value"]
|
table_writer.headers = ["Property", "Value"]
|
||||||
@ -256,12 +279,16 @@ class Command(CommandDefinition):
|
|||||||
"system.distro",
|
"system.distro",
|
||||||
"system.init",
|
"system.init",
|
||||||
"system.arch",
|
"system.arch",
|
||||||
|
"system.aslr",
|
||||||
|
"system.container",
|
||||||
]
|
]
|
||||||
|
|
||||||
# This is the list of known enumeration types that we want to
|
# This is the list of known enumeration types that we want to
|
||||||
# happen first in this order. Other types will still be output
|
# happen first in this order. Other types will still be output
|
||||||
# but will be output in an arbitrary order following this list
|
# but will be output in an arbitrary order following this list
|
||||||
ordered_types = [
|
ordered_types = [
|
||||||
|
# Sudo privileges
|
||||||
|
"sudo",
|
||||||
# Possible kernel exploits - very important
|
# Possible kernel exploits - very important
|
||||||
"system.kernel.exploit",
|
"system.kernel.exploit",
|
||||||
# Enumerated user passwords - very important
|
# Enumerated user passwords - very important
|
||||||
|
44
pwncat/enumerate/system/aslr.py
Normal file
44
pwncat/enumerate/system/aslr.py
Normal 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
|
52
pwncat/enumerate/system/container.py
Normal file
52
pwncat/enumerate/system/container.py
Normal 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
|
62
pwncat/enumerate/system/selinux.py
Normal file
62
pwncat/enumerate/system/selinux.py
Normal 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)
|
@ -1556,11 +1556,11 @@ class Victim:
|
|||||||
try:
|
try:
|
||||||
new = self.client.recv(4096)
|
new = self.client.recv(4096)
|
||||||
if len(new) == 0:
|
if len(new) == 0:
|
||||||
if len(output) > 0 or some == False:
|
if len(output) > 0 or some is False:
|
||||||
break
|
break
|
||||||
output += new
|
output += new
|
||||||
except (socket.timeout, BlockingIOError):
|
except (socket.timeout, BlockingIOError):
|
||||||
if len(output) > 0 or some == False:
|
if len(output) > 0 or some is False:
|
||||||
break
|
break
|
||||||
|
|
||||||
self.client.settimeout(old_timeout)
|
self.client.settimeout(old_timeout)
|
||||||
|
Loading…
Reference in New Issue
Block a user