Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions conf/default/distributed.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ submit_only = no
# Path will be $CAPE_ROOT/$nfs_mount_folder. Ex: /opt/CAPEv2/workers
mount_folder = workers
fstab_socket = /tmp/cape-fstab
# Optional comma-separated list of private CIDR subnets allowed for NFS mounts
# (e.g., 10.0.0.0/8, 192.168.1.0/24). When empty, any private network IP
# (ip_address.is_private, excluding loopback/link-local) is allowed.
# Note: When nfs = yes, POST /node rejects registration (HTTP 400) if the NFS
# host does not resolve to a private IP (or pass a separate private `nfs_host`
# in the POST /node payload if the node `url` uses a public hostname).
allowed_networks =

# Google Cloud Platform
[GCP]
Expand Down
45 changes: 34 additions & 11 deletions lib/cuckoo/common/integrations/pyinstxtractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,17 +227,19 @@ def parseTOC(self):
log.warning("[!] File name %s contains invalid bytes. Using random name %s", name, newName)
name = newName

while "%" in name:
for _ in range(10):
if "%" not in name:
break
new_name = urllib.parse.unquote(name)
if new_name == name:
break
name = new_name

# Prevent writing outside the extraction directory
if name.startswith("/"):
name = name.lstrip("/")
name = name.replace("\\", "/")
name = name.replace("..", "__")
name = name.replace("\0", "").replace("\\", "/")
name = name.replace("..", "__").lstrip("/")
parts = [p for p in name.split("/") if p and p not in (".", "..")]
name = "/".join(parts)

if len(name) == 0:
name = str(uniquename())
Expand Down Expand Up @@ -283,10 +285,11 @@ def extractFiles(self):
os.mkdir(extractionDir)

# os.chdir(extractionDir)
dest_root = os.path.realpath(self.destination_folder)

for entry in self.tocList:
destination_entry = os.path.abspath(os.path.join(self.destination_folder, entry.name))
if not destination_entry.startswith(os.path.abspath(self.destination_folder) + os.sep):
destination_entry = os.path.realpath(os.path.join(dest_root, entry.name))
if not destination_entry.startswith(dest_root + os.sep):
log.warning("[!] Path traversal attempt detected. Skipping %s", entry.name)
continue
self.fPtr.seek(entry.position, os.SEEK_SET)
Expand Down Expand Up @@ -323,7 +326,7 @@ def extractFiles(self):
# if we don't have the pyc header yet, fix them in a later pass
self.barePycList.append(final_filename)

elif entry.typeCmprsData == (b"M", b"m") and not self.only_entrypoints:
elif entry.typeCmprsData in (b"M", b"m") and not self.only_entrypoints:
# M -> ARCHIVE_ITEM_PYPACKAGE
# m -> ARCHIVE_ITEM_PYMODULE
# packages and modules are pyc files with their header intact
Expand Down Expand Up @@ -379,6 +382,7 @@ def _extractPyz(self, name):
# Create a directory for the contents of the pyz
if not os.path.exists(dirName):
os.mkdir(dirName)
dir_root = os.path.realpath(dirName)

with open(name, "rb") as f:
pyzMagic = f.read(4)
Expand Down Expand Up @@ -427,12 +431,31 @@ def _extractPyz(self, name):
# for Python > 3.3 some keys are bytes object some are str object
fileName = fileName.decode("utf-8")

# Prevent writing outside dirName
fileName = str(fileName).replace("\0", "")
for _ in range(10):
if "%" not in fileName:
break
new_name = urllib.parse.unquote(fileName)
if new_name == fileName:
break
fileName = new_name

# Prevent writing outside dirName (including leading '.', '/', or '\')
fileName = fileName.replace("\\", os.path.sep).replace("/", os.path.sep)
fileName = fileName.replace("..", "__").replace(".", os.path.sep)
parts = [p for p in fileName.split(os.path.sep) if p and p not in (".", "..")]
if not parts:
parts = [str(uniquename())]
safe_rel = os.path.join(*parts)

if ispkg == 1:
filePath = os.path.join(dirName, fileName, "__init__.pyc")
filePath = os.path.realpath(os.path.join(dir_root, safe_rel, "__init__.pyc"))
else:
filePath = os.path.join(dirName, fileName + ".pyc")
filePath = os.path.realpath(os.path.join(dir_root, safe_rel + ".pyc"))

if not filePath.startswith(dir_root + os.sep):
log.warning("[!] Path traversal attempt detected in PYZ archive. Skipping %s", key)
continue

fileDir = os.path.dirname(filePath)
if not os.path.exists(fileDir):
Expand Down
Empty file removed mcp/__init__.py
Empty file.
31 changes: 0 additions & 31 deletions mcp/filters.py

This file was deleted.

Loading
Loading