Skip to content

Commit 7d027f2

Browse files
Merge pull request Pennyw0rth#1121 from Pennyw0rth/marshall_smb_spider_vuln_fix
Fix for arbitrary file write via smb_spider module
2 parents f363124 + 0e0cbe0 commit 7d027f2

1 file changed

Lines changed: 10 additions & 13 deletions

File tree

nxc/modules/spider_plus.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import json
22
import errno
3-
from os.path import abspath, join, split, exists, splitext, getsize, sep
3+
from os.path import abspath, join, exists, splitext, getsize
44
from os import makedirs, remove, stat
5+
from pathlib import Path, PurePosixPath
56
import time
67
from nxc.helpers.misc import CATEGORY
78
from nxc.paths import NXC_PATH
@@ -167,19 +168,15 @@ def read_chunk(self, remote_file, chunk_size=CHUNK_SIZE):
167168
def get_file_save_path(self, remote_file):
168169
r"""Processes the remote file path to extract the filename and the folder path where the file should be saved locally.
169170
170-
It converts forward slashes (/) and backslashes (\) in the remote file path to the appropriate path separator for the local file system.
171-
The folder path and filename are then obtained separately.
171+
Creates a PurePosixPath and replaces UNC parts, then cleans it of any path traversal (see issue #1120)
172172
"""
173-
# Remove the backslash before the remote host part and replace slashes with the appropriate path separator
174-
remote_file_path = str(remote_file)[2:].replace("/", sep).replace("\\", sep)
175-
176-
# Split the path to obtain the folder path and the filename
177-
folder, filename = split(remote_file_path)
178-
179-
# Join the output folder with the folder path to get the final local folder path
180-
folder = join(self.output_folder, folder)
181-
182-
return folder, filename
173+
self.logger.debug(f"Remote file: {remote_file}")
174+
raw_path = PurePosixPath(remote_file._RemoteFile__share, remote_file._RemoteFile__fileName.replace("\\", "/"))
175+
self.logger.debug(f"Raw path: {remote_file}")
176+
clean_parts = [p for p in raw_path.parts if p not in ("..", ".")]
177+
resolved = Path(self.output_folder).joinpath(self.host, *clean_parts)
178+
self.logger.debug(f"Resolved path: {resolved}")
179+
return str(resolved.parent), resolved.name
183180

184181
def spider_shares(self):
185182
"""Enumerates all available shares for the SMB connection, spiders through the readable shares, and saves the metadata of the shares to a JSON file"""

0 commit comments

Comments
 (0)