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:
parent
3c381f5f1f
commit
591a1d1385
51
pwncat/enumerate/writable_path.py
Normal file
51
pwncat/enumerate/writable_path.py
Normal 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
|
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user