mirror of
https://github.com/Pennyw0rth/NetExec.git
synced 2026-11-07 09:26:01 -10:00
Merge pull request #1377 from Pennyw0rth/neff-add-nfs-cat
Add --cat argument for NFS
This commit is contained in:
2 files changed
+86
No files matched your search
@@ -1,3 +1,5 @@
|
||||
from io import BytesIO
|
||||
|
||||
from termcolor import colored
|
||||
from nxc.connection import connection
|
||||
from nxc.logger import NXCAdapter
|
||||
@@ -774,6 +776,89 @@ class nfs(connection):
|
||||
path = path.rsplit("/", 1)[0] # Remove the file from the path
|
||||
self.print_directory(content, path)
|
||||
|
||||
def cat(self):
|
||||
# Connect to NFS
|
||||
nfs_port = self.portmap.getport(NFS_PROGRAM, NFS_V3)
|
||||
self.nfs3 = NFSv3(self.host, nfs_port, self.args.nfs_timeout, self.auth)
|
||||
self.nfs3.connect()
|
||||
|
||||
# Remove leading or trailing slashes
|
||||
self.args.cat = self.args.cat.lstrip("/").rstrip("/")
|
||||
|
||||
# NORMAL LS CALL (without root escape)
|
||||
if self.args.share:
|
||||
mount_info = self.mount.mnt(self.args.share, self.auth)
|
||||
if mount_info["status"] != 0:
|
||||
self.logger.fail(f"Could not mount share {self.args.share}: {NFSSTAT3[mount_info['status']]}")
|
||||
return
|
||||
else:
|
||||
mount_fh = mount_info["mountinfo"]["fhandle"]
|
||||
elif self.root_escape:
|
||||
# Interestingly we don't actually have to mount the share if we already got the handle
|
||||
self.logger.success(f"Successful escape on share: {self.escape_share}")
|
||||
mount_fh = self.escape_fh
|
||||
else:
|
||||
self.logger.fail("No root escape possible, please specify a share")
|
||||
return
|
||||
|
||||
# We got a path to look up
|
||||
curr_fh = mount_fh
|
||||
is_file = False # If the last path is a file
|
||||
|
||||
# If ls is "" or "/" without filter we would get one item with [""]
|
||||
for sub_path in list(filter(None, self.args.cat.split("/"))):
|
||||
# Update UID and GID for the path
|
||||
self.update_auth(curr_fh)
|
||||
res = self.nfs3.lookup(curr_fh, sub_path, auth=self.auth)
|
||||
|
||||
if "resfail" in res and res["status"] == NFS3ERR_NOENT:
|
||||
self.logger.fail(f"Unknown path: {self.args.cat!r}")
|
||||
return
|
||||
elif "resfail" in res:
|
||||
self.logger.fail(f"Error on looking up path '{sub_path}': {NFSSTAT3[res['status']]}")
|
||||
return
|
||||
|
||||
curr_fh = res["resok"]["object"]["data"]
|
||||
|
||||
# If file then break and only display file
|
||||
if res["resok"]["obj_attributes"]["attributes"]["type"] == NF3REG:
|
||||
is_file = True
|
||||
break
|
||||
|
||||
# Update the UID and GID for the file/dir
|
||||
self.update_auth(curr_fh)
|
||||
|
||||
if not is_file:
|
||||
self.logger.fail(f"Path '{self.args.cat}' is not a file!")
|
||||
return
|
||||
|
||||
buf = BytesIO()
|
||||
# Handle files over the default chunk size of 1024 * 1024
|
||||
offset = 0
|
||||
eof = False
|
||||
while not eof:
|
||||
file_data = self.nfs3.read(curr_fh, offset, auth=self.auth)
|
||||
|
||||
if "resfail" in file_data:
|
||||
self.logger.fail(f"Failed to retrieve data for '{self.args.cat}': {NFSSTAT3[file_data['status']]}")
|
||||
return
|
||||
|
||||
else:
|
||||
# Get the data and append it to the total file data
|
||||
data = file_data["resok"]["data"]
|
||||
eof = file_data["resok"]["eof"]
|
||||
|
||||
# Update the offset to read the next chunk
|
||||
offset += len(data)
|
||||
# Write the file data to the local file
|
||||
buf.write(data)
|
||||
|
||||
try:
|
||||
for line in buf.getvalue().decode().splitlines():
|
||||
self.logger.highlight(line)
|
||||
except UnicodeDecodeError as e:
|
||||
self.logger.fail(f"File is not in UTF-8: {e}")
|
||||
|
||||
def print_directory(self, content, path):
|
||||
"""
|
||||
Highlight log the content of the directory provided by a READDIRPLUS call.
|
||||
|
||||
@@ -8,6 +8,7 @@ def proto_args(parser, parents):
|
||||
dgroup.add_argument("--shares", action="store_true", help="List NFS shares")
|
||||
dgroup.add_argument("--enum-shares", nargs="?", type=int, const=3, help="Authenticate and enumerate exposed shares recursively (default depth: %(const)s)")
|
||||
dgroup.add_argument("--ls", const="/", nargs="?", metavar="PATH", help="List files in the specified NFS share. Example: --ls /")
|
||||
dgroup.add_argument("--cat", metavar="FILE", help="Display the contents of an NFS file. Example: --cat /path/to/file")
|
||||
dgroup.add_argument("--get-file", nargs=2, metavar="FILE", help="Download remote NFS file. Example: --get-file remote_file local_file")
|
||||
dgroup.add_argument("--put-file", nargs=2, metavar="FILE", help="Upload remote NFS file with chmod 777 permissions to the specified folder. Example: --put-file local_file remote_file")
|
||||
dgroup.add_argument("--chmod", nargs=2, metavar=("PERMISSIONS", "FILE"), help="Change permissions of remote NFS file. Example: --chmod 777 /path/to/file")
|
||||
|
||||
Reference in new issue
Block a user