1
0
mirror of https://github.com/calebstewart/pwncat.git synced 2024-11-30 20:34:15 +01:00

Added enumerator for writable entries in PATH

This commit is contained in:
Caleb Stewart 2020-05-28 17:57:30 -04:00
parent 3c381f5f1f
commit 591a1d1385
2 changed files with 56 additions and 0 deletions

View File

@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""
Enumerate directories in your PATH which are writable. All paths which are generated
from this enumerator are either directly writable, or do not exist but are under a
path which you have write access to. If the directory returned from this enumerator
does not exist, a call to `mkdir -p {directory}` should succeed.
"""
import os
from typing import Generator
from pwncat.enumerate import FactData
import pwncat
from pwncat.util import Access
name = "pwncat.enumerate.writable_path"
provides = "writable_path"
per_user = False
always_run = False
def enumerate() -> Generator[FactData, None, None]:
"""
Enumerate directories in our PATH which are writable
:return:
"""
for path in pwncat.victim.getenv("PATH").split(":"):
access = pwncat.victim.access(path)
if (Access.DIRECTORY | Access.WRITE) in access:
yield path
elif (
Access.EXISTS not in access
and (Access.PARENT_EXIST | Access.PARENT_WRITE) in access
):
yield path
elif access == Access.NONE:
# This means the parent directory doesn't exist. Check up the chain to see if
# We can create this chain of directories
dirpath = os.path.dirname(path)
access = pwncat.victim.access(dirpath)
# Find the first item that either exists or it's parent does
while access == Access.NONE:
dirpath = os.path.dirname(dirpath)
access = pwncat.victim.access(dirpath)
# This item exists. Is it a directory and can we write to it?
if (Access.DIRECTORY | Access.WRITE) in access:
yield path
elif (
Access.PARENT_EXIST | Access.PARENT_WRITE
) in access and Access.EXISTS not in access:
yield path

View File

@ -152,6 +152,8 @@ class Victim:
# The current user. This is cached while at the `pwncat` prompt # The current user. This is cached while at the `pwncat` prompt
# and reloaded whenever returning from RAW mode. # and reloaded whenever returning from RAW mode.
self.cached_user: str = None self.cached_user: str = None
# The original value of the PATH environment variable
self.original_path: List[str] = None
def reconnect( def reconnect(
self, hostid: str, requested_method: str = None, requested_user: str = None self, hostid: str, requested_method: str = None, requested_user: str = None
@ -353,6 +355,9 @@ class Victim:
# Disable automatic margins, which fuck up the prompt # Disable automatic margins, which fuck up the prompt
self.run("tput rmam") self.run("tput rmam")
# Store the original path
self.original_path = self.getenv("PATH").split(":")
# Now that we have a stable connection, we can create our # Now that we have a stable connection, we can create our
# privesc finder object. # privesc finder object.
self.privesc = privesc.Finder() self.privesc = privesc.Finder()