Skip to content
Open
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
8 changes: 8 additions & 0 deletions dojo/settings/settings.dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@
DD_SECRET_KEY=(str, ""),
DD_CREDENTIAL_AES_256_KEY=(str, "."),
DD_DATA_UPLOAD_MAX_MEMORY_SIZE=(int, 8388608), # Max post size set to 8mb
DD_MAX_ZIP_MEMBERS=(int, 1000),
DD_MAX_ZIP_MEMBER_SIZE=(int, 512 * 1024 * 1024), # 512 MB per member (uncompressed)
DD_MAX_ZIP_TOTAL_SIZE=(int, 1 * 1024 * 1024 * 1024), # 1 GB total (uncompressed)
DD_MAX_ZIP_RATIO=(int, 100), # max compression ratio (uncompressed / compressed)
DD_FORGOT_PASSWORD=(bool, True), # do we show link "I forgot my password" on login screen
DD_PASSWORD_RESET_TIMEOUT=(int, 259200), # 3 days, in seconds (the deafult)
DD_FORGOT_USERNAME=(bool, True), # do we show link "I forgot my username" on login screen
Expand Down Expand Up @@ -532,6 +536,10 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param
)

DATA_UPLOAD_MAX_MEMORY_SIZE = env("DD_DATA_UPLOAD_MAX_MEMORY_SIZE")
MAX_ZIP_MEMBERS = env("DD_MAX_ZIP_MEMBERS")
MAX_ZIP_MEMBER_SIZE = env("DD_MAX_ZIP_MEMBER_SIZE")
MAX_ZIP_TOTAL_SIZE = env("DD_MAX_ZIP_TOTAL_SIZE")
MAX_ZIP_RATIO = env("DD_MAX_ZIP_RATIO")

# ------------------------------------------------------------------------------
# URLS
Expand Down
24 changes: 10 additions & 14 deletions dojo/tools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@
import logging
import zipfile

logger = logging.getLogger(__name__)
from django.conf import settings

# Zip bomb protection limits
MAX_ZIP_MEMBERS = 1000
MAX_ZIP_MEMBER_SIZE = 512 * 1024 * 1024 # 512 MB per member (uncompressed)
MAX_ZIP_TOTAL_SIZE = 1 * 1024 * 1024 * 1024 # 1 GB total (uncompressed)
MAX_ZIP_RATIO = 100 # max compression ratio (uncompressed / compressed)
logger = logging.getLogger(__name__)


def safe_open_zip(file):
Expand All @@ -32,32 +28,32 @@ def safe_open_zip(file):

infos = zf.infolist()

if len(infos) > MAX_ZIP_MEMBERS:
if len(infos) > settings.MAX_ZIP_MEMBERS:
zf.close()
msg = f"Zip file contains {len(infos)} members, exceeding the limit of {MAX_ZIP_MEMBERS}."
msg = f"Zip file contains {len(infos)} members, exceeding the limit of {settings.MAX_ZIP_MEMBERS}."
raise ValueError(msg)

total_size = 0
for info in infos:
if info.file_size > MAX_ZIP_MEMBER_SIZE:
if info.file_size > settings.MAX_ZIP_MEMBER_SIZE:
zf.close()
msg = (
f"Zip member '{info.filename}' has uncompressed size {info.file_size} bytes, "
f"exceeding the per-member limit of {MAX_ZIP_MEMBER_SIZE} bytes."
f"exceeding the per-member limit of {settings.MAX_ZIP_MEMBER_SIZE} bytes."
)
raise ValueError(msg)
if info.compress_size > 0 and (info.file_size / info.compress_size) > MAX_ZIP_RATIO:
if info.compress_size > 0 and (info.file_size / info.compress_size) > settings.MAX_ZIP_RATIO:
zf.close()
ratio = info.file_size / info.compress_size
msg = (
f"Zip member '{info.filename}' has a compression ratio of "
f"{ratio:.1f}:1, exceeding the limit of {MAX_ZIP_RATIO}:1."
f"{ratio:.1f}:1, exceeding the limit of {settings.MAX_ZIP_RATIO}:1."
)
raise ValueError(msg)
total_size += info.file_size
if total_size > MAX_ZIP_TOTAL_SIZE:
if total_size > settings.MAX_ZIP_TOTAL_SIZE:
zf.close()
msg = f"Zip file total uncompressed size exceeds the limit of {MAX_ZIP_TOTAL_SIZE} bytes."
msg = f"Zip file total uncompressed size exceeds the limit of {settings.MAX_ZIP_TOTAL_SIZE} bytes."
raise ValueError(msg)

return zf
Expand Down
Loading