Skip to content

Commit

Permalink
Merge pull request #1476 from ii5mai1/fix/upload
Browse files Browse the repository at this point in the history
Fix for xss file upload vulnerability
  • Loading branch information
derneuere authored Nov 8, 2024
2 parents f213f4b + 32237dd commit c80e102
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
24 changes: 19 additions & 5 deletions api/views/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def check_permissions(self, request):
jwt = request.COOKIES.get("jwt")
if jwt is not None:
try:
AccessToken(jwt)
token=AccessToken(jwt)
except TokenError:
raise ChunkedUploadError(
status=http_status.HTTP_403_FORBIDDEN,
Expand All @@ -57,7 +57,7 @@ def check_permissions(self, request):
detail="Authentication credentials were not provided",
)
# To-Do: Check if file is allowed type
user = User.objects.filter(id=request.POST.get("user")).first()
user = User.objects.filter(id=token["user_id"]).first()
if not user or not user.is_authenticated:
raise ChunkedUploadError(
status=http_status.HTTP_403_FORBIDDEN,
Expand Down Expand Up @@ -88,7 +88,7 @@ def check_permissions(self, request):
jwt = request.COOKIES.get("jwt")
if jwt is not None:
try:
AccessToken(jwt)
token=AccessToken(jwt)
except TokenError:
raise ChunkedUploadError(
status=http_status.HTTP_403_FORBIDDEN,
Expand All @@ -99,15 +99,29 @@ def check_permissions(self, request):
status=http_status.HTTP_403_FORBIDDEN,
detail="Authentication credentials were not provided",
)
user = User.objects.filter(id=request.POST.get("user")).first()
user = User.objects.filter(id=token["user_id"]).first()
if not user or not user.is_authenticated:
raise ChunkedUploadError(
status=http_status.HTTP_403_FORBIDDEN,
detail="Authentication credentials were not provided",
)

def on_completion(self, uploaded_file, request):
user = User.objects.filter(id=request.POST.get("user")).first()
jwt = request.COOKIES.get("jwt")
if jwt is not None:
try:
token=AccessToken(jwt)
except TokenError:
raise ChunkedUploadError(
status=http_status.HTTP_403_FORBIDDEN,
detail="Authentication credentials were invalid",
)
else:
raise ChunkedUploadError(
status=http_status.HTTP_403_FORBIDDEN,
detail="Authentication credentials were not provided",
)
user = User.objects.filter(id=token["user_id"]).first()
# Sanitize file name
filename = get_valid_filename(request.POST.get("filename"))

Expand Down
13 changes: 8 additions & 5 deletions api/views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,6 @@ def get(self, request, path, fname, format=None):
photo = Photo.objects.get(image_hash=image_hash)
except Photo.DoesNotExist:
return HttpResponse(status=404)

if photo.main_file.path.startswith("/nextcloud_media/"):
internal_path = photo.main_file.path.replace(
"/nextcloud_media/", "/nextcloud_original/"
Expand All @@ -617,15 +616,16 @@ def get(self, request, path, fname, format=None):
else:
# If, for some reason, the file is in a weird place, handle that.
internal_path = None

internal_path = quote(internal_path)

# grant access if the requested photo is public
if photo.public:
response = HttpResponse()
mime = magic.Magic(mime=True)
filename = mime.from_file(photo.main_file.path)
response["Content-Type"] = filename
if photo.video:
response["Content-Type"] = filename
else:
response["Content-Type"] = "image/webp"
response["X-Accel-Redirect"] = internal_path
return response

Expand All @@ -647,7 +647,10 @@ def get(self, request, path, fname, format=None):
response = HttpResponse()
mime = magic.Magic(mime=True)
filename = mime.from_file(photo.main_file.path)
response["Content-Type"] = filename
if photo.video:
response["Content-Type"] = filename
else:
response["Content-Type"] = "image/webp"
response["Content-Disposition"] = 'inline; filename="{}"'.format(
photo.main_file.path.split("/")[-1]
)
Expand Down

0 comments on commit c80e102

Please sign in to comment.