Skip to content

Commit

Permalink
🔒️ Close a sanity check hole in language packs
Browse files Browse the repository at this point in the history
A language pack containing a directory traversing
symlink could be uploaded. Upon backup creation, the
symlink would then lead to inclusion of whatever it
was pointing to in the resulting backup. This could
be used by an attacker with admin permissions to extract
information from the server.
  • Loading branch information
foosel committed Aug 31, 2022
1 parent ef95ef1 commit 3cca3a4
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions src/octoprint/server/api/languages.py
Expand Up @@ -174,7 +174,8 @@ def deleteInstalledLanguagePack(locale, pack):
def _unpack_uploaded_zipfile(path, target):
with zipfile.ZipFile(path, "r") as zip:
# sanity check
map(_validate_archive_name, zip.namelist())
for info in zip.infolist():
_validate_zip_info(info, target)

# unpack everything
zip.extractall(target)
Expand All @@ -183,16 +184,27 @@ def _unpack_uploaded_zipfile(path, target):
def _unpack_uploaded_tarball(path, target):
with tarfile.open(path, "r") as tar:
# sanity check
map(_validate_archive_name, tar.getmembers())
for info in tar.getmembers():
_validate_tar_info(info, target)

# unpack everything
tar.extractall(target)


def _validate_archive_name(name):
if name.startswith("/") or ".." in name:
def _validate_archive_name(name, target):
if not os.path.abspath(os.path.join(target, name)).startswith(target + os.path.sep):
raise InvalidLanguagePack(f"Provided language pack contains invalid name {name}")


def _validate_zip_info(info, target):
_validate_archive_name(info.filename, target)


def _validate_tar_info(info, target):
_validate_archive_name(info.name, target)
if not (info.isfile() or info.isdir()):
raise InvalidLanguagePack("Provided language pack contains invalid file type")


class InvalidLanguagePack(Exception):
pass

0 comments on commit 3cca3a4

Please sign in to comment.