mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-27 19:04: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
|
||||
# and reloaded whenever returning from RAW mode.
|
||||
self.cached_user: str = None
|
||||
# The original value of the PATH environment variable
|
||||
self.original_path: List[str] = None
|
||||
|
||||
def reconnect(
|
||||
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
|
||||
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
|
||||
# privesc finder object.
|
||||
self.privesc = privesc.Finder()
|
||||
|
Loading…
Reference in New Issue
Block a user