diff --git a/filemanager/views.py b/filemanager/views.py index 864ecc993..6e5b54149 100644 --- a/filemanager/views.py +++ b/filemanager/views.py @@ -306,13 +306,20 @@ def downloadFile(request): try: userID = request.session['userID'] admin = Administrator.objects.get(pk=userID) - from urllib.parse import quote - from django.utils.encoding import iri_to_uri + from urllib.parse import unquote + import os - fileToDownload = request.build_absolute_uri().split('fileToDownload')[1][1:] - fileToDownload = iri_to_uri(fileToDownload) + # Properly get fileToDownload from query parameters + fileToDownload = request.GET.get('fileToDownload') + if not fileToDownload: + return HttpResponse("Unauthorized access: Not a valid file.") + + # URL decode the file path + fileToDownload = unquote(fileToDownload) domainName = request.GET.get('domainName') + if not domainName: + return HttpResponse("Unauthorized access: Domain not specified.") currentACL = ACLManager.loadedACL(userID) @@ -323,8 +330,18 @@ def downloadFile(request): homePath = '/home/%s' % (domainName) - if fileToDownload.find('..') > -1 or fileToDownload.find(homePath) == -1: - return HttpResponse("Unauthorized access.") + # Security checks: prevent directory traversal and ensure file is within domain's home path + if '..' in fileToDownload or not fileToDownload.startswith(homePath): + return HttpResponse("Unauthorized access: Not a valid file.") + + # Normalize path to prevent any path traversal attempts + fileToDownload = os.path.normpath(fileToDownload) + if not fileToDownload.startswith(homePath): + return HttpResponse("Unauthorized access: Not a valid file.") + + # Verify file exists and is a file (not a directory) + if not os.path.exists(fileToDownload) or not os.path.isfile(fileToDownload): + return HttpResponse("Unauthorized access: Not a valid file.") response = HttpResponse(content_type='application/force-download') response['Content-Disposition'] = 'attachment; filename=%s' % (fileToDownload.split('/')[-1]) @@ -338,11 +355,16 @@ def downloadFile(request): def RootDownloadFile(request): try: userID = request.session['userID'] - from urllib.parse import quote - from django.utils.encoding import iri_to_uri + from urllib.parse import unquote + import os - fileToDownload = request.build_absolute_uri().split('fileToDownload')[1][1:] - fileToDownload = iri_to_uri(fileToDownload) + # Properly get fileToDownload from query parameters + fileToDownload = request.GET.get('fileToDownload') + if not fileToDownload: + return HttpResponse("Unauthorized access: Not a valid file.") + + # URL decode the file path + fileToDownload = unquote(fileToDownload) currentACL = ACLManager.loadedACL(userID) @@ -351,6 +373,17 @@ def RootDownloadFile(request): else: return ACLManager.loadError() + # Security checks: prevent directory traversal + if '..' in fileToDownload: + return HttpResponse("Unauthorized access: Not a valid file.") + + # Normalize path to prevent any path traversal attempts + fileToDownload = os.path.normpath(fileToDownload) + + # Verify file exists and is a file (not a directory) + if not os.path.exists(fileToDownload) or not os.path.isfile(fileToDownload): + return HttpResponse("Unauthorized access: Not a valid file.") + response = HttpResponse(content_type='application/force-download') response['Content-Disposition'] = 'attachment; filename=%s' % (fileToDownload.split('/')[-1]) response['X-LiteSpeed-Location'] = '%s' % (fileToDownload)