|
1 | 1 | import json |
2 | 2 | import errno |
3 | | -from os.path import abspath, join, split, exists, splitext, getsize, sep |
| 3 | +from os.path import abspath, join, exists, splitext, getsize |
4 | 4 | from os import makedirs, remove, stat |
| 5 | +from pathlib import Path, PurePosixPath |
5 | 6 | import time |
6 | 7 | from nxc.helpers.misc import CATEGORY |
7 | 8 | from nxc.paths import NXC_PATH |
@@ -167,19 +168,15 @@ def read_chunk(self, remote_file, chunk_size=CHUNK_SIZE): |
167 | 168 | def get_file_save_path(self, remote_file): |
168 | 169 | r"""Processes the remote file path to extract the filename and the folder path where the file should be saved locally. |
169 | 170 |
|
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) |
172 | 172 | """ |
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 |
183 | 180 |
|
184 | 181 | def spider_shares(self): |
185 | 182 | """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