From 6847e198478d4c53026162f590cdf991199172da Mon Sep 17 00:00:00 2001 From: grossmj Date: Sun, 16 May 2021 14:44:38 +0930 Subject: [PATCH] Change method to prevent forbidden directory traversal. Fixes #1894 --- gns3server/handlers/api/compute/dynamips_vm_handler.py | 5 +++-- gns3server/handlers/api/compute/iou_handler.py | 5 +++-- gns3server/handlers/api/compute/qemu_handler.py | 5 +++-- gns3server/utils/path.py | 8 ++++---- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/gns3server/handlers/api/compute/dynamips_vm_handler.py b/gns3server/handlers/api/compute/dynamips_vm_handler.py index ac438423..378dc1dd 100644 --- a/gns3server/handlers/api/compute/dynamips_vm_handler.py +++ b/gns3server/handlers/api/compute/dynamips_vm_handler.py @@ -470,7 +470,8 @@ class DynamipsVMHandler: async def upload_image(request, response): dynamips_manager = Dynamips.instance() - await dynamips_manager.write_image(request.match_info["filename"], request.content) + filename = os.path.normpath(request.match_info["filename"]) + await dynamips_manager.write_image(filename, request.content) response.set_status(204) @Route.get( @@ -485,7 +486,7 @@ class DynamipsVMHandler: description="Download a Dynamips IOS image") async def download_image(request, response): - filename = request.match_info["filename"] + filename = os.path.normpath(request.match_info["filename"]) # Raise error if user try to escape if filename[0] == "." or os.path.sep in filename: diff --git a/gns3server/handlers/api/compute/iou_handler.py b/gns3server/handlers/api/compute/iou_handler.py index 9534b4f0..ad27201e 100644 --- a/gns3server/handlers/api/compute/iou_handler.py +++ b/gns3server/handlers/api/compute/iou_handler.py @@ -428,7 +428,8 @@ class IOUHandler: async def upload_image(request, response): iou_manager = IOU.instance() - await iou_manager.write_image(request.match_info["filename"], request.content) + filename = os.path.normpath(request.match_info["filename"]) + await iou_manager.write_image(filename, request.content) response.set_status(204) @@ -444,7 +445,7 @@ class IOUHandler: description="Download an IOU image") async def download_image(request, response): - filename = request.match_info["filename"] + filename = os.path.normpath(request.match_info["filename"]) # Raise error if user try to escape if filename[0] == "." or os.path.sep in filename: diff --git a/gns3server/handlers/api/compute/qemu_handler.py b/gns3server/handlers/api/compute/qemu_handler.py index 66decec3..d70e8a3f 100644 --- a/gns3server/handlers/api/compute/qemu_handler.py +++ b/gns3server/handlers/api/compute/qemu_handler.py @@ -552,7 +552,8 @@ class QEMUHandler: async def upload_image(request, response): qemu_manager = Qemu.instance() - await qemu_manager.write_image(request.match_info["filename"], request.content) + filename = os.path.normpath(request.match_info["filename"]) + await qemu_manager.write_image(filename, request.content) response.set_status(204) @Route.get( @@ -567,7 +568,7 @@ class QEMUHandler: description="Download Qemu image") async def download_image(request, response): - filename = request.match_info["filename"] + filename = os.path.normpath(request.match_info["filename"]) # Raise error if user try to escape if filename[0] == "." or os.path.sep in filename: diff --git a/gns3server/utils/path.py b/gns3server/utils/path.py index 943968da..e3360010 100644 --- a/gns3server/utils/path.py +++ b/gns3server/utils/path.py @@ -17,6 +17,7 @@ import os import aiohttp +from pathlib import Path from ..config import Config @@ -37,15 +38,14 @@ def get_default_project_directory(): return path -def is_safe_path(file_path, directory): +def is_safe_path(file_path: str, basedir: str) -> bool: """ Check that file path is safe. (the file is stored inside directory or one of its sub-directory) """ - requested_path = os.path.abspath(file_path) - common_prefix = os.path.commonprefix([requested_path, directory]) - return common_prefix != directory + test_path = (Path(basedir) / file_path).resolve() + return Path(basedir).resolve() in test_path.resolve().parents def check_path_allowed(path):